blob: 1699340ae5d7fe9faa922cd855b42d36580de159 [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>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070072#include "platform_api.h"
73#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070074#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080075#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070077#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080078#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080079
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053080#ifdef DYNAMIC_LOG_ENABLED
81#include <log_xml_parser.h>
82#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
83#include <log_utils.h>
84#endif
85
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053087/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
88#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070090#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053091#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070093#define PROXY_OPEN_RETRY_COUNT 100
94#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080095
Mingming Yin08c7e312015-03-16 18:10:58 -070096#ifdef USE_LL_AS_PRIMARY_OUTPUT
97#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
98#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
99#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800100#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700101#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
102#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800103
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700104#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700105#define DEFAULT_VOIP_BUF_DURATION_MS 20
106#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
107#define DEFAULT_VOIP_SAMP_RATE 48000
108
109#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
110
111struct pcm_config default_pcm_config_voip_copp = {
112 .channels = 1,
113 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
114 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
115 .period_count = 2,
116 .format = PCM_FORMAT_S16_LE,
117};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700118
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700119static unsigned int configured_low_latency_capture_period_size =
120 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
121
Haynes Mathew George16081042017-05-31 17:16:49 -0700122#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
123#define MMAP_PERIOD_COUNT_MIN 32
124#define MMAP_PERIOD_COUNT_MAX 512
125#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
126
Eric Laurentb23d5282013-05-14 15:27:20 -0700127struct pcm_config pcm_config_deep_buffer = {
128 .channels = 2,
129 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
130 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
131 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
132 .format = PCM_FORMAT_S16_LE,
133 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
134 .stop_threshold = INT_MAX,
135 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
136};
137
138struct pcm_config pcm_config_low_latency = {
139 .channels = 2,
140 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
141 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
142 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
145 .stop_threshold = INT_MAX,
146 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
147};
148
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700149static int af_period_multiplier = 4;
150struct pcm_config pcm_config_rt = {
151 .channels = 2,
152 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
153 .period_size = ULL_PERIOD_SIZE, //1 ms
154 .period_count = 512, //=> buffer size is 512ms
155 .format = PCM_FORMAT_S16_LE,
156 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
157 .stop_threshold = INT_MAX,
158 .silence_threshold = 0,
159 .silence_size = 0,
160 .avail_min = ULL_PERIOD_SIZE, //1 ms
161};
162
Eric Laurentb23d5282013-05-14 15:27:20 -0700163struct pcm_config pcm_config_hdmi_multi = {
164 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
165 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
166 .period_size = HDMI_MULTI_PERIOD_SIZE,
167 .period_count = HDMI_MULTI_PERIOD_COUNT,
168 .format = PCM_FORMAT_S16_LE,
169 .start_threshold = 0,
170 .stop_threshold = INT_MAX,
171 .avail_min = 0,
172};
173
Haynes Mathew George16081042017-05-31 17:16:49 -0700174struct pcm_config pcm_config_mmap_playback = {
175 .channels = 2,
176 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
177 .period_size = MMAP_PERIOD_SIZE,
178 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
179 .format = PCM_FORMAT_S16_LE,
180 .start_threshold = MMAP_PERIOD_SIZE*8,
181 .stop_threshold = INT32_MAX,
182 .silence_threshold = 0,
183 .silence_size = 0,
184 .avail_min = MMAP_PERIOD_SIZE, //1 ms
185};
186
Eric Laurentb23d5282013-05-14 15:27:20 -0700187struct pcm_config pcm_config_audio_capture = {
188 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
190 .format = PCM_FORMAT_S16_LE,
191};
192
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700193struct pcm_config pcm_config_audio_capture_rt = {
194 .channels = 2,
195 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
196 .period_size = ULL_PERIOD_SIZE,
197 .period_count = 512,
198 .format = PCM_FORMAT_S16_LE,
199 .start_threshold = 0,
200 .stop_threshold = INT_MAX,
201 .silence_threshold = 0,
202 .silence_size = 0,
203 .avail_min = ULL_PERIOD_SIZE, //1 ms
204};
205
Haynes Mathew George16081042017-05-31 17:16:49 -0700206struct pcm_config pcm_config_mmap_capture = {
207 .channels = 2,
208 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
209 .period_size = MMAP_PERIOD_SIZE,
210 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
211 .format = PCM_FORMAT_S16_LE,
212 .start_threshold = 0,
213 .stop_threshold = INT_MAX,
214 .silence_threshold = 0,
215 .silence_size = 0,
216 .avail_min = MMAP_PERIOD_SIZE, //1 ms
217};
218
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700219#define AFE_PROXY_CHANNEL_COUNT 2
220#define AFE_PROXY_SAMPLING_RATE 48000
221
222#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
223#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
224
225struct pcm_config pcm_config_afe_proxy_playback = {
226 .channels = AFE_PROXY_CHANNEL_COUNT,
227 .rate = AFE_PROXY_SAMPLING_RATE,
228 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
229 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
232 .stop_threshold = INT_MAX,
233 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
234};
235
236#define AFE_PROXY_RECORD_PERIOD_SIZE 768
237#define AFE_PROXY_RECORD_PERIOD_COUNT 4
238
239struct pcm_config pcm_config_afe_proxy_record = {
240 .channels = AFE_PROXY_CHANNEL_COUNT,
241 .rate = AFE_PROXY_SAMPLING_RATE,
242 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
243 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
244 .format = PCM_FORMAT_S16_LE,
245 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
246 .stop_threshold = INT_MAX,
247 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
248};
249
Ashish Jainf1eaa582016-05-23 20:54:24 +0530250#define AUDIO_MAX_PCM_FORMATS 7
251
252const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
253 [AUDIO_FORMAT_DEFAULT] = 0,
254 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
255 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
256 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
257 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
258 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
259 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
260};
261
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800262const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700263 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
264 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700265 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
266 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700267 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700268 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700269 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
270 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
271 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
272 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
273 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
274 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
275 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
276 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700277 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
278 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700279
Eric Laurentb23d5282013-05-14 15:27:20 -0700280 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700281 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530282 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
283 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
284 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700285 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700286 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700287 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
288
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800289 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800290 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700291 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700292
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700293 [USECASE_VOICE2_CALL] = "voice2-call",
294 [USECASE_VOLTE_CALL] = "volte-call",
295 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800296 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800297 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
298 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800299 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700300 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
301 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
302 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800303 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
304 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
305 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
306
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700307 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
308 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700309 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
310 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700311
312 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
313 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700314 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700315
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530316 /* Transcode loopback cases */
317 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700318
319 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
320 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530321 /* For Interactive Audio Streams */
322 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
323 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
324 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
325 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
326 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
327 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
328 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
329 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700330
331 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture"
Eric Laurentb23d5282013-05-14 15:27:20 -0700332};
333
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700334static const audio_usecase_t offload_usecases[] = {
335 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700336 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
337 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
338 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
339 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
340 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
341 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
342 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
343 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700344};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800345
Varun Balaraje49253e2017-07-06 19:48:56 +0530346static const audio_usecase_t interactive_usecases[] = {
347 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
348 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
349 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
350 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
351 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
352 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
353 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
354 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
355};
356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800357#define STRING_TO_ENUM(string) { #string, string }
358
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800359struct string_to_enum {
360 const char *name;
361 uint32_t value;
362};
363
364static const struct string_to_enum out_channels_name_to_enum_table[] = {
365 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800366 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
367 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
368 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700369 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800370 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
371 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800372 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
373};
374
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700375static const struct string_to_enum out_formats_name_to_enum_table[] = {
376 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
377 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
378 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700379 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800380 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
381 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700382 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800383};
384
385//list of all supported sample rates by HDMI specification.
386static const int out_hdmi_sample_rates[] = {
387 32000, 44100, 48000, 88200, 96000, 176400, 192000,
388};
389
390static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
391 STRING_TO_ENUM(32000),
392 STRING_TO_ENUM(44100),
393 STRING_TO_ENUM(48000),
394 STRING_TO_ENUM(88200),
395 STRING_TO_ENUM(96000),
396 STRING_TO_ENUM(176400),
397 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700398};
399
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700400static struct audio_device *adev = NULL;
401static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700402static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700403//cache last MBDRC cal step level
404static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700405
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530406static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
407static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800408static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530409
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700410static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
411 int flags __unused)
412{
413 int dir = 0;
414 switch (uc_id) {
415 case USECASE_AUDIO_RECORD_LOW_LATENCY:
416 dir = 1;
417 case USECASE_AUDIO_PLAYBACK_ULL:
418 break;
419 default:
420 return false;
421 }
422
423 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
424 PCM_PLAYBACK : PCM_CAPTURE);
425 if (adev->adm_is_noirq_avail)
426 return adev->adm_is_noirq_avail(adev->adm_data,
427 adev->snd_card, dev_id, dir);
428 return false;
429}
430
431static void register_out_stream(struct stream_out *out)
432{
433 struct audio_device *adev = out->dev;
434 if (is_offload_usecase(out->usecase) ||
435 !adev->adm_register_output_stream)
436 return;
437
438 // register stream first for backward compatibility
439 adev->adm_register_output_stream(adev->adm_data,
440 out->handle,
441 out->flags);
442
443 if (!adev->adm_set_config)
444 return;
445
446 if (out->realtime)
447 adev->adm_set_config(adev->adm_data,
448 out->handle,
449 out->pcm, &out->config);
450}
451
452static void register_in_stream(struct stream_in *in)
453{
454 struct audio_device *adev = in->dev;
455 if (!adev->adm_register_input_stream)
456 return;
457
458 adev->adm_register_input_stream(adev->adm_data,
459 in->capture_handle,
460 in->flags);
461
462 if (!adev->adm_set_config)
463 return;
464
465 if (in->realtime)
466 adev->adm_set_config(adev->adm_data,
467 in->capture_handle,
468 in->pcm,
469 &in->config);
470}
471
472static void request_out_focus(struct stream_out *out, long ns)
473{
474 struct audio_device *adev = out->dev;
475
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700476 if (adev->adm_request_focus_v2)
477 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
478 else if (adev->adm_request_focus)
479 adev->adm_request_focus(adev->adm_data, out->handle);
480}
481
482static void request_in_focus(struct stream_in *in, long ns)
483{
484 struct audio_device *adev = in->dev;
485
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700486 if (adev->adm_request_focus_v2)
487 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
488 else if (adev->adm_request_focus)
489 adev->adm_request_focus(adev->adm_data, in->capture_handle);
490}
491
492static void release_out_focus(struct stream_out *out)
493{
494 struct audio_device *adev = out->dev;
495
496 if (adev->adm_abandon_focus)
497 adev->adm_abandon_focus(adev->adm_data, out->handle);
498}
499
500static void release_in_focus(struct stream_in *in)
501{
502 struct audio_device *adev = in->dev;
503 if (adev->adm_abandon_focus)
504 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
505}
506
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530507static int parse_snd_card_status(struct str_parms *parms, int *card,
508 card_status_t *status)
509{
510 char value[32]={0};
511 char state[32]={0};
512
513 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
514 if (ret < 0)
515 return -1;
516
517 // sscanf should be okay as value is of max length 32.
518 // same as sizeof state.
519 if (sscanf(value, "%d,%s", card, state) < 2)
520 return -1;
521
522 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
523 CARD_STATUS_OFFLINE;
524 return 0;
525}
526
vivek mehtaa76401a2015-04-24 14:12:15 -0700527__attribute__ ((visibility ("default")))
528bool audio_hw_send_gain_dep_calibration(int level) {
529 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700530 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700531
532 pthread_mutex_lock(&adev_init_lock);
533
534 if (adev != NULL && adev->platform != NULL) {
535 pthread_mutex_lock(&adev->lock);
536 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700537
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530538 // cache level info for any of the use case which
539 // was not started.
540 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700541
vivek mehtaa76401a2015-04-24 14:12:15 -0700542 pthread_mutex_unlock(&adev->lock);
543 } else {
544 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
545 }
546
547 pthread_mutex_unlock(&adev_init_lock);
548
549 return ret_val;
550}
551
Ashish Jain5106d362016-05-11 19:23:33 +0530552static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
553{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800554 bool gapless_enabled = false;
555 const char *mixer_ctl_name = "Compress Gapless Playback";
556 struct mixer_ctl *ctl;
557
558 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700559 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530560
561 /*Disable gapless if its AV playback*/
562 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800563
564 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
565 if (!ctl) {
566 ALOGE("%s: Could not get ctl for mixer cmd - %s",
567 __func__, mixer_ctl_name);
568 return -EINVAL;
569 }
570
571 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
572 ALOGE("%s: Could not set gapless mode %d",
573 __func__, gapless_enabled);
574 return -EINVAL;
575 }
576 return 0;
577}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700578
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700579__attribute__ ((visibility ("default")))
580int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
581 int table_size) {
582 int ret_val = 0;
583 ALOGV("%s: enter ... ", __func__);
584
585 pthread_mutex_lock(&adev_init_lock);
586 if (adev == NULL) {
587 ALOGW("%s: adev is NULL .... ", __func__);
588 goto done;
589 }
590
591 pthread_mutex_lock(&adev->lock);
592 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
593 pthread_mutex_unlock(&adev->lock);
594done:
595 pthread_mutex_unlock(&adev_init_lock);
596 ALOGV("%s: exit ... ", __func__);
597 return ret_val;
598}
599
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700600static bool is_supported_format(audio_format_t format)
601{
Eric Laurent86e17132013-09-12 17:49:30 -0700602 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530603 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530604 format == AUDIO_FORMAT_AAC_LC ||
605 format == AUDIO_FORMAT_AAC_HE_V1 ||
606 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530607 format == AUDIO_FORMAT_AAC_ADTS_LC ||
608 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
609 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530610 format == AUDIO_FORMAT_AAC_LATM_LC ||
611 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
612 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530613 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
614 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530615 format == AUDIO_FORMAT_PCM_FLOAT ||
616 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700617 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530618 format == AUDIO_FORMAT_AC3 ||
619 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700620 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530621 format == AUDIO_FORMAT_DTS ||
622 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800623 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530624 format == AUDIO_FORMAT_ALAC ||
625 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530626 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530627 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800628 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530629 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700630 format == AUDIO_FORMAT_APTX ||
631 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800632 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700633
634 return false;
635}
636
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700637static inline bool is_mmap_usecase(audio_usecase_t uc_id)
638{
639 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
640 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
641}
642
Avinash Vaish71a8b972014-07-24 15:36:33 +0530643static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
644 struct audio_usecase *uc_info)
645{
646 struct listnode *node;
647 struct audio_usecase *usecase;
648
649 if (uc_info == NULL)
650 return -EINVAL;
651
652 /* Re-route all voice usecases on the shared backend other than the
653 specified usecase to new snd devices */
654 list_for_each(node, &adev->usecase_list) {
655 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800656 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530657 enable_audio_route(adev, usecase);
658 }
659 return 0;
660}
661
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530662static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530663{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530664 ALOGV("%s", __func__);
665 audio_route_apply_and_update_path(adev->audio_route,
666 "asrc-mode");
667 adev->asrc_mode_enabled = true;
668}
669
670static void disable_asrc_mode(struct audio_device *adev)
671{
672 ALOGV("%s", __func__);
673 audio_route_reset_and_update_path(adev->audio_route,
674 "asrc-mode");
675 adev->asrc_mode_enabled = false;
676}
677
678/*
679 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
680 * 44.1 or Native DSD backends are enabled for any of current use case.
681 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
682 * - Disable current mix path use case(Headphone backend) and re-enable it with
683 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
684 * e.g. Naitve DSD or Headphone 44.1 -> + 48
685 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530686static void check_and_set_asrc_mode(struct audio_device *adev,
687 struct audio_usecase *uc_info,
688 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530689{
690 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530691 int i, num_new_devices = 0;
692 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
693 /*
694 *Split snd device for new combo use case
695 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
696 */
697 if (platform_split_snd_device(adev->platform,
698 snd_device,
699 &num_new_devices,
700 split_new_snd_devices) == 0) {
701 for (i = 0; i < num_new_devices; i++)
702 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
703 } else {
704 int new_backend_idx = platform_get_backend_index(snd_device);
705 if (((new_backend_idx == HEADPHONE_BACKEND) ||
706 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
707 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
708 !adev->asrc_mode_enabled) {
709 struct listnode *node = NULL;
710 struct audio_usecase *uc = NULL;
711 struct stream_out *curr_out = NULL;
712 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
713 int i, num_devices, ret = 0;
714 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530715
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530716 list_for_each(node, &adev->usecase_list) {
717 uc = node_to_item(node, struct audio_usecase, list);
718 curr_out = (struct stream_out*) uc->stream.out;
719 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
720 /*
721 *Split snd device for existing combo use case
722 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
723 */
724 ret = platform_split_snd_device(adev->platform,
725 uc->out_snd_device,
726 &num_devices,
727 split_snd_devices);
728 if (ret < 0 || num_devices == 0) {
729 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
730 split_snd_devices[0] = uc->out_snd_device;
731 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800732 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530733 for (i = 0; i < num_devices; i++) {
734 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
735 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
736 if((new_backend_idx == HEADPHONE_BACKEND) &&
737 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
738 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
739 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
740 __func__);
741 enable_asrc_mode(adev);
742 break;
743 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
744 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
745 (usecase_backend_idx == HEADPHONE_BACKEND)) {
746 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
747 __func__);
748 disable_audio_route(adev, uc);
749 disable_snd_device(adev, uc->out_snd_device);
750 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
751 if (new_backend_idx == DSD_NATIVE_BACKEND)
752 audio_route_apply_and_update_path(adev->audio_route,
753 "hph-true-highquality-mode");
754 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
755 (curr_out->bit_width >= 24))
756 audio_route_apply_and_update_path(adev->audio_route,
757 "hph-highquality-mode");
758 enable_asrc_mode(adev);
759 enable_snd_device(adev, uc->out_snd_device);
760 enable_audio_route(adev, uc);
761 break;
762 }
763 }
764 // reset split devices count
765 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800766 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530767 if (adev->asrc_mode_enabled)
768 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530769 }
770 }
771 }
772}
773
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700774int pcm_ioctl(struct pcm *pcm, int request, ...)
775{
776 va_list ap;
777 void * arg;
778 int pcm_fd = *(int*)pcm;
779
780 va_start(ap, request);
781 arg = va_arg(ap, void *);
782 va_end(ap);
783
784 return ioctl(pcm_fd, request, arg);
785}
786
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700787int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700788 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800789{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700790 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700791 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530792 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800793
794 if (usecase == NULL)
795 return -EINVAL;
796
797 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
798
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800799 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700800 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800801 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700802 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800803
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800804#ifdef DS1_DOLBY_DAP_ENABLED
805 audio_extn_dolby_set_dmid(adev);
806 audio_extn_dolby_set_endpoint(adev);
807#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700808 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700809 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530810 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700811 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530812 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530813 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
814 out = usecase->stream.out;
815 if (out && out->compr)
816 audio_extn_utils_compress_set_clk_rec_mode(usecase);
817 }
818
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800819 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700820 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700821 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700822 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800823 ALOGV("%s: exit", __func__);
824 return 0;
825}
826
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700827int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700828 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800829{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700830 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700831 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800832
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530833 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800834 return -EINVAL;
835
836 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 if (usecase->type == PCM_CAPTURE)
838 snd_device = usecase->in_snd_device;
839 else
840 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800841 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700842 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700843 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700844 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700845 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530846 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800847 ALOGV("%s: exit", __func__);
848 return 0;
849}
850
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700851int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700852 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800853{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530854 int i, num_devices = 0;
855 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700856 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
857
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800858 if (snd_device < SND_DEVICE_MIN ||
859 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800860 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800861 return -EINVAL;
862 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700863
864 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700865
866 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
867 ALOGE("%s: Invalid sound device returned", __func__);
868 return -EINVAL;
869 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700871 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700872 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 return 0;
874 }
875
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530876
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700877 if (audio_extn_spkr_prot_is_enabled())
878 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700879
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800880 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
881 audio_extn_spkr_prot_is_enabled()) {
882 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700883 adev->snd_dev_ref_cnt[snd_device]--;
884 return -EINVAL;
885 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200886 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800887 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800888 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200889 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800890 return -EINVAL;
891 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700892 } else if (platform_split_snd_device(adev->platform,
893 snd_device,
894 &num_devices,
895 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530896 for (i = 0; i < num_devices; i++) {
897 enable_snd_device(adev, new_snd_devices[i]);
898 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800899 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700900 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530901
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530902
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530903 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
904 (audio_extn_a2dp_start_playback() < 0)) {
905 ALOGE(" fail to configure A2dp control path ");
906 return -EINVAL;
907 }
908
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700909 /* due to the possibility of calibration overwrite between listen
910 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700911 audio_extn_sound_trigger_update_device_status(snd_device,
912 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530913 audio_extn_listen_update_device_status(snd_device,
914 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700915 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700916 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700917 audio_extn_sound_trigger_update_device_status(snd_device,
918 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530919 audio_extn_listen_update_device_status(snd_device,
920 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700921 return -EINVAL;
922 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300923 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700924 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530925
926 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
927 !adev->native_playback_enabled &&
928 audio_is_true_native_stream_active(adev)) {
929 ALOGD("%s: %d: napb: enabling native mode in hardware",
930 __func__, __LINE__);
931 audio_route_apply_and_update_path(adev->audio_route,
932 "true-native-mode");
933 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530934 }
Garmond Leunge2433c32017-09-28 21:51:22 -0700935 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
936 (audio_extn_ffv_get_stream() == adev->active_input)) {
937 ALOGD("%s: init ec ref loopback", __func__);
938 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
939 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800940 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800941 return 0;
942}
943
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700944int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700945 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800946{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530947 int i, num_devices = 0;
948 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700949 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
950
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800951 if (snd_device < SND_DEVICE_MIN ||
952 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800953 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800954 return -EINVAL;
955 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
957 ALOGE("%s: device ref cnt is already 0", __func__);
958 return -EINVAL;
959 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700960
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700961 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700962
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700963 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
964 ALOGE("%s: Invalid sound device returned", __func__);
965 return -EINVAL;
966 }
967
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700969 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530970
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800971 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
972 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700973 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700974 } else if (platform_split_snd_device(adev->platform,
975 snd_device,
976 &num_devices,
977 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530978 for (i = 0; i < num_devices; i++) {
979 disable_snd_device(adev, new_snd_devices[i]);
980 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300981 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700982 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300983 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700984
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530985 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
986 audio_extn_a2dp_stop_playback();
987
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700988 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530989 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530990 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
991 adev->native_playback_enabled) {
992 ALOGD("%s: %d: napb: disabling native mode in hardware",
993 __func__, __LINE__);
994 audio_route_reset_and_update_path(adev->audio_route,
995 "true-native-mode");
996 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530997 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
998 adev->asrc_mode_enabled) {
999 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301000 disable_asrc_mode(adev);
1001 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301002 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001003 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1004 (audio_extn_ffv_get_stream() == adev->active_input)) {
1005 ALOGD("%s: deinit ec ref loopback", __func__);
1006 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1007 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001008 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001009 audio_extn_sound_trigger_update_device_status(snd_device,
1010 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301011 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001012 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001013 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015 return 0;
1016}
1017
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001018/*
1019 legend:
1020 uc - existing usecase
1021 new_uc - new usecase
1022 d1, d11, d2 - SND_DEVICE enums
1023 a1, a2 - corresponding ANDROID device enums
1024 B1, B2 - backend strings
1025
1026case 1
1027 uc->dev d1 (a1) B1
1028 new_uc->dev d1 (a1), d2 (a2) B1, B2
1029
1030 resolution: disable and enable uc->dev on d1
1031
1032case 2
1033 uc->dev d1 (a1) B1
1034 new_uc->dev d11 (a1) B1
1035
1036 resolution: need to switch uc since d1 and d11 are related
1037 (e.g. speaker and voice-speaker)
1038 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1039
1040case 3
1041 uc->dev d1 (a1) B1
1042 new_uc->dev d2 (a2) B2
1043
1044 resolution: no need to switch uc
1045
1046case 4
1047 uc->dev d1 (a1) B1
1048 new_uc->dev d2 (a2) B1
1049
1050 resolution: disable enable uc-dev on d2 since backends match
1051 we cannot enable two streams on two different devices if they
1052 share the same backend. e.g. if offload is on speaker device using
1053 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1054 using the same backend, offload must also be switched to voice-handset.
1055
1056case 5
1057 uc->dev d1 (a1) B1
1058 new_uc->dev d1 (a1), d2 (a2) B1
1059
1060 resolution: disable enable uc-dev on d2 since backends match
1061 we cannot enable two streams on two different devices if they
1062 share the same backend.
1063
1064case 6
1065 uc->dev d1 (a1) B1
1066 new_uc->dev d2 (a1) B2
1067
1068 resolution: no need to switch
1069
1070case 7
1071 uc->dev d1 (a1), d2 (a2) B1, B2
1072 new_uc->dev d1 (a1) B1
1073
1074 resolution: no need to switch
1075
1076*/
1077static snd_device_t derive_playback_snd_device(void * platform,
1078 struct audio_usecase *uc,
1079 struct audio_usecase *new_uc,
1080 snd_device_t new_snd_device)
1081{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301082 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001083
1084 snd_device_t d1 = uc->out_snd_device;
1085 snd_device_t d2 = new_snd_device;
1086
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301087 switch (uc->type) {
1088 case TRANSCODE_LOOPBACK :
1089 a1 = uc->stream.inout->out_config.devices;
1090 a2 = new_uc->stream.inout->out_config.devices;
1091 break;
1092 default :
1093 a1 = uc->stream.out->devices;
1094 a2 = new_uc->stream.out->devices;
1095 break;
1096 }
1097
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001098 // Treat as a special case when a1 and a2 are not disjoint
1099 if ((a1 != a2) && (a1 & a2)) {
1100 snd_device_t d3[2];
1101 int num_devices = 0;
1102 int ret = platform_split_snd_device(platform,
1103 popcount(a1) > 1 ? d1 : d2,
1104 &num_devices,
1105 d3);
1106 if (ret < 0) {
1107 if (ret != -ENOSYS) {
1108 ALOGW("%s failed to split snd_device %d",
1109 __func__,
1110 popcount(a1) > 1 ? d1 : d2);
1111 }
1112 goto end;
1113 }
1114
1115 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1116 // But if it does happen, we need to give priority to d2 if
1117 // the combo devices active on the existing usecase share a backend.
1118 // This is because we cannot have a usecase active on a combo device
1119 // and a new usecase requests one device in this combo pair.
1120 if (platform_check_backends_match(d3[0], d3[1])) {
1121 return d2; // case 5
1122 } else {
1123 return d1; // case 1
1124 }
1125 } else {
1126 if (platform_check_backends_match(d1, d2)) {
1127 return d2; // case 2, 4
1128 } else {
1129 return d1; // case 6, 3
1130 }
1131 }
1132
1133end:
1134 return d2; // return whatever was calculated before.
1135}
1136
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301138 struct audio_usecase *uc_info,
1139 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140{
1141 struct listnode *node;
1142 struct audio_usecase *usecase;
1143 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301144 snd_device_t uc_derive_snd_device;
1145 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001147 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301148 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001149 /*
1150 * This function is to make sure that all the usecases that are active on
1151 * the hardware codec backend are always routed to any one device that is
1152 * handled by the hardware codec.
1153 * For example, if low-latency and deep-buffer usecases are currently active
1154 * on speaker and out_set_parameters(headset) is received on low-latency
1155 * output, then we have to make sure deep-buffer is also switched to headset,
1156 * because of the limitation that both the devices cannot be enabled
1157 * at the same time as they share the same backend.
1158 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001159 /*
1160 * This call is to check if we need to force routing for a particular stream
1161 * If there is a backend configuration change for the device when a
1162 * new stream starts, then ADM needs to be closed and re-opened with the new
1163 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001164 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001165 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001166 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1167 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301168 /* For a2dp device reconfigure all active sessions
1169 * with new AFE encoder format based on a2dp state
1170 */
1171 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1172 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1173 audio_extn_a2dp_is_force_device_switch()) {
1174 force_routing = true;
1175 force_restart_session = true;
1176 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301177 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1178
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001180 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001181 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001182 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1183 switch_device[i] = false;
1184
1185 list_for_each(node, &adev->usecase_list) {
1186 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001187
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301188 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1189 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301190 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301191 platform_get_snd_device_name(usecase->out_snd_device),
1192 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301193 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1194 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1195 usecase, uc_info, snd_device);
1196 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1197 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1198 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1199 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1200 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1201 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1202 ((force_restart_session) ||
1203 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301204 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1205 __func__, use_case_table[usecase->id],
1206 platform_get_snd_device_name(usecase->out_snd_device));
1207 disable_audio_route(adev, usecase);
1208 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301209 /* Enable existing usecase on derived playback device */
1210 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301211 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301212 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001213 }
1214 }
1215
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301216 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1217 num_uc_to_switch);
1218
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001219 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001220 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001221
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301222 /* Make sure the previous devices to be disabled first and then enable the
1223 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001224 list_for_each(node, &adev->usecase_list) {
1225 usecase = node_to_item(node, struct audio_usecase, list);
1226 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001227 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228 }
1229 }
1230
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001231 list_for_each(node, &adev->usecase_list) {
1232 usecase = node_to_item(node, struct audio_usecase, list);
1233 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301234 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001235 }
1236 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001237
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238 /* Re-route all the usecases on the shared backend other than the
1239 specified usecase to new snd devices */
1240 list_for_each(node, &adev->usecase_list) {
1241 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301242 /* Update the out_snd_device only before enabling the audio route */
1243 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301244 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301245 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301246 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301247 use_case_table[usecase->id],
1248 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001249 /* Update voc calibration before enabling VoIP route */
1250 if (usecase->type == VOIP_CALL)
1251 status = platform_switch_voice_call_device_post(adev->platform,
1252 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001253 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301254 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301255 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001256 }
1257 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001258 }
1259}
1260
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301261static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001262 struct audio_usecase *uc_info,
1263 snd_device_t snd_device)
1264{
1265 struct listnode *node;
1266 struct audio_usecase *usecase;
1267 bool switch_device[AUDIO_USECASE_MAX];
1268 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301269 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001270 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001271
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301272 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1273 snd_device);
1274 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301275
1276 /*
1277 * Make sure out devices is checked against out codec backend device and
1278 * also in devices against in codec backend. Checking out device against in
1279 * codec backend or vice versa causes issues.
1280 */
1281 if (uc_info->type == PCM_CAPTURE)
1282 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001283 /*
1284 * This function is to make sure that all the active capture usecases
1285 * are always routed to the same input sound device.
1286 * For example, if audio-record and voice-call usecases are currently
1287 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1288 * is received for voice call then we have to make sure that audio-record
1289 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1290 * because of the limitation that two devices cannot be enabled
1291 * at the same time if they share the same backend.
1292 */
1293 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1294 switch_device[i] = false;
1295
1296 list_for_each(node, &adev->usecase_list) {
1297 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301298 /*
1299 * TODO: Enhance below condition to handle BT sco/USB multi recording
1300 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001301 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001302 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301303 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301304 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301305 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301306 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001307 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001308 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1309 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001310 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001311 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001312 switch_device[usecase->id] = true;
1313 num_uc_to_switch++;
1314 }
1315 }
1316
1317 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001318 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001319
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301320 /* Make sure the previous devices to be disabled first and then enable the
1321 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001322 list_for_each(node, &adev->usecase_list) {
1323 usecase = node_to_item(node, struct audio_usecase, list);
1324 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001325 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001326 }
1327 }
1328
1329 list_for_each(node, &adev->usecase_list) {
1330 usecase = node_to_item(node, struct audio_usecase, list);
1331 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001332 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001333 }
1334 }
1335
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001336 /* Re-route all the usecases on the shared backend other than the
1337 specified usecase to new snd devices */
1338 list_for_each(node, &adev->usecase_list) {
1339 usecase = node_to_item(node, struct audio_usecase, list);
1340 /* Update the in_snd_device only before enabling the audio route */
1341 if (switch_device[usecase->id] ) {
1342 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001343 if (usecase->type != VOICE_CALL) {
1344 /* Update voc calibration before enabling VoIP route */
1345 if (usecase->type == VOIP_CALL)
1346 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001347 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001348 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301349 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001350 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001351 }
1352 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001353 }
1354}
1355
Mingming Yin3a941d42016-02-17 18:08:05 -08001356static void reset_hdmi_sink_caps(struct stream_out *out) {
1357 int i = 0;
1358
1359 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1360 out->supported_channel_masks[i] = 0;
1361 }
1362 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1363 out->supported_formats[i] = 0;
1364 }
1365 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1366 out->supported_sample_rates[i] = 0;
1367 }
1368}
1369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001370/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001371static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372{
Mingming Yin3a941d42016-02-17 18:08:05 -08001373 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001374 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375
Mingming Yin3a941d42016-02-17 18:08:05 -08001376 reset_hdmi_sink_caps(out);
1377
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001378 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001379 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001380 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001381 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001382 }
1383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001385 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001386 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001387 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001388 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1389 case 6:
1390 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1391 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1392 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1393 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1394 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1395 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001396 break;
1397 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001398 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001399 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001400 break;
1401 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001402
1403 // check channel format caps
1404 i = 0;
1405 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1406 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1407 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1408 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1409 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1410 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1411 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1412 }
1413
Ben Romberger1aaaf862017-04-06 17:49:46 -07001414 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1415 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1416 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1417 }
1418
Mingming Yin3a941d42016-02-17 18:08:05 -08001419 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1420 ALOGV(":%s HDMI supports DTS format", __func__);
1421 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1422 }
1423
1424 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1425 ALOGV(":%s HDMI supports DTS HD format", __func__);
1426 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1427 }
1428
Naresh Tanniru928f0862017-04-07 16:44:23 -07001429 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1430 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1431 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1432 }
1433
Mingming Yin3a941d42016-02-17 18:08:05 -08001434
1435 // check sample rate caps
1436 i = 0;
1437 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1438 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1439 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1440 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1441 }
1442 }
1443
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001444 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445}
1446
Alexy Josephb1379942016-01-29 15:49:38 -08001447audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001448 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001449{
1450 struct audio_usecase *usecase;
1451 struct listnode *node;
1452
1453 list_for_each(node, &adev->usecase_list) {
1454 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001455 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001456 ALOGV("%s: usecase id %d", __func__, usecase->id);
1457 return usecase->id;
1458 }
1459 }
1460 return USECASE_INVALID;
1461}
1462
Alexy Josephb1379942016-01-29 15:49:38 -08001463struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001464 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001465{
1466 struct audio_usecase *usecase;
1467 struct listnode *node;
1468
1469 list_for_each(node, &adev->usecase_list) {
1470 usecase = node_to_item(node, struct audio_usecase, list);
1471 if (usecase->id == uc_id)
1472 return usecase;
1473 }
1474 return NULL;
1475}
1476
Dhananjay Kumard4833242016-10-06 22:09:12 +05301477struct stream_in *get_next_active_input(const struct audio_device *adev)
1478{
1479 struct audio_usecase *usecase;
1480 struct listnode *node;
1481
1482 list_for_each_reverse(node, &adev->usecase_list) {
1483 usecase = node_to_item(node, struct audio_usecase, list);
1484 if (usecase->type == PCM_CAPTURE)
1485 return usecase->stream.in;
1486 }
1487 return NULL;
1488}
1489
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301490/*
1491 * is a true native playback active
1492 */
1493bool audio_is_true_native_stream_active(struct audio_device *adev)
1494{
1495 bool active = false;
1496 int i = 0;
1497 struct listnode *node;
1498
1499 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1500 ALOGV("%s:napb: not in true mode or non hdphones device",
1501 __func__);
1502 active = false;
1503 goto exit;
1504 }
1505
1506 list_for_each(node, &adev->usecase_list) {
1507 struct audio_usecase *uc;
1508 uc = node_to_item(node, struct audio_usecase, list);
1509 struct stream_out *curr_out =
1510 (struct stream_out*) uc->stream.out;
1511
1512 if (curr_out && PCM_PLAYBACK == uc->type) {
1513 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1514 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1515 uc->id, curr_out->sample_rate,
1516 curr_out->bit_width,
1517 platform_get_snd_device_name(uc->out_snd_device));
1518
1519 if (is_offload_usecase(uc->id) &&
1520 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1521 active = true;
1522 ALOGD("%s:napb:native stream detected", __func__);
1523 }
1524 }
1525 }
1526exit:
1527 return active;
1528}
1529
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001530uint32_t adev_get_dsp_bit_width_enforce_mode()
1531{
1532 if (adev == NULL) {
1533 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1534 return 0;
1535 }
1536 return adev->dsp_bit_width_enforce_mode;
1537}
1538
1539static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1540{
1541 char value[PROPERTY_VALUE_MAX];
1542 int trial;
1543 uint32_t dsp_bit_width_enforce_mode = 0;
1544
1545 if (!mixer) {
1546 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1547 __func__);
1548 return 0;
1549 }
1550
1551 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1552 value, NULL) > 0) {
1553 trial = atoi(value);
1554 switch (trial) {
1555 case 16:
1556 dsp_bit_width_enforce_mode = 16;
1557 break;
1558 case 24:
1559 dsp_bit_width_enforce_mode = 24;
1560 break;
1561 case 32:
1562 dsp_bit_width_enforce_mode = 32;
1563 break;
1564 default:
1565 dsp_bit_width_enforce_mode = 0;
1566 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1567 break;
1568 }
1569 }
1570
1571 return dsp_bit_width_enforce_mode;
1572}
1573
1574static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1575 uint32_t enforce_mode,
1576 bool enable)
1577{
1578 struct mixer_ctl *ctl = NULL;
1579 const char *mixer_ctl_name = "ASM Bit Width";
1580 uint32_t asm_bit_width_mode = 0;
1581
1582 if (enforce_mode == 0) {
1583 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1584 return;
1585 }
1586
1587 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1588 if (!ctl) {
1589 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1590 __func__, mixer_ctl_name);
1591 return;
1592 }
1593
1594 if (enable)
1595 asm_bit_width_mode = enforce_mode;
1596 else
1597 asm_bit_width_mode = 0;
1598
1599 ALOGV("%s DSP bit width feature status is %d width=%d",
1600 __func__, enable, asm_bit_width_mode);
1601 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1602 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1603 asm_bit_width_mode);
1604
1605 return;
1606}
1607
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301608/*
1609 * if native DSD playback active
1610 */
1611bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1612{
1613 bool active = false;
1614 struct listnode *node = NULL;
1615 struct audio_usecase *uc = NULL;
1616 struct stream_out *curr_out = NULL;
1617
1618 list_for_each(node, &adev->usecase_list) {
1619 uc = node_to_item(node, struct audio_usecase, list);
1620 curr_out = (struct stream_out*) uc->stream.out;
1621
1622 if (curr_out && PCM_PLAYBACK == uc->type &&
1623 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1624 active = true;
1625 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301626 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301627 }
1628 }
1629 return active;
1630}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301631
1632static bool force_device_switch(struct audio_usecase *usecase)
1633{
1634 bool ret = false;
1635 bool is_it_true_mode = false;
1636
1637 if (is_offload_usecase(usecase->id) &&
1638 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001639 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1640 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1641 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301642 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1643 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1644 (!is_it_true_mode && adev->native_playback_enabled)){
1645 ret = true;
1646 ALOGD("napb: time to toggle native mode");
1647 }
1648 }
1649
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301650 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301651 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1652 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301653 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001654 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301655 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301656 ALOGD("Force a2dp device switch to update new encoder config");
1657 ret = true;
1658 }
1659
Manish Dewangan671a4202017-08-18 17:30:46 +05301660 if (usecase->stream.out->stream_config_changed) {
1661 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1662 return true;
1663 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301664 return ret;
1665}
1666
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301667bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1668{
1669 bool ret=false;
1670 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1671 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1672 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1673 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1674 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1675 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1676 ret = true;
1677
1678 return ret;
1679}
1680
1681bool is_a2dp_device(snd_device_t out_snd_device)
1682{
1683 bool ret=false;
1684 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1685 ret = true;
1686
1687 return ret;
1688}
1689
1690bool is_bt_soc_on(struct audio_device *adev)
1691{
1692 struct mixer_ctl *ctl;
1693 char *mixer_ctl_name = "BT SOC status";
1694 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1695 bool bt_soc_status = true;
1696 if (!ctl) {
1697 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1698 __func__, mixer_ctl_name);
1699 /*This is to ensure we dont break targets which dont have the kernel change*/
1700 return true;
1701 }
1702 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1703 ALOGD("BT SOC status: %d",bt_soc_status);
1704 return bt_soc_status;
1705}
1706
1707int out_standby_l(struct audio_stream *stream);
1708
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001709int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001711 snd_device_t out_snd_device = SND_DEVICE_NONE;
1712 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001713 struct audio_usecase *usecase = NULL;
1714 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001715 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001716 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301717 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001718 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001719 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301721 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1722
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001723 usecase = get_usecase_from_list(adev, uc_id);
1724 if (usecase == NULL) {
1725 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1726 return -EINVAL;
1727 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001729 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001730 (usecase->type == VOIP_CALL) ||
1731 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301732 if(usecase->stream.out == NULL) {
1733 ALOGE("%s: stream.out is NULL", __func__);
1734 return -EINVAL;
1735 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001736 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001737 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001738 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001739 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301740 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1741 if (usecase->stream.inout == NULL) {
1742 ALOGE("%s: stream.inout is NULL", __func__);
1743 return -EINVAL;
1744 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301745 stream_out.devices = usecase->stream.inout->out_config.devices;
1746 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
1747 stream_out.format = usecase->stream.inout->out_config.format;
1748 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
1749 out_snd_device = platform_get_output_snd_device(adev->platform,
1750 &stream_out);
1751 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301752 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001753 } else {
1754 /*
1755 * If the voice call is active, use the sound devices of voice call usecase
1756 * so that it would not result any device switch. All the usecases will
1757 * be switched to new device when select_devices() is called for voice call
1758 * usecase. This is to avoid switching devices for voice call when
1759 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001760 * choose voice call device only if the use case device is
1761 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001762 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001763 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001764 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001765 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001766 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1767 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301768 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1769 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001770 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001771 in_snd_device = vc_usecase->in_snd_device;
1772 out_snd_device = vc_usecase->out_snd_device;
1773 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001774 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001775 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001776 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001777 if ((voip_usecase != NULL) &&
1778 (usecase->type == PCM_PLAYBACK) &&
1779 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001780 out_snd_device_backend_match = platform_check_backends_match(
1781 voip_usecase->out_snd_device,
1782 platform_get_output_snd_device(
1783 adev->platform,
1784 usecase->stream.out));
1785 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001786 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001787 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1788 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001789 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001790 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001791 in_snd_device = voip_usecase->in_snd_device;
1792 out_snd_device = voip_usecase->out_snd_device;
1793 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001794 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001795 hfp_ucid = audio_extn_hfp_get_usecase();
1796 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001797 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001798 in_snd_device = hfp_usecase->in_snd_device;
1799 out_snd_device = hfp_usecase->out_snd_device;
1800 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001801 }
1802 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301803 if (usecase->stream.out == NULL) {
1804 ALOGE("%s: stream.out is NULL", __func__);
1805 return -EINVAL;
1806 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001807 usecase->devices = usecase->stream.out->devices;
1808 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001809 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001810 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001811 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001812 if (usecase->stream.out == adev->primary_output &&
1813 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001814 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001815 select_devices(adev, adev->active_input->usecase);
1816 }
1817 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001818 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301819 if (usecase->stream.in == NULL) {
1820 ALOGE("%s: stream.in is NULL", __func__);
1821 return -EINVAL;
1822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823 usecase->devices = usecase->stream.in->device;
1824 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001825 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001826 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001827 if (adev->active_input &&
1828 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301829 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1830 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1831 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001832 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001833 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001834 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1835 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001836 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001837 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001838 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001839 }
1840 }
1841
1842 if (out_snd_device == usecase->out_snd_device &&
1843 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301844
1845 if (!force_device_switch(usecase))
1846 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 }
1848
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301849 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1850 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1851 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1852 return 0;
1853 }
1854
sangwoobc677242013-08-08 16:53:43 +09001855 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001856 out_snd_device, platform_get_snd_device_name(out_snd_device),
1857 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 /*
1860 * Limitation: While in call, to do a device switch we need to disable
1861 * and enable both RX and TX devices though one of them is same as current
1862 * device.
1863 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001864 if ((usecase->type == VOICE_CALL) &&
1865 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1866 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001867 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001868 }
1869
1870 if (((usecase->type == VOICE_CALL) ||
1871 (usecase->type == VOIP_CALL)) &&
1872 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1873 /* Disable sidetone only if voice/voip call already exists */
1874 if (voice_is_call_state_active(adev) ||
1875 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001876 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001877
1878 /* Disable aanc only if voice call exists */
1879 if (voice_is_call_state_active(adev))
1880 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001881 }
1882
Zhou Songc66eb7e2017-08-08 18:29:07 +08001883 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301884 (!audio_extn_a2dp_is_ready())) {
1885 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08001886 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301887 }
1888
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001889 /* Disable current sound devices */
1890 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001891 disable_audio_route(adev, usecase);
1892 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893 }
1894
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001896 disable_audio_route(adev, usecase);
1897 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898 }
1899
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001900 /* Applicable only on the targets that has external modem.
1901 * New device information should be sent to modem before enabling
1902 * the devices to reduce in-call device switch time.
1903 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001904 if ((usecase->type == VOICE_CALL) &&
1905 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1906 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001907 status = platform_switch_voice_call_enable_device_config(adev->platform,
1908 out_snd_device,
1909 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001910 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001911
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001912 /* Enable new sound devices */
1913 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001914 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301915 if (platform_check_codec_asrc_support(adev->platform))
1916 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001917 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918 }
1919
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001920 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301921 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001922 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001923 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001924
Avinash Vaish71a8b972014-07-24 15:36:33 +05301925 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001926 status = platform_switch_voice_call_device_post(adev->platform,
1927 out_snd_device,
1928 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301929 enable_audio_route_for_voice_usecases(adev, usecase);
1930 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001931
sangwoo170731f2013-06-08 15:36:36 +09001932 usecase->in_snd_device = in_snd_device;
1933 usecase->out_snd_device = out_snd_device;
1934
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301935 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1936 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301937 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001938 if ((24 == usecase->stream.out->bit_width) &&
1939 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1940 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1941 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1942 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1943 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1944 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1945 /*
1946 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1947 * configured device sample rate, if not update the COPP rate to be equal to the
1948 * device sample rate, else open COPP at stream sample rate
1949 */
1950 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1951 usecase->stream.out->sample_rate,
1952 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301953 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1954 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001955 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1956 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1957 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1958 }
1959
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001960 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001961 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001962 audio_extn_gef_notify_device_config(
1963 usecase->stream.out->devices,
1964 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001965 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001966 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001967 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301968 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001969 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001970
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001971 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001972 /* Enable aanc only if voice call exists */
1973 if (voice_is_call_state_active(adev))
1974 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1975
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001976 /* Enable sidetone only if other voice/voip call already exists */
1977 if (voice_is_call_state_active(adev) ||
1978 voice_extn_compress_voip_is_started(adev))
1979 voice_set_sidetone(adev, out_snd_device, true);
1980 }
1981
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001982 /* Applicable only on the targets that has external modem.
1983 * Enable device command should be sent to modem only after
1984 * enabling voice call mixer controls
1985 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001986 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001987 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1988 out_snd_device,
1989 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301990
1991 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1992
1993 if (usecase->type == VOIP_CALL) {
1994 if (adev->active_input != NULL &&
1995 !adev->active_input->standby) {
1996 if (is_bt_soc_on(adev) == false){
1997 ALOGD("BT SCO MIC disconnected while in connection");
1998 if (adev->active_input->pcm != NULL)
1999 pcm_stop(adev->active_input->pcm);
2000 }
2001 }
2002 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2003 && usecase->stream.out->started) {
2004 if (is_bt_soc_on(adev) == false) {
2005 ALOGD("BT SCO/A2DP disconnected while in connection");
2006 out_standby_l(&usecase->stream.out->stream.common);
2007 }
2008 }
2009 } else if ((usecase->stream.out != NULL) &&
2010 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2011 usecase->stream.out->started) {
2012 if (is_bt_soc_on(adev) == false) {
2013 ALOGD("BT SCO/A2dp disconnected while in connection");
2014 out_standby_l(&usecase->stream.out->stream.common);
2015 }
2016 }
2017 }
2018
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302019 ALOGD("%s: done",__func__);
2020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021 return status;
2022}
2023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024static int stop_input_stream(struct stream_in *in)
2025{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302026 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027 struct audio_usecase *uc_info;
2028 struct audio_device *adev = in->dev;
2029
Eric Laurent994a6932013-07-17 11:51:42 -07002030 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002031 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032 uc_info = get_usecase_from_list(adev, in->usecase);
2033 if (uc_info == NULL) {
2034 ALOGE("%s: Could not find the usecase (%d) in the list",
2035 __func__, in->usecase);
2036 return -EINVAL;
2037 }
2038
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002039 /* Close in-call recording streams */
2040 voice_check_and_stop_incall_rec_usecase(adev, in);
2041
Eric Laurent150dbfe2013-02-27 14:31:02 -08002042 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002043 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002044
2045 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002046 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002048 list_remove(&uc_info->list);
2049 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002051 adev->active_input = get_next_active_input(adev);
2052
Eric Laurent994a6932013-07-17 11:51:42 -07002053 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 return ret;
2055}
2056
2057int start_input_stream(struct stream_in *in)
2058{
2059 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002060 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 struct audio_usecase *uc_info;
2062 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002063 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002064 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065
Mingming Yin2664a5b2015-09-03 10:53:11 -07002066 if (get_usecase_from_list(adev, usecase) == NULL)
2067 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302068 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2069 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002070
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302071 if (CARD_STATUS_OFFLINE == in->card_status||
2072 CARD_STATUS_OFFLINE == adev->card_status) {
2073 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302074 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302075 goto error_config;
2076 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302077
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302078 if (audio_is_bluetooth_sco_device(in->device)) {
2079 if (!adev->bt_sco_on) {
2080 ALOGE("%s: SCO profile is not ready, return error", __func__);
2081 ret = -EIO;
2082 goto error_config;
2083 }
2084 }
2085
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002086 /* Check if source matches incall recording usecase criteria */
2087 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2088 if (ret)
2089 goto error_config;
2090 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002091 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2092
2093 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2094 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2095 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002096 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002097 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002098
Eric Laurentb23d5282013-05-14 15:27:20 -07002099 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100 if (in->pcm_device_id < 0) {
2101 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2102 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002103 ret = -EINVAL;
2104 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002106
2107 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002109
2110 if (!uc_info) {
2111 ret = -ENOMEM;
2112 goto error_config;
2113 }
2114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 uc_info->id = in->usecase;
2116 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002117 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002118 uc_info->devices = in->device;
2119 uc_info->in_snd_device = SND_DEVICE_NONE;
2120 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002122 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302123 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2124 adev->perf_lock_opts,
2125 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002126 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127
Haynes Mathew George16081042017-05-31 17:16:49 -07002128 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302129 ret = audio_extn_cin_start_input_stream(in);
2130 if (ret)
2131 goto error_open;
2132 else
2133 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002134 }
2135
Haynes Mathew George16081042017-05-31 17:16:49 -07002136 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002137 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002138 ALOGE("%s: pcm stream not ready", __func__);
2139 goto error_open;
2140 }
2141 ret = pcm_start(in->pcm);
2142 if (ret < 0) {
2143 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2144 goto error_open;
2145 }
2146 } else {
2147 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2148 unsigned int pcm_open_retry_count = 0;
2149
2150 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2151 flags |= PCM_MMAP | PCM_NOIRQ;
2152 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2153 } else if (in->realtime) {
2154 flags |= PCM_MMAP | PCM_NOIRQ;
2155 }
2156
Garmond Leunge2433c32017-09-28 21:51:22 -07002157 if (audio_extn_ffv_get_stream() == in) {
2158 ALOGD("%s: ffv stream, update pcm config", __func__);
2159 audio_extn_ffv_update_pcm_config(&config);
2160 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002161 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2162 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2163
2164 while (1) {
2165 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002166 flags, &config);
Haynes Mathew George16081042017-05-31 17:16:49 -07002167 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2168 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2169 if (in->pcm != NULL) {
2170 pcm_close(in->pcm);
2171 in->pcm = NULL;
2172 }
2173 if (pcm_open_retry_count-- == 0) {
2174 ret = -EIO;
2175 goto error_open;
2176 }
2177 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2178 continue;
2179 }
2180 break;
2181 }
2182
2183 ALOGV("%s: pcm_prepare", __func__);
2184 ret = pcm_prepare(in->pcm);
2185 if (ret < 0) {
2186 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2187 pcm_close(in->pcm);
2188 in->pcm = NULL;
2189 goto error_open;
2190 }
2191 register_in_stream(in);
2192 if (in->realtime) {
2193 ret = pcm_start(in->pcm);
2194 if (ret < 0) {
2195 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002196 pcm_close(in->pcm);
2197 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002198 goto error_open;
2199 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002200 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002201 }
2202
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302203done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302204 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002205 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002206
Eric Laurentc8400632013-02-14 19:04:54 -08002207 return ret;
2208
2209error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302210 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002212error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302213 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302214 /*
2215 * sleep 50ms to allow sufficient time for kernel
2216 * drivers to recover incases like SSR.
2217 */
2218 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002219 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002220
2221 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222}
2223
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002224void lock_input_stream(struct stream_in *in)
2225{
2226 pthread_mutex_lock(&in->pre_lock);
2227 pthread_mutex_lock(&in->lock);
2228 pthread_mutex_unlock(&in->pre_lock);
2229}
2230
2231void lock_output_stream(struct stream_out *out)
2232{
2233 pthread_mutex_lock(&out->pre_lock);
2234 pthread_mutex_lock(&out->lock);
2235 pthread_mutex_unlock(&out->pre_lock);
2236}
2237
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238/* must be called with out->lock locked */
2239static int send_offload_cmd_l(struct stream_out* out, int command)
2240{
2241 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2242
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002243 if (!cmd) {
2244 ALOGE("failed to allocate mem for command 0x%x", command);
2245 return -ENOMEM;
2246 }
2247
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002248 ALOGVV("%s %d", __func__, command);
2249
2250 cmd->cmd = command;
2251 list_add_tail(&out->offload_cmd_list, &cmd->node);
2252 pthread_cond_signal(&out->offload_cond);
2253 return 0;
2254}
2255
2256/* must be called iwth out->lock locked */
2257static void stop_compressed_output_l(struct stream_out *out)
2258{
2259 out->offload_state = OFFLOAD_STATE_IDLE;
2260 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002261 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002262 if (out->compr != NULL) {
2263 compress_stop(out->compr);
2264 while (out->offload_thread_blocked) {
2265 pthread_cond_wait(&out->cond, &out->lock);
2266 }
2267 }
2268}
2269
Varun Balaraje49253e2017-07-06 19:48:56 +05302270bool is_interactive_usecase(audio_usecase_t uc_id)
2271{
2272 unsigned int i;
2273 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2274 if (uc_id == interactive_usecases[i])
2275 return true;
2276 }
2277 return false;
2278}
2279
2280static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2281{
2282 audio_usecase_t ret_uc = USECASE_INVALID;
2283 unsigned int intract_uc_index;
2284 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2285
2286 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2287 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2288 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2289 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2290 ret_uc = interactive_usecases[intract_uc_index];
2291 break;
2292 }
2293 }
2294
2295 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2296 return ret_uc;
2297}
2298
2299static void free_interactive_usecase(struct audio_device *adev,
2300 audio_usecase_t uc_id)
2301{
2302 unsigned int interact_uc_index;
2303 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2304
2305 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2306 if (interactive_usecases[interact_uc_index] == uc_id) {
2307 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2308 break;
2309 }
2310 }
2311 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2312}
2313
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002314bool is_offload_usecase(audio_usecase_t uc_id)
2315{
2316 unsigned int i;
2317 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2318 if (uc_id == offload_usecases[i])
2319 return true;
2320 }
2321 return false;
2322}
2323
Dhananjay Kumarac341582017-02-23 23:42:25 +05302324static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002325{
vivek mehta446c3962015-09-14 10:57:35 -07002326 audio_usecase_t ret_uc = USECASE_INVALID;
2327 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002328 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002329 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302330 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002331 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2332 else
2333 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002334
vivek mehta446c3962015-09-14 10:57:35 -07002335 pthread_mutex_lock(&adev->lock);
2336 if (get_usecase_from_list(adev, ret_uc) != NULL)
2337 ret_uc = USECASE_INVALID;
2338 pthread_mutex_unlock(&adev->lock);
2339
2340 return ret_uc;
2341 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002342
2343 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002344 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2345 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2346 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2347 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002348 break;
2349 }
2350 }
vivek mehta446c3962015-09-14 10:57:35 -07002351
2352 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2353 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002354}
2355
2356static void free_offload_usecase(struct audio_device *adev,
2357 audio_usecase_t uc_id)
2358{
vivek mehta446c3962015-09-14 10:57:35 -07002359 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002360 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002361
2362 if (!adev->multi_offload_enable)
2363 return;
2364
2365 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2366 if (offload_usecases[offload_uc_index] == uc_id) {
2367 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002368 break;
2369 }
2370 }
2371 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2372}
2373
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374static void *offload_thread_loop(void *context)
2375{
2376 struct stream_out *out = (struct stream_out *) context;
2377 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002378 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2381 set_sched_policy(0, SP_FOREGROUND);
2382 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2383
2384 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002385 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 for (;;) {
2387 struct offload_cmd *cmd = NULL;
2388 stream_callback_event_t event;
2389 bool send_callback = false;
2390
2391 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2392 __func__, list_empty(&out->offload_cmd_list),
2393 out->offload_state);
2394 if (list_empty(&out->offload_cmd_list)) {
2395 ALOGV("%s SLEEPING", __func__);
2396 pthread_cond_wait(&out->offload_cond, &out->lock);
2397 ALOGV("%s RUNNING", __func__);
2398 continue;
2399 }
2400
2401 item = list_head(&out->offload_cmd_list);
2402 cmd = node_to_item(item, struct offload_cmd, node);
2403 list_remove(item);
2404
2405 ALOGVV("%s STATE %d CMD %d out->compr %p",
2406 __func__, out->offload_state, cmd->cmd, out->compr);
2407
2408 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2409 free(cmd);
2410 break;
2411 }
2412
2413 if (out->compr == NULL) {
2414 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002415 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002416 pthread_cond_signal(&out->cond);
2417 continue;
2418 }
2419 out->offload_thread_blocked = true;
2420 pthread_mutex_unlock(&out->lock);
2421 send_callback = false;
2422 switch(cmd->cmd) {
2423 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002424 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002425 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002426 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002427 send_callback = true;
2428 event = STREAM_CBK_EVENT_WRITE_READY;
2429 break;
2430 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002431 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302432 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002433 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302434 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002435 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302436 if (ret < 0)
2437 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302438 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302439 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002440 compress_drain(out->compr);
2441 else
2442 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302443 if (ret != -ENETRESET) {
2444 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302445 pthread_mutex_lock(&out->lock);
2446 out->send_new_metadata = 1;
2447 out->send_next_track_params = true;
2448 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302449 event = STREAM_CBK_EVENT_DRAIN_READY;
2450 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2451 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302452 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453 break;
2454 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002455 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002456 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002457 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002458 send_callback = true;
2459 event = STREAM_CBK_EVENT_DRAIN_READY;
2460 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302461 case OFFLOAD_CMD_ERROR:
2462 ALOGD("copl(%p): sending error callback to AF", out);
2463 send_callback = true;
2464 event = STREAM_CBK_EVENT_ERROR;
2465 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 default:
2467 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2468 break;
2469 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002470 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002471 out->offload_thread_blocked = false;
2472 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002473 if (send_callback && out->client_callback) {
2474 ALOGVV("%s: sending client_callback event %d", __func__, event);
2475 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002476 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002477 free(cmd);
2478 }
2479
2480 pthread_cond_signal(&out->cond);
2481 while (!list_empty(&out->offload_cmd_list)) {
2482 item = list_head(&out->offload_cmd_list);
2483 list_remove(item);
2484 free(node_to_item(item, struct offload_cmd, node));
2485 }
2486 pthread_mutex_unlock(&out->lock);
2487
2488 return NULL;
2489}
2490
2491static int create_offload_callback_thread(struct stream_out *out)
2492{
2493 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2494 list_init(&out->offload_cmd_list);
2495 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2496 offload_thread_loop, out);
2497 return 0;
2498}
2499
2500static int destroy_offload_callback_thread(struct stream_out *out)
2501{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002502 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002503 stop_compressed_output_l(out);
2504 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2505
2506 pthread_mutex_unlock(&out->lock);
2507 pthread_join(out->offload_thread, (void **) NULL);
2508 pthread_cond_destroy(&out->offload_cond);
2509
2510 return 0;
2511}
2512
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513static int stop_output_stream(struct stream_out *out)
2514{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302515 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 struct audio_usecase *uc_info;
2517 struct audio_device *adev = out->dev;
2518
Eric Laurent994a6932013-07-17 11:51:42 -07002519 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002520 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 uc_info = get_usecase_from_list(adev, out->usecase);
2522 if (uc_info == NULL) {
2523 ALOGE("%s: Could not find the usecase (%d) in the list",
2524 __func__, out->usecase);
2525 return -EINVAL;
2526 }
2527
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002528 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302529 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002530 if (adev->visualizer_stop_output != NULL)
2531 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002532
2533 audio_extn_dts_remove_state_notifier_node(out->usecase);
2534
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002535 if (adev->offload_effects_stop_output != NULL)
2536 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2537 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002538
Eric Laurent150dbfe2013-02-27 14:31:02 -08002539 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002540 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002541
2542 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002543 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002545 if (is_offload_usecase(out->usecase)) {
2546 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2547 adev->dsp_bit_width_enforce_mode,
2548 false);
2549 }
2550
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002551 list_remove(&uc_info->list);
2552 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302553 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002554 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302555 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002556 ALOGV("Disable passthrough , reset mixer to pcm");
2557 /* NO_PASSTHROUGH */
2558 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002559 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002560 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2561 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002562
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302563 /* Must be called after removing the usecase from list */
2564 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302565 audio_extn_keep_alive_start();
2566
Manish Dewangan21a850a2017-08-14 12:03:55 +05302567 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002568 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2569 if (ret < 0)
2570 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2571 }
2572
Eric Laurent994a6932013-07-17 11:51:42 -07002573 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 return ret;
2575}
2576
2577int start_output_stream(struct stream_out *out)
2578{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 struct audio_usecase *uc_info;
2581 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002582 char mixer_ctl_name[128];
2583 struct mixer_ctl *ctl = NULL;
2584 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302585 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002587 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2588 ret = -EINVAL;
2589 goto error_config;
2590 }
2591
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302592 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2593 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2594 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302595
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302596 if (CARD_STATUS_OFFLINE == out->card_status ||
2597 CARD_STATUS_OFFLINE == adev->card_status) {
2598 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302599 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302600 goto error_config;
2601 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302602
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302603 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2604 if (!audio_extn_a2dp_is_ready()) {
2605 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302606 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302607 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302608 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2609 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2610 ret = -EAGAIN;
2611 goto error_config;
2612 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302613 }
2614 }
2615 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302616 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2617 if (!adev->bt_sco_on) {
2618 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2619 //combo usecase just by pass a2dp
2620 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2621 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2622 } else {
2623 ALOGE("%s: SCO profile is not ready, return error", __func__);
2624 ret = -EAGAIN;
2625 goto error_config;
2626 }
2627 }
2628 }
2629
Eric Laurentb23d5282013-05-14 15:27:20 -07002630 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631 if (out->pcm_device_id < 0) {
2632 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2633 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002634 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002635 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 }
2637
2638 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002639
2640 if (!uc_info) {
2641 ret = -ENOMEM;
2642 goto error_config;
2643 }
2644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 uc_info->id = out->usecase;
2646 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002647 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002648 uc_info->devices = out->devices;
2649 uc_info->in_snd_device = SND_DEVICE_NONE;
2650 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002651 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302653 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2654 adev->perf_lock_opts,
2655 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302656
2657 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2658 audio_extn_keep_alive_stop();
2659 if (audio_extn_passthru_is_enabled() &&
2660 audio_extn_passthru_is_passthrough_stream(out)) {
2661 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302662 }
2663 }
2664
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302665 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2666 (!audio_extn_a2dp_is_ready())) {
2667 if (!a2dp_combo) {
2668 check_a2dp_restore_l(adev, out, false);
2669 } else {
2670 audio_devices_t dev = out->devices;
2671 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2672 select_devices(adev, out->usecase);
2673 out->devices = dev;
2674 }
2675 } else {
2676 select_devices(adev, out->usecase);
2677 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002678
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002679 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2680 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07002681
2682 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2683 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2684 ALOGE("%s: pcm stream not ready", __func__);
2685 goto error_open;
2686 }
2687 ret = pcm_start(out->pcm);
2688 if (ret < 0) {
2689 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2690 goto error_open;
2691 }
2692 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002693 unsigned int flags = PCM_OUT;
2694 unsigned int pcm_open_retry_count = 0;
2695 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2696 flags |= PCM_MMAP | PCM_NOIRQ;
2697 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002698 } else if (out->realtime) {
2699 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002700 } else
2701 flags |= PCM_MONOTONIC;
2702
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002703 if ((adev->vr_audio_mode_enabled) &&
2704 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2705 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2706 "PCM_Dev %d Topology", out->pcm_device_id);
2707 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2708 if (!ctl) {
2709 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2710 __func__, mixer_ctl_name);
2711 } else {
2712 //if success use ULLPP
2713 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2714 __func__, mixer_ctl_name, out->pcm_device_id);
2715 //There is a still a possibility that some sessions
2716 // that request for FAST|RAW when 3D audio is active
2717 //can go through ULLPP. Ideally we expects apps to
2718 //listen to audio focus and stop concurrent playback
2719 //Also, we will look for mode flag (voice_in_communication)
2720 //before enabling the realtime flag.
2721 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2722 }
2723 }
2724
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002725 while (1) {
2726 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2727 flags, &out->config);
2728 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2729 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2730 if (out->pcm != NULL) {
2731 pcm_close(out->pcm);
2732 out->pcm = NULL;
2733 }
2734 if (pcm_open_retry_count-- == 0) {
2735 ret = -EIO;
2736 goto error_open;
2737 }
2738 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2739 continue;
2740 }
2741 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002742 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002743
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002744 ALOGV("%s: pcm_prepare", __func__);
2745 if (pcm_is_ready(out->pcm)) {
2746 ret = pcm_prepare(out->pcm);
2747 if (ret < 0) {
2748 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2749 pcm_close(out->pcm);
2750 out->pcm = NULL;
2751 goto error_open;
2752 }
2753 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302754 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302755 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08002756 // apply volume for voip playback after path is set up
2757 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
2758 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002759 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002760 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302761 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002762 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2763 adev->dsp_bit_width_enforce_mode,
2764 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002766 out->compr = compress_open(adev->snd_card,
2767 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002768 COMPRESS_IN, &out->compr_config);
2769 if (out->compr && !is_compress_ready(out->compr)) {
2770 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2771 compress_close(out->compr);
2772 out->compr = NULL;
2773 ret = -EIO;
2774 goto error_open;
2775 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302776 /* compress_open sends params of the track, so reset the flag here */
2777 out->is_compr_metadata_avail = false;
2778
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002779 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002780 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002781
Fred Oh3f43e742015-03-04 18:42:34 -08002782 /* Since small bufs uses blocking writes, a write will be blocked
2783 for the default max poll time (20s) in the event of an SSR.
2784 Reduce the poll time to observe and deal with SSR faster.
2785 */
Ashish Jain5106d362016-05-11 19:23:33 +05302786 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002787 compress_set_max_poll_wait(out->compr, 1000);
2788 }
2789
Manish Dewangan69426c82017-01-30 17:35:36 +05302790 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302791 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302792
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002793 audio_extn_dts_create_state_notifier_node(out->usecase);
2794 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2795 popcount(out->channel_mask),
2796 out->playback_started);
2797
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002798#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05302799 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002800 audio_extn_dolby_send_ddp_endp_params(adev);
2801#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302802 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2803 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002804 if (adev->visualizer_start_output != NULL)
2805 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2806 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302807 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002808 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002809 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002811
2812 if (ret == 0) {
2813 register_out_stream(out);
2814 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07002815 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2816 ALOGE("%s: pcm stream not ready", __func__);
2817 goto error_open;
2818 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002819 ret = pcm_start(out->pcm);
2820 if (ret < 0)
2821 goto error_open;
2822 }
2823 }
2824
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302825 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002826 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002827
Manish Dewangan21a850a2017-08-14 12:03:55 +05302828 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002829 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002830 if (ret < 0)
2831 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2832 }
2833
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002834 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302836 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002838error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302839 /*
2840 * sleep 50ms to allow sufficient time for kernel
2841 * drivers to recover incases like SSR.
2842 */
2843 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002844 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845}
2846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847static int check_input_parameters(uint32_t sample_rate,
2848 audio_format_t format,
2849 int channel_count)
2850{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002851 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302853 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2854 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2855 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002856 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302857 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002858
2859 switch (channel_count) {
2860 case 1:
2861 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302862 case 3:
2863 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002864 case 6:
2865 break;
2866 default:
2867 ret = -EINVAL;
2868 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869
2870 switch (sample_rate) {
2871 case 8000:
2872 case 11025:
2873 case 12000:
2874 case 16000:
2875 case 22050:
2876 case 24000:
2877 case 32000:
2878 case 44100:
2879 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302880 case 96000:
2881 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 break;
2883 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002884 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002885 }
2886
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002887 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888}
2889
2890static size_t get_input_buffer_size(uint32_t sample_rate,
2891 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002892 int channel_count,
2893 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894{
2895 size_t size = 0;
2896
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002897 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2898 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002899
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002900 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002901 if (is_low_latency)
2902 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302903
2904 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002906 /* make sure the size is multiple of 32 bytes
2907 * At 48 kHz mono 16-bit PCM:
2908 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2909 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2910 */
2911 size += 0x1f;
2912 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002913
2914 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915}
2916
Ashish Jain058165c2016-09-28 23:18:48 +05302917static size_t get_output_period_size(uint32_t sample_rate,
2918 audio_format_t format,
2919 int channel_count,
2920 int duration /*in millisecs*/)
2921{
2922 size_t size = 0;
2923 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2924
2925 if ((duration == 0) || (sample_rate == 0) ||
2926 (bytes_per_sample == 0) || (channel_count == 0)) {
2927 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2928 bytes_per_sample, channel_count);
2929 return -EINVAL;
2930 }
2931
2932 size = (sample_rate *
2933 duration *
2934 bytes_per_sample *
2935 channel_count) / 1000;
2936 /*
2937 * To have same PCM samples for all channels, the buffer size requires to
2938 * be multiple of (number of channels * bytes per sample)
2939 * For writes to succeed, the buffer must be written at address which is multiple of 32
2940 */
2941 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2942
2943 return (size/(channel_count * bytes_per_sample));
2944}
2945
Ashish Jain5106d362016-05-11 19:23:33 +05302946static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2947{
2948 uint64_t actual_frames_rendered = 0;
2949 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2950
2951 /* This adjustment accounts for buffering after app processor.
2952 * It is based on estimated DSP latency per use case, rather than exact.
2953 */
2954 int64_t platform_latency = platform_render_latency(out->usecase) *
2955 out->sample_rate / 1000000LL;
2956
2957 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2958 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2959 * hence only estimate.
2960 */
2961 int64_t signed_frames = out->written - kernel_buffer_size;
2962
2963 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2964
2965 if (signed_frames > 0)
2966 actual_frames_rendered = signed_frames;
2967
2968 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2969 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2970 (long long int)out->written, (int)kernel_buffer_size,
2971 audio_bytes_per_sample(out->compr_config.codec->format),
2972 popcount(out->channel_mask));
2973
2974 return actual_frames_rendered;
2975}
2976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2978{
2979 struct stream_out *out = (struct stream_out *)stream;
2980
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002981 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982}
2983
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002984static int out_set_sample_rate(struct audio_stream *stream __unused,
2985 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986{
2987 return -ENOSYS;
2988}
2989
2990static size_t out_get_buffer_size(const struct audio_stream *stream)
2991{
2992 struct stream_out *out = (struct stream_out *)stream;
2993
Varun Balaraje49253e2017-07-06 19:48:56 +05302994 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05302995 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05302996 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302997 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2998 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2999 else
3000 return out->compr_config.fragment_size;
3001 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003002 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003003 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3004 return VOIP_IO_BUF_SIZE(out->config.rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE);
Dhananjay Kumarac341582017-02-23 23:42:25 +05303005 else if (is_offload_usecase(out->usecase) &&
3006 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303007 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003008
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003009 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003010 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011}
3012
3013static uint32_t out_get_channels(const struct audio_stream *stream)
3014{
3015 struct stream_out *out = (struct stream_out *)stream;
3016
3017 return out->channel_mask;
3018}
3019
3020static audio_format_t out_get_format(const struct audio_stream *stream)
3021{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022 struct stream_out *out = (struct stream_out *)stream;
3023
3024 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025}
3026
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003027static int out_set_format(struct audio_stream *stream __unused,
3028 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029{
3030 return -ENOSYS;
3031}
3032
3033static int out_standby(struct audio_stream *stream)
3034{
3035 struct stream_out *out = (struct stream_out *)stream;
3036 struct audio_device *adev = out->dev;
kunleiza9d11682017-08-04 14:14:09 +08003037 struct audio_usecase *uc_info;
3038 struct listnode *node;
Haynes Mathew George16081042017-05-31 17:16:49 -07003039 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303041 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3042 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003044 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003046 if (adev->adm_deregister_stream)
3047 adev->adm_deregister_stream(adev->adm_data, out->handle);
3048
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003049 if (is_offload_usecase(out->usecase))
3050 stop_compressed_output_l(out);
3051
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003052 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003054 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3055 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303056 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003057 pthread_mutex_unlock(&adev->lock);
3058 pthread_mutex_unlock(&out->lock);
3059 ALOGD("VOIP output entered standby");
3060 return 0;
3061 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003062 if (out->pcm) {
3063 pcm_close(out->pcm);
3064 out->pcm = NULL;
3065 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003066 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3067 do_stop = out->playback_started;
3068 out->playback_started = false;
3069 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003070 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003071 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303072 out->send_next_track_params = false;
3073 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003074 out->gapless_mdata.encoder_delay = 0;
3075 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003076 if (out->compr != NULL) {
3077 compress_close(out->compr);
3078 out->compr = NULL;
3079 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003080 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003081 if (do_stop) {
3082 stop_output_stream(out);
3083 }
kunleiza9d11682017-08-04 14:14:09 +08003084 //restore output device for active usecase when current snd device and output device mismatch
3085 list_for_each(node, &adev->usecase_list) {
3086 uc_info = node_to_item(node, struct audio_usecase, list);
3087 if ((uc_info->type == PCM_PLAYBACK) &&
3088 (uc_info->out_snd_device != platform_get_output_snd_device(adev->platform, uc_info->stream.out)))
3089 select_devices(adev, uc_info->id);
3090 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003091 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092 }
3093 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303094 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 return 0;
3096}
3097
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303098static int out_on_error(struct audio_stream *stream)
3099{
3100 struct stream_out *out = (struct stream_out *)stream;
3101 bool do_standby = false;
3102
3103 lock_output_stream(out);
3104 if (!out->standby) {
3105 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3106 stop_compressed_output_l(out);
3107 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
3108 } else
3109 do_standby = true;
3110 }
3111 pthread_mutex_unlock(&out->lock);
3112
3113 if (do_standby)
3114 return out_standby(&out->stream.common);
3115
3116 return 0;
3117}
3118
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303119/*
3120 *standby implementation without locks, assumes that the callee already
3121 *has taken adev and out lock.
3122 */
3123int out_standby_l(struct audio_stream *stream)
3124{
3125 struct stream_out *out = (struct stream_out *)stream;
3126 struct audio_device *adev = out->dev;
3127
3128 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3129 stream, out->usecase, use_case_table[out->usecase]);
3130
3131 if (!out->standby) {
3132 if (adev->adm_deregister_stream)
3133 adev->adm_deregister_stream(adev->adm_data, out->handle);
3134
3135 if (is_offload_usecase(out->usecase))
3136 stop_compressed_output_l(out);
3137
3138 out->standby = true;
3139 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3140 voice_extn_compress_voip_close_output_stream(stream);
3141 out->started = 0;
3142 ALOGD("VOIP output entered standby");
3143 return 0;
3144 } else if (!is_offload_usecase(out->usecase)) {
3145 if (out->pcm) {
3146 pcm_close(out->pcm);
3147 out->pcm = NULL;
3148 }
3149 } else {
3150 ALOGD("copl(%p):standby", out);
3151 out->send_next_track_params = false;
3152 out->is_compr_metadata_avail = false;
3153 out->gapless_mdata.encoder_delay = 0;
3154 out->gapless_mdata.encoder_padding = 0;
3155 if (out->compr != NULL) {
3156 compress_close(out->compr);
3157 out->compr = NULL;
3158 }
3159 }
3160 stop_output_stream(out);
3161 }
3162 ALOGD("%s: exit", __func__);
3163 return 0;
3164}
3165
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003166static int out_dump(const struct audio_stream *stream __unused,
3167 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168{
3169 return 0;
3170}
3171
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003172static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3173{
3174 int ret = 0;
3175 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003176
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003177 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003178 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003179 return -EINVAL;
3180 }
3181
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303182 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003183
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003184 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3185 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303186 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003187 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003188 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3189 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303190 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003191 }
3192
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003193 ALOGV("%s new encoder delay %u and padding %u", __func__,
3194 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3195
3196 return 0;
3197}
3198
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003199static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3200{
3201 return out == adev->primary_output || out == adev->voice_tx_output;
3202}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003203
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303204// note: this call is safe only if the stream_cb is
3205// removed first in close_output_stream (as is done now).
3206static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3207{
3208 if (!stream || !parms)
3209 return;
3210
3211 struct stream_out *out = (struct stream_out *)stream;
3212 struct audio_device *adev = out->dev;
3213
3214 card_status_t status;
3215 int card;
3216 if (parse_snd_card_status(parms, &card, &status) < 0)
3217 return;
3218
3219 pthread_mutex_lock(&adev->lock);
3220 bool valid_cb = (card == adev->snd_card);
3221 pthread_mutex_unlock(&adev->lock);
3222
3223 if (!valid_cb)
3224 return;
3225
3226 lock_output_stream(out);
3227 if (out->card_status != status)
3228 out->card_status = status;
3229 pthread_mutex_unlock(&out->lock);
3230
3231 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3232 use_case_table[out->usecase],
3233 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3234
3235 if (status == CARD_STATUS_OFFLINE)
3236 out_on_error(stream);
3237
3238 return;
3239}
3240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3242{
3243 struct stream_out *out = (struct stream_out *)stream;
3244 struct audio_device *adev = out->dev;
3245 struct str_parms *parms;
3246 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003247 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303248 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249
sangwoobc677242013-08-08 16:53:43 +09003250 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003251 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303253 if (!parms)
3254 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003255 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3256 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003258 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003259 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003261 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003262 * When HDMI cable is unplugged the music playback is paused and
3263 * the policy manager sends routing=0. But the audioflinger continues
3264 * to write data until standby time (3sec). As the HDMI core is
3265 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003266 * Avoid this by routing audio to speaker until standby.
3267 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003268 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3269 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303270 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003271 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3272 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003273 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303274 /*
3275 * When A2DP is disconnected the
3276 * music playback is paused and the policy manager sends routing=0
3277 * But the audioflingercontinues to write data until standby time
3278 * (3sec). As BT is turned off, the write gets blocked.
3279 * Avoid this by routing audio to speaker until standby.
3280 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003281 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303282 (val == AUDIO_DEVICE_NONE)) {
3283 val = AUDIO_DEVICE_OUT_SPEAKER;
3284 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303285 /* To avoid a2dp to sco overlapping / BT device improper state
3286 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303287 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303288 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3289 if (!audio_extn_a2dp_is_ready()) {
3290 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3291 //combo usecase just by pass a2dp
3292 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303293 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303294 } else {
3295 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3296 /* update device to a2dp and don't route as BT returned error
3297 * However it is still possible a2dp routing called because
3298 * of current active device disconnection (like wired headset)
3299 */
3300 out->devices = val;
3301 pthread_mutex_unlock(&out->lock);
3302 pthread_mutex_unlock(&adev->lock);
3303 goto error;
3304 }
3305 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303306 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003307 /*
3308 * select_devices() call below switches all the usecases on the same
3309 * backend to the new device. Refer to check_usecases_codec_backend() in
3310 * the select_devices(). But how do we undo this?
3311 *
3312 * For example, music playback is active on headset (deep-buffer usecase)
3313 * and if we go to ringtones and select a ringtone, low-latency usecase
3314 * will be started on headset+speaker. As we can't enable headset+speaker
3315 * and headset devices at the same time, select_devices() switches the music
3316 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3317 * So when the ringtone playback is completed, how do we undo the same?
3318 *
3319 * We are relying on the out_set_parameters() call on deep-buffer output,
3320 * once the ringtone playback is ended.
3321 * NOTE: We should not check if the current devices are same as new devices.
3322 * Because select_devices() must be called to switch back the music
3323 * playback to headset.
3324 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003325 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003326 audio_devices_t new_dev = val;
3327 bool same_dev = out->devices == new_dev;
3328 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003329
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003330 if (output_drives_call(adev, out)) {
3331 if(!voice_is_in_call(adev)) {
3332 if (adev->mode == AUDIO_MODE_IN_CALL) {
3333 adev->current_call_output = out;
3334 ret = voice_start_call(adev);
3335 }
3336 } else {
3337 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003338 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003339 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003340 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003341
3342 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003343 if (!same_dev) {
3344 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303345 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3346 adev->perf_lock_opts,
3347 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003348 if (adev->adm_on_routing_change)
3349 adev->adm_on_routing_change(adev->adm_data,
3350 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003351 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303352 if (!bypass_a2dp) {
3353 select_devices(adev, out->usecase);
3354 } else {
3355 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3356 select_devices(adev, out->usecase);
3357 out->devices = new_dev;
3358 }
Sudheer Papothi80266982016-08-16 02:36:18 +05303359 if (!same_dev)
3360 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303361 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3362 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003363 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303364 pthread_mutex_lock(&out->compr_mute_lock);
3365 out->a2dp_compress_mute = false;
3366 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3367 pthread_mutex_unlock(&out->compr_mute_lock);
3368 }
3369
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003370 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003371 }
3372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003374 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003376
3377 if (out == adev->primary_output) {
3378 pthread_mutex_lock(&adev->lock);
3379 audio_extn_set_parameters(adev, parms);
3380 pthread_mutex_unlock(&adev->lock);
3381 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003382 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003383 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003384 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003385
3386 audio_extn_dts_create_state_notifier_node(out->usecase);
3387 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3388 popcount(out->channel_mask),
3389 out->playback_started);
3390
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003391 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003392 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003393
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303394 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3395 if (err >= 0) {
3396 strlcpy(out->profile, value, sizeof(out->profile));
3397 ALOGV("updating stream profile with value '%s'", out->profile);
3398 lock_output_stream(out);
3399 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3400 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003401 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303402 out->sample_rate, out->bit_width,
3403 out->channel_mask, out->profile,
3404 &out->app_type_cfg);
3405 pthread_mutex_unlock(&out->lock);
3406 }
3407
Alexy Joseph98988832017-01-13 14:56:59 -08003408 //suspend, resume handling block
3409 if (out->dynamic_pm_qos_enabled) {
3410 //check suspend parameter only for low latency and if the property
3411 //is enabled
3412 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3413 ALOGI("%s: got suspend_playback %s", __func__, value);
3414 lock_output_stream(out);
3415 if (!strncmp(value, "false", 5)) {
3416 //suspend_playback=false is supposed to set QOS value back to 75%
3417 //the mixer control sent with value Enable will achieve that
3418 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3419 } else if (!strncmp (value, "true", 4)) {
3420 //suspend_playback=true is supposed to remove QOS value
3421 //resetting the mixer control will set the default value
3422 //for the mixer control which is Disable and this removes the QOS vote
3423 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3424 } else {
3425 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3426 " got %s", __func__, value);
3427 ret = -1;
3428 }
3429
3430 if (ret != 0) {
3431 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3432 __func__, out->pm_qos_mixer_path, ret);
3433 }
3434
3435 pthread_mutex_unlock(&out->lock);
3436 }
3437 }
3438 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303440error:
Eric Laurent994a6932013-07-17 11:51:42 -07003441 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 return ret;
3443}
3444
3445static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3446{
3447 struct stream_out *out = (struct stream_out *)stream;
3448 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003449 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450 char value[256];
3451 struct str_parms *reply = str_parms_create();
3452 size_t i, j;
3453 int ret;
3454 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003455
3456 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003457 if (reply) {
3458 str_parms_destroy(reply);
3459 }
3460 if (query) {
3461 str_parms_destroy(query);
3462 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003463 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3464 return NULL;
3465 }
3466
Eric Laurent994a6932013-07-17 11:51:42 -07003467 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3469 if (ret >= 0) {
3470 value[0] = '\0';
3471 i = 0;
3472 while (out->supported_channel_masks[i] != 0) {
3473 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3474 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3475 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003476 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003478 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479 first = false;
3480 break;
3481 }
3482 }
3483 i++;
3484 }
3485 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3486 str = str_parms_to_str(reply);
3487 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003488 voice_extn_out_get_parameters(out, query, reply);
3489 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003491
Alexy Joseph62142aa2015-11-16 15:10:34 -08003492
3493 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3494 if (ret >= 0) {
3495 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303496 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3497 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003498 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303499 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003500 } else {
3501 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303502 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003503 }
3504 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003505 if (str)
3506 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003507 str = str_parms_to_str(reply);
3508 }
3509
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003510 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3511 if (ret >= 0) {
3512 value[0] = '\0';
3513 i = 0;
3514 first = true;
3515 while (out->supported_formats[i] != 0) {
3516 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3517 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3518 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003519 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003520 }
3521 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3522 first = false;
3523 break;
3524 }
3525 }
3526 i++;
3527 }
3528 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003529 if (str)
3530 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003531 str = str_parms_to_str(reply);
3532 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003533
3534 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3535 if (ret >= 0) {
3536 value[0] = '\0';
3537 i = 0;
3538 first = true;
3539 while (out->supported_sample_rates[i] != 0) {
3540 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3541 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3542 if (!first) {
3543 strlcat(value, "|", sizeof(value));
3544 }
3545 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3546 first = false;
3547 break;
3548 }
3549 }
3550 i++;
3551 }
3552 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3553 if (str)
3554 free(str);
3555 str = str_parms_to_str(reply);
3556 }
3557
Alexy Joseph98988832017-01-13 14:56:59 -08003558 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
3559 //only low latency track supports suspend_resume
3560 str_parms_add_int(reply, "supports_hw_suspend",
3561 (out->dynamic_pm_qos_enabled));
3562 if (str)
3563 free(str);
3564 str = str_parms_to_str(reply);
3565 }
3566
3567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568 str_parms_destroy(query);
3569 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003570 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571 return str;
3572}
3573
3574static uint32_t out_get_latency(const struct audio_stream_out *stream)
3575{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003576 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003578 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579
Alexy Josephaa54c872014-12-03 02:46:47 -08003580 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303581 lock_output_stream(out);
3582 latency = audio_extn_utils_compress_get_dsp_latency(out);
3583 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07003584 } else if ((out->realtime) ||
3585 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003586 // since the buffer won't be filled up faster than realtime,
3587 // return a smaller number
3588 if (out->config.rate)
3589 period_ms = (out->af_period_multiplier * out->config.period_size *
3590 1000) / (out->config.rate);
3591 else
3592 period_ms = 0;
3593 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003594 } else {
3595 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003596 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003597 }
3598
yidongh0515e042017-07-06 15:00:34 +08003599 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003600 latency += audio_extn_a2dp_get_encoder_latency();
3601
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303602 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003603 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604}
3605
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303606static float AmpToDb(float amplification)
3607{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303608 float db = DSD_VOLUME_MIN_DB;
3609 if (amplification > 0) {
3610 db = 20 * log10(amplification);
3611 if(db < DSD_VOLUME_MIN_DB)
3612 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303613 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303614 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303615}
3616
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303617static int out_set_compr_volume(struct audio_stream_out *stream, float left,
3618 float right)
3619{
3620 struct stream_out *out = (struct stream_out *)stream;
3621 int volume[2];
3622 char mixer_ctl_name[128];
3623 struct audio_device *adev = out->dev;
3624 struct mixer_ctl *ctl;
3625 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3626 PCM_PLAYBACK);
3627
3628 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3629 "Compress Playback %d Volume", pcm_device_id);
3630 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3631 if (!ctl) {
3632 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3633 __func__, mixer_ctl_name);
3634 return -EINVAL;
3635 }
3636 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
3637 __func__, mixer_ctl_name, left, right);
3638 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3639 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3640 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3641
3642 return 0;
3643}
3644
Zhou Song2b8f28f2017-09-11 10:51:38 +08003645static int out_set_voip_volume(struct audio_stream_out *stream, float left,
3646 float right)
3647{
3648 struct stream_out *out = (struct stream_out *)stream;
3649 char mixer_ctl_name[] = "App Type Gain";
3650 struct audio_device *adev = out->dev;
3651 struct mixer_ctl *ctl;
3652 uint32_t set_values[4];
3653
3654 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3655 if (!ctl) {
3656 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3657 __func__, mixer_ctl_name);
3658 return -EINVAL;
3659 }
3660
3661 set_values[0] = 0; //0: Rx Session 1:Tx Session
3662 set_values[1] = out->app_type_cfg.app_type;
3663 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3664 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3665
3666 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
3667 return 0;
3668}
3669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670static int out_set_volume(struct audio_stream_out *stream, float left,
3671 float right)
3672{
Eric Laurenta9024de2013-04-04 09:19:12 -07003673 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003674 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303675 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003676
Eric Laurenta9024de2013-04-04 09:19:12 -07003677 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3678 /* only take left channel into account: the API is for stereo anyway */
3679 out->muted = (left == 0.0f);
3680 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003681 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303682 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003683 /*
3684 * Set mute or umute on HDMI passthrough stream.
3685 * Only take left channel into account.
3686 * Mute is 0 and unmute 1
3687 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303688 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303689 } else if (out->format == AUDIO_FORMAT_DSD){
3690 char mixer_ctl_name[128] = "DSD Volume";
3691 struct audio_device *adev = out->dev;
3692 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3693
3694 if (!ctl) {
3695 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3696 __func__, mixer_ctl_name);
3697 return -EINVAL;
3698 }
3699 volume[0] = (int)(AmpToDb(left));
3700 volume[1] = (int)(AmpToDb(right));
3701 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3702 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003703 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303704 pthread_mutex_lock(&out->compr_mute_lock);
3705 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3706 if (!out->a2dp_compress_mute)
3707 ret = out_set_compr_volume(stream, left, right);
3708 out->volume_l = left;
3709 out->volume_r = right;
3710 pthread_mutex_unlock(&out->compr_mute_lock);
3711 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003712 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003713 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08003714 if (!out->standby)
3715 ret = out_set_voip_volume(stream, left, right);
3716 out->volume_l = left;
3717 out->volume_r = right;
3718 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07003719 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 return -ENOSYS;
3722}
3723
Zhou Songc9672822017-08-16 16:01:39 +08003724static void update_frames_written(struct stream_out *out, size_t bytes)
3725{
3726 size_t bpf = 0;
3727
3728 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3729 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3730 bpf = 1;
3731 else if (!is_offload_usecase(out->usecase))
3732 bpf = audio_bytes_per_sample(out->format) *
3733 audio_channel_count_from_out_mask(out->channel_mask);
3734 if (bpf != 0)
3735 out->written += bytes / bpf;
3736}
3737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3739 size_t bytes)
3740{
3741 struct stream_out *out = (struct stream_out *)stream;
3742 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003743 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303744 int channels = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003746 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303747
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303748 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003749
Dhananjay Kumarac341582017-02-23 23:42:25 +05303750 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303751 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303752 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3753 pthread_mutex_unlock(&out->lock);
3754 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303755 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05303756 ALOGD(" %s: sound card is not active/SSR state", __func__);
3757 ret= -EIO;
3758 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303759 }
3760 }
3761
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303762 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303763 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303764 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303765 goto exit;
3766 }
3767
Haynes Mathew George16081042017-05-31 17:16:49 -07003768 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3769 ret = -EINVAL;
3770 goto exit;
3771 }
3772
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303773 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3774 !out->is_iec61937_info_available) {
3775
3776 if (!audio_extn_passthru_is_passthrough_stream(out)) {
3777 out->is_iec61937_info_available = true;
3778 } else if (audio_extn_passthru_is_enabled()) {
3779 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05303780 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05303781
3782 if((out->format == AUDIO_FORMAT_DTS) ||
3783 (out->format == AUDIO_FORMAT_DTS_HD)) {
3784 ret = audio_extn_passthru_update_dts_stream_configuration(out,
3785 buffer, bytes);
3786 if (ret) {
3787 if (ret != -ENOSYS) {
3788 out->is_iec61937_info_available = false;
3789 ALOGD("iec61937 transmission info not yet updated retry");
3790 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303791 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05303792 /* if stream has started and after that there is
3793 * stream config change (iec transmission config)
3794 * then trigger select_device to update backend configuration.
3795 */
3796 out->stream_config_changed = true;
3797 pthread_mutex_lock(&adev->lock);
3798 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303799 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
3800 ret = -EINVAL;
3801 goto exit;
3802 }
Manish Dewangan671a4202017-08-18 17:30:46 +05303803 pthread_mutex_unlock(&adev->lock);
3804 out->stream_config_changed = false;
3805 out->is_iec61937_info_available = true;
3806 }
3807 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303808
Garmond Leung317cbf12017-09-13 16:20:50 -07003809 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303810 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
3811 (out->is_iec61937_info_available == true)) {
3812 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
3813 ret = -EINVAL;
3814 goto exit;
3815 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05303816 }
3817 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303818
3819 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3820 (audio_extn_a2dp_is_suspended())) {
3821 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
3822 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303823 ret = -EIO;
3824 goto exit;
3825 }
3826 }
3827 }
3828
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003829 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003830 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003831 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003832 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3833 ret = voice_extn_compress_voip_start_output_stream(out);
3834 else
3835 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003836 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003837 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003839 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 goto exit;
3841 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303842 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003843 if (last_known_cal_step != -1) {
3844 ALOGD("%s: retry previous failed cal level set", __func__);
3845 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05303846 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003847 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303848
3849 if ((out->is_iec61937_info_available == true) &&
3850 (audio_extn_passthru_is_passthrough_stream(out))&&
3851 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
3852 ret = -EINVAL;
3853 goto exit;
3854 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856
Ashish Jain81eb2a82015-05-13 10:52:34 +05303857 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003858 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303859 adev->is_channel_status_set = true;
3860 }
3861
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003862 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003863 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003864 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003865 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003866 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3867 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303868 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3869 ALOGD("copl(%p):send next track params in gapless", out);
3870 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3871 out->send_next_track_params = false;
3872 out->is_compr_metadata_avail = false;
3873 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003874 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303875 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303876 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003877
Ashish Jain83a6cc22016-06-28 14:34:17 +05303878 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303879 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303880 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303881 pthread_mutex_unlock(&out->lock);
3882 return -EINVAL;
3883 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303884 audio_format_t dst_format = out->hal_op_format;
3885 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303886
3887 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3888 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3889
Ashish Jain83a6cc22016-06-28 14:34:17 +05303890 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303891 dst_format,
3892 buffer,
3893 src_format,
3894 frames);
3895
Ashish Jain83a6cc22016-06-28 14:34:17 +05303896 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303897 bytes_to_write);
3898
3899 /*Convert written bytes in audio flinger format*/
3900 if (ret > 0)
3901 ret = ((ret * format_to_bitwidth_table[out->format]) /
3902 format_to_bitwidth_table[dst_format]);
3903 }
3904 } else
3905 ret = compress_write(out->compr, buffer, bytes);
3906
Zhou Songc9672822017-08-16 16:01:39 +08003907 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
3908 update_frames_written(out, bytes);
3909
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303910 if (ret < 0)
3911 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303912 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303913 /*msg to cb thread only if non blocking write is enabled*/
3914 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303915 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003916 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303917 } else if (-ENETRESET == ret) {
3918 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303919 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303920 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05303921 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05303922 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003923 }
Ashish Jain5106d362016-05-11 19:23:33 +05303924
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303925 /* Call compr start only when non-zero bytes of data is there to be rendered */
3926 if (!out->playback_started && ret > 0) {
3927 int status = compress_start(out->compr);
3928 if (status < 0) {
3929 ret = status;
3930 ALOGE("%s: compr start failed with err %d", __func__, errno);
3931 goto exit;
3932 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003933 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003934 out->playback_started = 1;
3935 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003936
3937 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3938 popcount(out->channel_mask),
3939 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003940 }
3941 pthread_mutex_unlock(&out->lock);
3942 return ret;
3943 } else {
3944 if (out->pcm) {
3945 if (out->muted)
3946 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003947
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303948 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003949
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003950 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003951
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003952 if (out->config.rate)
3953 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3954 out->config.rate;
3955
3956 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3957
3958 request_out_focus(out, ns);
3959
3960 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003961 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003962 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303963 out->convert_buffer != NULL) {
3964
3965 memcpy_by_audio_format(out->convert_buffer,
3966 out->hal_op_format,
3967 buffer,
3968 out->hal_ip_format,
3969 out->config.period_size * out->config.channels);
3970
3971 ret = pcm_write(out->pcm, out->convert_buffer,
3972 (out->config.period_size *
3973 out->config.channels *
3974 format_to_bitwidth_table[out->hal_op_format]));
3975 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303976 /*
3977 * To avoid underrun in DSP when the application is not pumping
3978 * data at required rate, check for the no. of bytes and ignore
3979 * pcm_write if it is less than actual buffer size.
3980 * It is a work around to a change in compress VOIP driver.
3981 */
3982 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3983 bytes < (out->config.period_size * out->config.channels *
3984 audio_bytes_per_sample(out->format))) {
3985 size_t voip_buf_size =
3986 out->config.period_size * out->config.channels *
3987 audio_bytes_per_sample(out->format);
3988 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3989 __func__, bytes, voip_buf_size);
3990 usleep(((uint64_t)voip_buf_size - bytes) *
3991 1000000 / audio_stream_out_frame_size(stream) /
3992 out_get_sample_rate(&out->stream.common));
3993 ret = 0;
3994 } else
3995 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303996 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003997
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003998 release_out_focus(out);
3999
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304000 if (ret < 0)
4001 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004002 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304003 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004004 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005 }
4006
4007exit:
Zhou Songc9672822017-08-16 16:01:39 +08004008 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304009 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304010 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304011 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012 pthread_mutex_unlock(&out->lock);
4013
4014 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004015 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004016 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304017 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304018 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304019 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304020 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304021 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304022 out->standby = true;
4023 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304024 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304025 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4026 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4027 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004028
4029 if (audio_extn_passthru_is_passthrough_stream(out)) {
Garmond Leung317cbf12017-09-13 16:20:50 -07004030 ALOGE("%s: write error, ret = %ld", __func__, ret);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004031 return ret;
4032 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004033 }
4034 return bytes;
4035}
4036
4037static int out_get_render_position(const struct audio_stream_out *stream,
4038 uint32_t *dsp_frames)
4039{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004040 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004041
4042 if (dsp_frames == NULL)
4043 return -EINVAL;
4044
4045 *dsp_frames = 0;
4046 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004047 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304048
4049 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4050 * this operation and adev_close_output_stream(where out gets reset).
4051 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304052 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304053 *dsp_frames = get_actual_pcm_frames_rendered(out);
4054 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
4055 return 0;
4056 }
4057
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004058 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304059 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304060 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004061 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304062 if (ret < 0)
4063 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004064 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304065 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004066 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304067 if (-ENETRESET == ret) {
4068 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304069 out->card_status = CARD_STATUS_OFFLINE;
4070 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304071 } else if(ret < 0) {
4072 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304073 ret = -EINVAL;
4074 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304075 /*
4076 * Handle corner case where compress session is closed during SSR
4077 * and timestamp is queried
4078 */
4079 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304080 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304081 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304082 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05304083 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304084 pthread_mutex_unlock(&out->lock);
4085 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004086 } else if (audio_is_linear_pcm(out->format)) {
4087 *dsp_frames = out->written;
4088 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004089 } else
4090 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091}
4092
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004093static int out_add_audio_effect(const struct audio_stream *stream __unused,
4094 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095{
4096 return 0;
4097}
4098
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004099static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4100 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101{
4102 return 0;
4103}
4104
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004105static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4106 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004107{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304108 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004109}
4110
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004111static int out_get_presentation_position(const struct audio_stream_out *stream,
4112 uint64_t *frames, struct timespec *timestamp)
4113{
4114 struct stream_out *out = (struct stream_out *)stream;
4115 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07004116 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004117
Ashish Jain5106d362016-05-11 19:23:33 +05304118 /* below piece of code is not guarded against any lock because audioFliner serializes
4119 * this operation and adev_close_output_stream( where out gets reset).
4120 */
4121 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304122 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304123 *frames = get_actual_pcm_frames_rendered(out);
4124 /* this is the best we can do */
4125 clock_gettime(CLOCK_MONOTONIC, timestamp);
4126 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4127 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4128 return 0;
4129 }
4130
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004131 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004132
Ashish Jain5106d362016-05-11 19:23:33 +05304133 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4134 ret = compress_get_tstamp(out->compr, &dsp_frames,
4135 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004136 // Adjustment accounts for A2dp encoder latency with offload usecases
4137 // Note: Encoder latency is returned in ms.
4138 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4139 unsigned long offset =
4140 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4141 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4142 }
Ashish Jain5106d362016-05-11 19:23:33 +05304143 ALOGVV("%s rendered frames %ld sample_rate %d",
4144 __func__, dsp_frames, out->sample_rate);
4145 *frames = dsp_frames;
4146 if (ret < 0)
4147 ret = -errno;
4148 if (-ENETRESET == ret) {
4149 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304150 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304151 ret = -EINVAL;
4152 } else
4153 ret = 0;
4154 /* this is the best we can do */
4155 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004156 } else {
4157 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004158 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07004159 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4160 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07004161 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004162 // This adjustment accounts for buffering after app processor.
4163 // It is based on estimated DSP latency per use case, rather than exact.
4164 signed_frames -=
4165 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
4166
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004167 // Adjustment accounts for A2dp encoder latency with non offload usecases
4168 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4169 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4170 signed_frames -=
4171 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4172 }
4173
Eric Laurent949a0892013-09-20 09:20:13 -07004174 // It would be unusual for this value to be negative, but check just in case ...
4175 if (signed_frames >= 0) {
4176 *frames = signed_frames;
4177 ret = 0;
4178 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004179 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304180 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304181 *frames = out->written;
4182 clock_gettime(CLOCK_MONOTONIC, timestamp);
4183 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004184 }
4185 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004186 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004187 return ret;
4188}
4189
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004190static int out_set_callback(struct audio_stream_out *stream,
4191 stream_callback_t callback, void *cookie)
4192{
4193 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004194 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004195
4196 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004197 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004198 out->client_callback = callback;
4199 out->client_cookie = cookie;
4200 if (out->adsp_hdlr_stream_handle) {
4201 ret = audio_extn_adsp_hdlr_stream_set_callback(
4202 out->adsp_hdlr_stream_handle,
4203 callback,
4204 cookie);
4205 if (ret)
4206 ALOGW("%s:adsp hdlr callback registration failed %d",
4207 __func__, ret);
4208 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004209 pthread_mutex_unlock(&out->lock);
4210 return 0;
4211}
4212
4213static int out_pause(struct audio_stream_out* stream)
4214{
4215 struct stream_out *out = (struct stream_out *)stream;
4216 int status = -ENOSYS;
4217 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004218 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004219 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004220 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004221 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304222 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304223 status = compress_pause(out->compr);
4224
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004225 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004226
Mingming Yin21854652016-04-13 11:54:02 -07004227 if (audio_extn_passthru_is_active()) {
4228 ALOGV("offload use case, pause passthru");
4229 audio_extn_passthru_on_pause(out);
4230 }
4231
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304232 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004233 audio_extn_dts_notify_playback_state(out->usecase, 0,
4234 out->sample_rate, popcount(out->channel_mask),
4235 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004236 }
4237 pthread_mutex_unlock(&out->lock);
4238 }
4239 return status;
4240}
4241
4242static int out_resume(struct audio_stream_out* stream)
4243{
4244 struct stream_out *out = (struct stream_out *)stream;
4245 int status = -ENOSYS;
4246 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004247 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004248 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004249 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004250 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004251 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304252 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304253 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004254 }
4255 if (!status) {
4256 out->offload_state = OFFLOAD_STATE_PLAYING;
4257 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304258 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004259 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4260 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004261 }
4262 pthread_mutex_unlock(&out->lock);
4263 }
4264 return status;
4265}
4266
4267static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4268{
4269 struct stream_out *out = (struct stream_out *)stream;
4270 int status = -ENOSYS;
4271 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004272 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004273 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004274 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4275 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4276 else
4277 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4278 pthread_mutex_unlock(&out->lock);
4279 }
4280 return status;
4281}
4282
4283static int out_flush(struct audio_stream_out* stream)
4284{
4285 struct stream_out *out = (struct stream_out *)stream;
4286 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004287 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004288 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004289 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004290 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4291 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004292 } else {
4293 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4294 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08004295 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004296 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004297 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004298 return 0;
4299 }
4300 return -ENOSYS;
4301}
4302
Haynes Mathew George16081042017-05-31 17:16:49 -07004303static int out_stop(const struct audio_stream_out* stream)
4304{
4305 struct stream_out *out = (struct stream_out *)stream;
4306 struct audio_device *adev = out->dev;
4307 int ret = -ENOSYS;
4308
4309 ALOGV("%s", __func__);
4310 pthread_mutex_lock(&adev->lock);
4311 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4312 out->playback_started && out->pcm != NULL) {
4313 pcm_stop(out->pcm);
4314 ret = stop_output_stream(out);
4315 out->playback_started = false;
4316 }
4317 pthread_mutex_unlock(&adev->lock);
4318 return ret;
4319}
4320
4321static int out_start(const struct audio_stream_out* stream)
4322{
4323 struct stream_out *out = (struct stream_out *)stream;
4324 struct audio_device *adev = out->dev;
4325 int ret = -ENOSYS;
4326
4327 ALOGV("%s", __func__);
4328 pthread_mutex_lock(&adev->lock);
4329 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4330 !out->playback_started && out->pcm != NULL) {
4331 ret = start_output_stream(out);
4332 if (ret == 0) {
4333 out->playback_started = true;
4334 }
4335 }
4336 pthread_mutex_unlock(&adev->lock);
4337 return ret;
4338}
4339
4340/*
4341 * Modify config->period_count based on min_size_frames
4342 */
4343static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4344{
4345 int periodCountRequested = (min_size_frames + config->period_size - 1)
4346 / config->period_size;
4347 int periodCount = MMAP_PERIOD_COUNT_MIN;
4348
4349 ALOGV("%s original config.period_size = %d config.period_count = %d",
4350 __func__, config->period_size, config->period_count);
4351
4352 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4353 periodCount *= 2;
4354 }
4355 config->period_count = periodCount;
4356
4357 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4358}
4359
4360static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4361 int32_t min_size_frames,
4362 struct audio_mmap_buffer_info *info)
4363{
4364 struct stream_out *out = (struct stream_out *)stream;
4365 struct audio_device *adev = out->dev;
4366 int ret = 0;
4367 unsigned int offset1;
4368 unsigned int frames1;
4369 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004370 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004371
4372 ALOGV("%s", __func__);
4373 pthread_mutex_lock(&adev->lock);
4374
4375 if (info == NULL || min_size_frames == 0) {
4376 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4377 ret = -EINVAL;
4378 goto exit;
4379 }
4380 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4381 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4382 ret = -ENOSYS;
4383 goto exit;
4384 }
4385 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4386 if (out->pcm_device_id < 0) {
4387 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4388 __func__, out->pcm_device_id, out->usecase);
4389 ret = -EINVAL;
4390 goto exit;
4391 }
4392
4393 adjust_mmap_period_count(&out->config, min_size_frames);
4394
4395 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4396 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4397 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4398 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4399 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4400 step = "open";
4401 ret = -ENODEV;
4402 goto exit;
4403 }
4404 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4405 if (ret < 0) {
4406 step = "begin";
4407 goto exit;
4408 }
4409 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4410 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004411 ret = platform_get_mmap_data_fd(adev->platform,
4412 out->pcm_device_id, 0 /*playback*/,
4413 &info->shared_memory_fd,
4414 &mmap_size);
4415 if (ret < 0) {
4416 step = "get_mmap_fd";
4417 goto exit;
4418 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004419 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004420 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07004421
4422 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4423 if (ret < 0) {
4424 step = "commit";
4425 goto exit;
4426 }
4427
4428 out->standby = false;
4429 ret = 0;
4430
4431 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4432 __func__, info->shared_memory_address, info->buffer_size_frames);
4433
4434exit:
4435 if (ret != 0) {
4436 if (out->pcm == NULL) {
4437 ALOGE("%s: %s - %d", __func__, step, ret);
4438 } else {
4439 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4440 pcm_close(out->pcm);
4441 out->pcm = NULL;
4442 }
4443 }
4444 pthread_mutex_unlock(&adev->lock);
4445 return ret;
4446}
4447
4448static int out_get_mmap_position(const struct audio_stream_out *stream,
4449 struct audio_mmap_position *position)
4450{
4451 struct stream_out *out = (struct stream_out *)stream;
4452 ALOGVV("%s", __func__);
4453 if (position == NULL) {
4454 return -EINVAL;
4455 }
4456 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
4457 return -ENOSYS;
4458 }
4459 if (out->pcm == NULL) {
4460 return -ENOSYS;
4461 }
4462
4463 struct timespec ts = { 0, 0 };
4464 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4465 if (ret < 0) {
4466 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4467 return ret;
4468 }
4469 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4470 return 0;
4471}
4472
4473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474/** audio_stream_in implementation **/
4475static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4476{
4477 struct stream_in *in = (struct stream_in *)stream;
4478
4479 return in->config.rate;
4480}
4481
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004482static int in_set_sample_rate(struct audio_stream *stream __unused,
4483 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004484{
4485 return -ENOSYS;
4486}
4487
4488static size_t in_get_buffer_size(const struct audio_stream *stream)
4489{
4490 struct stream_in *in = (struct stream_in *)stream;
4491
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004492 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4493 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004494 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4495 return VOIP_IO_BUF_SIZE(in->config.rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE);
Mingming Yine62d7842013-10-25 16:26:03 -07004496 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4497 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304498 else if(audio_extn_cin_attached_usecase(in->usecase))
4499 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004500
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004501 return in->config.period_size * in->af_period_multiplier *
4502 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004503}
4504
4505static uint32_t in_get_channels(const struct audio_stream *stream)
4506{
4507 struct stream_in *in = (struct stream_in *)stream;
4508
4509 return in->channel_mask;
4510}
4511
4512static audio_format_t in_get_format(const struct audio_stream *stream)
4513{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004514 struct stream_in *in = (struct stream_in *)stream;
4515
4516 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517}
4518
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004519static int in_set_format(struct audio_stream *stream __unused,
4520 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521{
4522 return -ENOSYS;
4523}
4524
4525static int in_standby(struct audio_stream *stream)
4526{
4527 struct stream_in *in = (struct stream_in *)stream;
4528 struct audio_device *adev = in->dev;
4529 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304530 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4531 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004532 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304533
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004534 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004535 if (!in->standby && in->is_st_session) {
4536 ALOGD("%s: sound trigger pcm stop lab", __func__);
4537 audio_extn_sound_trigger_stop_lab(in);
4538 in->standby = 1;
4539 }
4540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004541 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004542 if (adev->adm_deregister_stream)
4543 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4544
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004545 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004547 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08004548 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08004549 voice_extn_compress_voip_close_input_stream(stream);
4550 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07004551 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4552 do_stop = in->capture_started;
4553 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08004554 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304555 if (audio_extn_cin_attached_usecase(in->usecase))
4556 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08004557 }
4558
4559 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08004560 if (in->pcm) {
4561 pcm_close(in->pcm);
4562 in->pcm = NULL;
4563 }
4564 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004565 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004566 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004567 }
4568 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004569 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004570 return status;
4571}
4572
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004573static int in_dump(const struct audio_stream *stream __unused,
4574 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004575{
4576 return 0;
4577}
4578
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304579static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4580{
4581 if (!stream || !parms)
4582 return;
4583
4584 struct stream_in *in = (struct stream_in *)stream;
4585 struct audio_device *adev = in->dev;
4586
4587 card_status_t status;
4588 int card;
4589 if (parse_snd_card_status(parms, &card, &status) < 0)
4590 return;
4591
4592 pthread_mutex_lock(&adev->lock);
4593 bool valid_cb = (card == adev->snd_card);
4594 pthread_mutex_unlock(&adev->lock);
4595
4596 if (!valid_cb)
4597 return;
4598
4599 lock_input_stream(in);
4600 if (in->card_status != status)
4601 in->card_status = status;
4602 pthread_mutex_unlock(&in->lock);
4603
4604 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4605 use_case_table[in->usecase],
4606 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4607
4608 // a better solution would be to report error back to AF and let
4609 // it put the stream to standby
4610 if (status == CARD_STATUS_OFFLINE)
4611 in_standby(&in->stream.common);
4612
4613 return;
4614}
4615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4617{
4618 struct stream_in *in = (struct stream_in *)stream;
4619 struct audio_device *adev = in->dev;
4620 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004621 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004622 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004623
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304624 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004625 parms = str_parms_create_str(kvpairs);
4626
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304627 if (!parms)
4628 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004629 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004630 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004631
4632 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4633 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004634 val = atoi(value);
4635 /* no audio source uses val == 0 */
4636 if ((in->source != val) && (val != 0)) {
4637 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004638 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4639 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4640 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004641 (in->config.rate == 8000 || in->config.rate == 16000 ||
4642 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004643 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004644 err = voice_extn_compress_voip_open_input_stream(in);
4645 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004646 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004647 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004648 }
4649 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 }
4651 }
4652
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004653 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4654 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004655 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004656 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657 in->device = val;
4658 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004659 if (!in->standby && !in->is_st_session) {
4660 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004661 if (adev->adm_on_routing_change)
4662 adev->adm_on_routing_change(adev->adm_data,
4663 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004664 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004665 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666 }
4667 }
4668
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304669 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4670 if (err >= 0) {
4671 strlcpy(in->profile, value, sizeof(in->profile));
4672 ALOGV("updating stream profile with value '%s'", in->profile);
4673 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4674 &adev->streams_input_cfg_list,
4675 in->device, in->flags, in->format,
4676 in->sample_rate, in->bit_width,
4677 in->profile, &in->app_type_cfg);
4678 }
4679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004680 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004681 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682
4683 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304684error:
Eric Laurent994a6932013-07-17 11:51:42 -07004685 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004686 return ret;
4687}
4688
4689static char* in_get_parameters(const struct audio_stream *stream,
4690 const char *keys)
4691{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004692 struct stream_in *in = (struct stream_in *)stream;
4693 struct str_parms *query = str_parms_create_str(keys);
4694 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004695 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004696
4697 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004698 if (reply) {
4699 str_parms_destroy(reply);
4700 }
4701 if (query) {
4702 str_parms_destroy(query);
4703 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004704 ALOGE("in_get_parameters: failed to create query or reply");
4705 return NULL;
4706 }
4707
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004708 ALOGV("%s: enter: keys - %s", __func__, keys);
4709
4710 voice_extn_in_get_parameters(in, query, reply);
4711
4712 str = str_parms_to_str(reply);
4713 str_parms_destroy(query);
4714 str_parms_destroy(reply);
4715
4716 ALOGV("%s: exit: returns - %s", __func__, str);
4717 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004718}
4719
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004720static int in_set_gain(struct audio_stream_in *stream __unused,
4721 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004722{
4723 return 0;
4724}
4725
4726static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4727 size_t bytes)
4728{
4729 struct stream_in *in = (struct stream_in *)stream;
4730 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304731 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304732 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004733
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004734 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304735
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004736 if (in->is_st_session) {
4737 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4738 /* Read from sound trigger HAL */
4739 audio_extn_sound_trigger_read(in, buffer, bytes);
4740 pthread_mutex_unlock(&in->lock);
4741 return bytes;
4742 }
4743
Haynes Mathew George16081042017-05-31 17:16:49 -07004744 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4745 ret = -ENOSYS;
4746 goto exit;
4747 }
4748
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004749 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004750 pthread_mutex_lock(&adev->lock);
4751 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4752 ret = voice_extn_compress_voip_start_input_stream(in);
4753 else
4754 ret = start_input_stream(in);
4755 pthread_mutex_unlock(&adev->lock);
4756 if (ret != 0) {
4757 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758 }
4759 in->standby = 0;
4760 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004761
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004762 // what's the duration requested by the client?
4763 long ns = 0;
4764
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304765 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004766 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4767 in->config.rate;
4768
4769 request_in_focus(in, ns);
4770 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004771
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304772 if (audio_extn_cin_attached_usecase(in->usecase)) {
4773 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4774 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304775 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004776 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304777 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004778 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004779 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004780 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07004781 } else if (audio_extn_ffv_get_stream() == in) {
4782 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304783 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004784 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304785 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4786 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4787 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4788 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304789 ret = -EINVAL;
4790 goto exit;
4791 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304792 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304793 ret = -errno;
4794 }
4795 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304796 /* bytes read is always set to bytes for non compress usecases */
4797 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798 }
4799
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004800 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004802 /*
4803 * Instead of writing zeroes here, we could trust the hardware
4804 * to always provide zeroes when muted.
4805 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304806 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4807 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004808 memset(buffer, 0, bytes);
4809
4810exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004811 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304812 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004813 pthread_mutex_unlock(&in->lock);
4814
4815 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304816 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304817 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304818 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304819 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304820 in->standby = true;
4821 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304822 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4823 bytes_read = bytes;
4824 memset(buffer, 0, bytes);
4825 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004826 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004827 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304828 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304829 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004830 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304831 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004832}
4833
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004834static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004835{
4836 return 0;
4837}
4838
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004839static int add_remove_audio_effect(const struct audio_stream *stream,
4840 effect_handle_t effect,
4841 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004842{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004843 struct stream_in *in = (struct stream_in *)stream;
4844 int status = 0;
4845 effect_descriptor_t desc;
4846
4847 status = (*effect)->get_descriptor(effect, &desc);
4848 if (status != 0)
4849 return status;
4850
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004851 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004852 pthread_mutex_lock(&in->dev->lock);
4853 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4854 in->enable_aec != enable &&
4855 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4856 in->enable_aec = enable;
4857 if (!in->standby)
4858 select_devices(in->dev, in->usecase);
4859 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004860 if (in->enable_ns != enable &&
4861 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4862 in->enable_ns = enable;
4863 if (!in->standby)
4864 select_devices(in->dev, in->usecase);
4865 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004866 pthread_mutex_unlock(&in->dev->lock);
4867 pthread_mutex_unlock(&in->lock);
4868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004869 return 0;
4870}
4871
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004872static int in_add_audio_effect(const struct audio_stream *stream,
4873 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004874{
Eric Laurent994a6932013-07-17 11:51:42 -07004875 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004876 return add_remove_audio_effect(stream, effect, true);
4877}
4878
4879static int in_remove_audio_effect(const struct audio_stream *stream,
4880 effect_handle_t effect)
4881{
Eric Laurent994a6932013-07-17 11:51:42 -07004882 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004883 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884}
4885
Haynes Mathew George16081042017-05-31 17:16:49 -07004886static int in_stop(const struct audio_stream_in* stream)
4887{
4888 struct stream_in *in = (struct stream_in *)stream;
4889 struct audio_device *adev = in->dev;
4890
4891 int ret = -ENOSYS;
4892 ALOGV("%s", __func__);
4893 pthread_mutex_lock(&adev->lock);
4894 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4895 in->capture_started && in->pcm != NULL) {
4896 pcm_stop(in->pcm);
4897 ret = stop_input_stream(in);
4898 in->capture_started = false;
4899 }
4900 pthread_mutex_unlock(&adev->lock);
4901 return ret;
4902}
4903
4904static int in_start(const struct audio_stream_in* stream)
4905{
4906 struct stream_in *in = (struct stream_in *)stream;
4907 struct audio_device *adev = in->dev;
4908 int ret = -ENOSYS;
4909
4910 ALOGV("%s in %p", __func__, in);
4911 pthread_mutex_lock(&adev->lock);
4912 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4913 !in->capture_started && in->pcm != NULL) {
4914 if (!in->capture_started) {
4915 ret = start_input_stream(in);
4916 if (ret == 0) {
4917 in->capture_started = true;
4918 }
4919 }
4920 }
4921 pthread_mutex_unlock(&adev->lock);
4922 return ret;
4923}
4924
4925static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4926 int32_t min_size_frames,
4927 struct audio_mmap_buffer_info *info)
4928{
4929 struct stream_in *in = (struct stream_in *)stream;
4930 struct audio_device *adev = in->dev;
4931 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004932 unsigned int offset1 = 0;
4933 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07004934 const char *step = "";
4935
4936 pthread_mutex_lock(&adev->lock);
4937 ALOGV("%s in %p", __func__, in);
4938
4939 if (info == NULL || min_size_frames == 0) {
4940 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
4941 ret = -EINVAL;
4942 goto exit;
4943 }
4944 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
4945 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
4946 ALOGV("%s in %p", __func__, in);
4947 ret = -ENOSYS;
4948 goto exit;
4949 }
4950 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4951 if (in->pcm_device_id < 0) {
4952 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4953 __func__, in->pcm_device_id, in->usecase);
4954 ret = -EINVAL;
4955 goto exit;
4956 }
4957
4958 adjust_mmap_period_count(&in->config, min_size_frames);
4959
4960 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4961 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4962 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4963 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4964 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4965 step = "open";
4966 ret = -ENODEV;
4967 goto exit;
4968 }
4969
4970 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4971 if (ret < 0) {
4972 step = "begin";
4973 goto exit;
4974 }
4975 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
4976 info->burst_size_frames = in->config.period_size;
4977 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4978
4979 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
4980 info->buffer_size_frames));
4981
4982 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4983 if (ret < 0) {
4984 step = "commit";
4985 goto exit;
4986 }
4987
4988 in->standby = false;
4989 ret = 0;
4990
4991 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4992 __func__, info->shared_memory_address, info->buffer_size_frames);
4993
4994exit:
4995 if (ret != 0) {
4996 if (in->pcm == NULL) {
4997 ALOGE("%s: %s - %d", __func__, step, ret);
4998 } else {
4999 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5000 pcm_close(in->pcm);
5001 in->pcm = NULL;
5002 }
5003 }
5004 pthread_mutex_unlock(&adev->lock);
5005 return ret;
5006}
5007
5008static int in_get_mmap_position(const struct audio_stream_in *stream,
5009 struct audio_mmap_position *position)
5010{
5011 struct stream_in *in = (struct stream_in *)stream;
5012 ALOGVV("%s", __func__);
5013 if (position == NULL) {
5014 return -EINVAL;
5015 }
5016 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5017 return -ENOSYS;
5018 }
5019 if (in->pcm == NULL) {
5020 return -ENOSYS;
5021 }
5022 struct timespec ts = { 0, 0 };
5023 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5024 if (ret < 0) {
5025 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5026 return ret;
5027 }
5028 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5029 return 0;
5030}
5031
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305032int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005033 audio_io_handle_t handle,
5034 audio_devices_t devices,
5035 audio_output_flags_t flags,
5036 struct audio_config *config,
5037 struct audio_stream_out **stream_out,
5038 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005039{
5040 struct audio_device *adev = (struct audio_device *)dev;
5041 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305042 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005043 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005044 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305045 bool is_direct_passthough = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005047 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005049 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5050
Mingming Yin3a941d42016-02-17 18:08:05 -08005051 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5052 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305053 devices, flags, &out->stream);
5054
5055
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005056 if (!out) {
5057 return -ENOMEM;
5058 }
5059
Haynes Mathew George204045b2015-02-25 20:32:03 -08005060 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005061 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305062 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005063 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005065 if (devices == AUDIO_DEVICE_NONE)
5066 devices = AUDIO_DEVICE_OUT_SPEAKER;
5067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005068 out->flags = flags;
5069 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005070 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005071 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005072 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305073 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305074 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5075 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5076 else
5077 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005078 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005079 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005080 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305081 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305082 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305083 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08005084 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005085
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305086 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Ben Romberger6c4d3812017-06-13 17:46:45 -07005087 (property_get_bool("audio.matrix.limiter.enable", false)))
5088 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5089
Mingming Yin3a941d42016-02-17 18:08:05 -08005090 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5091 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
5092 pthread_mutex_lock(&adev->lock);
5093 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5094 ret = read_hdmi_sink_caps(out);
5095 pthread_mutex_unlock(&adev->lock);
5096 if (ret != 0) {
5097 if (ret == -ENOSYS) {
5098 /* ignore and go with default */
5099 ret = 0;
5100 } else {
5101 ALOGE("error reading hdmi sink caps");
5102 goto error_open;
5103 }
5104 }
5105 }
5106
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005107 /* Init use case and pcm_config */
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305108#ifndef COMPRES_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005109 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5110 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5111 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5112 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5113 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5114 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5115
5116 out->config = default_pcm_config_voip_copp;
5117 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5118 out->config.rate = out->sample_rate;
5119
5120#else
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305121 } 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 -08005122 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005123 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005124 ret = voice_extn_compress_voip_open_output_stream(out);
5125 if (ret != 0) {
5126 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5127 __func__, ret);
5128 goto error_open;
5129 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005130#endif
vivek mehta0ea887a2015-08-26 14:01:20 -07005131 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305132 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305133 pthread_mutex_lock(&adev->lock);
5134 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5135 pthread_mutex_unlock(&adev->lock);
5136
5137 // reject offload during card offline to allow
5138 // fallback to s/w paths
5139 if (offline) {
5140 ret = -ENODEV;
5141 goto error_open;
5142 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005143
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005144 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5145 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5146 ALOGE("%s: Unsupported Offload information", __func__);
5147 ret = -EINVAL;
5148 goto error_open;
5149 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005150
Atul Khare3fa6e542017-08-09 00:56:17 +05305151 if (config->offload_info.format == 0)
5152 config->offload_info.format = config->format;
5153 if (config->offload_info.sample_rate == 0)
5154 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005155
Mingming Yin90310102013-11-13 16:57:00 -08005156 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305157 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005158 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005159 ret = -EINVAL;
5160 goto error_open;
5161 }
5162
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005163 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5164 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5165 (audio_extn_passthru_is_passthrough_stream(out)) &&
5166 !((config->sample_rate == 48000) ||
5167 (config->sample_rate == 96000) ||
5168 (config->sample_rate == 192000))) {
5169 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5170 __func__, config->sample_rate, config->offload_info.format);
5171 ret = -EINVAL;
5172 goto error_open;
5173 }
5174
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005175 out->compr_config.codec = (struct snd_codec *)
5176 calloc(1, sizeof(struct snd_codec));
5177
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005178 if (!out->compr_config.codec) {
5179 ret = -ENOMEM;
5180 goto error_open;
5181 }
5182
Dhananjay Kumarac341582017-02-23 23:42:25 +05305183 out->stream.pause = out_pause;
5184 out->stream.resume = out_resume;
5185 out->stream.flush = out_flush;
5186 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005187 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07005188 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305189 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005190 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305191 } else {
5192 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5193 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005194 }
vivek mehta446c3962015-09-14 10:57:35 -07005195
5196 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005197 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5198 config->format == 0 && config->sample_rate == 0 &&
5199 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005200 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005201 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5202 } else {
5203 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5204 ret = -EEXIST;
5205 goto error_open;
5206 }
vivek mehta446c3962015-09-14 10:57:35 -07005207 }
5208
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005209 if (config->offload_info.channel_mask)
5210 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005211 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005212 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005213 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005214 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305215 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005216 ret = -EINVAL;
5217 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005218 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005219
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005220 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005221 out->sample_rate = config->offload_info.sample_rate;
5222
Mingming Yin3ee55c62014-08-04 14:23:35 -07005223 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005224
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305225 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305226 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305227 audio_extn_dolby_send_ddp_endp_params(adev);
5228 audio_extn_dolby_set_dmid(adev);
5229 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005230
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005231 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005232 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005233 out->compr_config.codec->bit_rate =
5234 config->offload_info.bit_rate;
5235 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305236 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005237 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305238 /* Update bit width only for non passthrough usecases.
5239 * For passthrough usecases, the output will always be opened @16 bit
5240 */
5241 if (!audio_extn_passthru_is_passthrough_stream(out))
5242 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305243
5244 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5245 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5246 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5247
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005248 /*TODO: Do we need to change it for passthrough */
5249 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005250
Manish Dewangana6fc5442015-08-24 20:30:31 +05305251 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5252 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305253 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305254 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305255 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5256 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305257
5258 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5259 AUDIO_FORMAT_PCM) {
5260
5261 /*Based on platform support, configure appropriate alsa format for corresponding
5262 *hal input format.
5263 */
5264 out->compr_config.codec->format = hal_format_to_alsa(
5265 config->offload_info.format);
5266
Ashish Jain83a6cc22016-06-28 14:34:17 +05305267 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305268 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305269 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305270
Dhananjay Kumarac341582017-02-23 23:42:25 +05305271 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305272 *hal input format and alsa format might differ based on platform support.
5273 */
5274 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305275 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305276
5277 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5278
5279 /* Check if alsa session is configured with the same format as HAL input format,
5280 * if not then derive correct fragment size needed to accomodate the
5281 * conversion of HAL input format to alsa format.
5282 */
5283 audio_extn_utils_update_direct_pcm_fragment_size(out);
5284
5285 /*if hal input and output fragment size is different this indicates HAL input format is
5286 *not same as the alsa format
5287 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305288 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305289 /*Allocate a buffer to convert input data to the alsa configured format.
5290 *size of convert buffer is equal to the size required to hold one fragment size
5291 *worth of pcm data, this is because flinger does not write more than fragment_size
5292 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305293 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5294 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305295 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5296 ret = -ENOMEM;
5297 goto error_open;
5298 }
5299 }
5300 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5301 out->compr_config.fragment_size =
5302 audio_extn_passthru_get_buffer_size(&config->offload_info);
5303 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5304 } else {
5305 out->compr_config.fragment_size =
5306 platform_get_compress_offload_buffer_size(&config->offload_info);
5307 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5308 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005309
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305310 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5311 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5312 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005313 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305314 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005315
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305316 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5317 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5318 }
5319
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005320 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5321 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005322
Manish Dewangan69426c82017-01-30 17:35:36 +05305323 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5324 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5325 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5326 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5327 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5328 } else {
5329 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5330 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005331
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305332 memset(&out->channel_map_param, 0,
5333 sizeof(struct audio_out_channel_map_param));
5334
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005335 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305336 out->send_next_track_params = false;
5337 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005338 out->offload_state = OFFLOAD_STATE_IDLE;
5339 out->playback_started = 0;
5340
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005341 audio_extn_dts_create_state_notifier_node(out->usecase);
5342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005343 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5344 __func__, config->offload_info.version,
5345 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305346
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305347 /* Check if DSD audio format is supported in codec
5348 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305349 */
5350
5351 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305352 (!platform_check_codec_dsd_support(adev->platform) ||
5353 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305354 ret = -EINVAL;
5355 goto error_open;
5356 }
5357
Ashish Jain5106d362016-05-11 19:23:33 +05305358 /* Disable gapless if any of the following is true
5359 * passthrough playback
5360 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305361 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305362 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305363 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305364 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005365 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305366 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305367 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305368 check_and_set_gapless_mode(adev, false);
5369 } else
5370 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005371
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305372 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005373 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5374 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305375 if (config->format == AUDIO_FORMAT_DSD) {
5376 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5377 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5378 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005379
5380 create_offload_callback_thread(out);
5381
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005382 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305383 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005384 if (ret != 0) {
5385 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5386 __func__, ret);
5387 goto error_open;
5388 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005389 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5390 if (config->sample_rate == 0)
5391 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5392 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5393 config->sample_rate != 8000) {
5394 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5395 ret = -EINVAL;
5396 goto error_open;
5397 }
5398 out->sample_rate = config->sample_rate;
5399 out->config.rate = config->sample_rate;
5400 if (config->format == AUDIO_FORMAT_DEFAULT)
5401 config->format = AUDIO_FORMAT_PCM_16_BIT;
5402 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5403 config->format = AUDIO_FORMAT_PCM_16_BIT;
5404 ret = -EINVAL;
5405 goto error_open;
5406 }
5407 out->format = config->format;
5408 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5409 out->config = pcm_config_afe_proxy_playback;
5410 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005411 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305412 unsigned int channels = 0;
5413 /*Update config params to default if not set by the caller*/
5414 if (config->sample_rate == 0)
5415 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5416 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5417 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5418 if (config->format == AUDIO_FORMAT_DEFAULT)
5419 config->format = AUDIO_FORMAT_PCM_16_BIT;
5420
5421 channels = audio_channel_count_from_out_mask(out->channel_mask);
5422
Varun Balaraje49253e2017-07-06 19:48:56 +05305423 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
5424 out->usecase = get_interactive_usecase(adev);
5425 out->config = pcm_config_low_latency;
5426 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305427 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005428 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5429 out->flags);
5430 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005431 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5432 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5433 out->config = pcm_config_mmap_playback;
5434 out->stream.start = out_start;
5435 out->stream.stop = out_stop;
5436 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5437 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305438 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5439 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005440 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5441 if (!out->dynamic_pm_qos_enabled) {
5442 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5443 } else {
5444 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5445 //the mixer path will be a string similar to "low-latency-playback resume"
5446 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5447 strlcat(out->pm_qos_mixer_path,
5448 " resume", MAX_MIXER_PATH_LEN);
5449 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5450 out->pm_qos_mixer_path);
5451 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305452 out->config = pcm_config_low_latency;
5453 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5454 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5455 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305456 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5457 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5458 if (out->config.period_size <= 0) {
5459 ALOGE("Invalid configuration period size is not valid");
5460 ret = -EINVAL;
5461 goto error_open;
5462 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305463 } else {
5464 /* primary path is the default path selected if no other outputs are available/suitable */
5465 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5466 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5467 }
5468 out->hal_ip_format = format = out->format;
5469 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5470 out->hal_op_format = pcm_format_to_hal(out->config.format);
5471 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5472 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005473 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305474 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305475 if (out->hal_ip_format != out->hal_op_format) {
5476 uint32_t buffer_size = out->config.period_size *
5477 format_to_bitwidth_table[out->hal_op_format] *
5478 out->config.channels;
5479 out->convert_buffer = calloc(1, buffer_size);
5480 if (out->convert_buffer == NULL){
5481 ALOGE("Allocation failed for convert buffer for size %d",
5482 out->compr_config.fragment_size);
5483 ret = -ENOMEM;
5484 goto error_open;
5485 }
5486 ALOGD("Convert buffer allocated of size %d", buffer_size);
5487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005488 }
5489
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005490 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5491 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305492
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005493 /* TODO remove this hardcoding and check why width is zero*/
5494 if (out->bit_width == 0)
5495 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305496 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005497 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07005498 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305499 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305500 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005501 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5502 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5503 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005504 if(adev->primary_output == NULL)
5505 adev->primary_output = out;
5506 else {
5507 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005508 ret = -EEXIST;
5509 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005510 }
5511 }
5512
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005513 /* Check if this usecase is already existing */
5514 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005515 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5516 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005517 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005518 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005519 ret = -EEXIST;
5520 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005521 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005523 pthread_mutex_unlock(&adev->lock);
5524
5525 out->stream.common.get_sample_rate = out_get_sample_rate;
5526 out->stream.common.set_sample_rate = out_set_sample_rate;
5527 out->stream.common.get_buffer_size = out_get_buffer_size;
5528 out->stream.common.get_channels = out_get_channels;
5529 out->stream.common.get_format = out_get_format;
5530 out->stream.common.set_format = out_set_format;
5531 out->stream.common.standby = out_standby;
5532 out->stream.common.dump = out_dump;
5533 out->stream.common.set_parameters = out_set_parameters;
5534 out->stream.common.get_parameters = out_get_parameters;
5535 out->stream.common.add_audio_effect = out_add_audio_effect;
5536 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5537 out->stream.get_latency = out_get_latency;
5538 out->stream.set_volume = out_set_volume;
5539 out->stream.write = out_write;
5540 out->stream.get_render_position = out_get_render_position;
5541 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005542 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005543
Haynes Mathew George16081042017-05-31 17:16:49 -07005544 if (out->realtime)
5545 out->af_period_multiplier = af_period_multiplier;
5546 else
5547 out->af_period_multiplier = 1;
5548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005549 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005550 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005551 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005552
5553 config->format = out->stream.common.get_format(&out->stream.common);
5554 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5555 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5556
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305557 /*
5558 By locking output stream before registering, we allow the callback
5559 to update stream's state only after stream's initial state is set to
5560 adev state.
5561 */
5562 lock_output_stream(out);
5563 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5564 pthread_mutex_lock(&adev->lock);
5565 out->card_status = adev->card_status;
5566 pthread_mutex_unlock(&adev->lock);
5567 pthread_mutex_unlock(&out->lock);
5568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005569 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305570 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07005571 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005572
5573 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
5574 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5575 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005576 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05305577 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005578 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005579 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05305580 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005581 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5582 out->usecase, PCM_PLAYBACK);
5583 hdlr_stream_cfg.flags = out->flags;
5584 hdlr_stream_cfg.type = PCM_PLAYBACK;
5585 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5586 &hdlr_stream_cfg);
5587 if (ret) {
5588 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5589 out->adsp_hdlr_stream_handle = NULL;
5590 }
5591 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05305592 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07005593 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07005594 if (ret < 0) {
5595 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5596 out->ip_hdlr_handle = NULL;
5597 }
5598 }
Eric Laurent994a6932013-07-17 11:51:42 -07005599 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005600 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005601
5602error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305603 if (out->convert_buffer)
5604 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005605 free(out);
5606 *stream_out = NULL;
5607 ALOGD("%s: exit: ret %d", __func__, ret);
5608 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005609}
5610
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305611void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005612 struct audio_stream_out *stream)
5613{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005614 struct stream_out *out = (struct stream_out *)stream;
5615 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005616 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005617
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305618 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
5619
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305620 // must deregister from sndmonitor first to prevent races
5621 // between the callback and close_stream
5622 audio_extn_snd_mon_unregister_listener(out);
5623
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005624 /* close adsp hdrl session before standby */
5625 if (out->adsp_hdlr_stream_handle) {
5626 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5627 if (ret)
5628 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5629 out->adsp_hdlr_stream_handle = NULL;
5630 }
5631
Manish Dewangan21a850a2017-08-14 12:03:55 +05305632 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07005633 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5634 out->ip_hdlr_handle = NULL;
5635 }
5636
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005637 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305638 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005639 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305640 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305641 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005642 if(ret != 0)
5643 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5644 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005645 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005646 out_standby(&stream->common);
5647
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005648 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005649 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005650 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005651 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005652 if (out->compr_config.codec != NULL)
5653 free(out->compr_config.codec);
5654 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005655
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305656 out->a2dp_compress_mute = false;
5657
Varun Balaraje49253e2017-07-06 19:48:56 +05305658 if (is_interactive_usecase(out->usecase))
5659 free_interactive_usecase(adev, out->usecase);
5660
Ashish Jain83a6cc22016-06-28 14:34:17 +05305661 if (out->convert_buffer != NULL) {
5662 free(out->convert_buffer);
5663 out->convert_buffer = NULL;
5664 }
5665
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005666 if (adev->voice_tx_output == out)
5667 adev->voice_tx_output = NULL;
5668
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305669 if (adev->primary_output == out)
5670 adev->primary_output = NULL;
5671
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005672 pthread_cond_destroy(&out->cond);
5673 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005674 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005675 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005676}
5677
5678static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5679{
5680 struct audio_device *adev = (struct audio_device *)dev;
5681 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005682 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005683 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005684 int ret;
5685 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005686
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005687 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005688 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005689
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305690 if (!parms)
5691 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305692
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305693 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5694 if (ret >= 0) {
5695 /* When set to false, HAL should disable EC and NS */
5696 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5697 adev->bt_sco_on = true;
5698 else
5699 adev->bt_sco_on = false;
5700 }
5701
Naresh Tanniru4c630392014-05-12 01:05:52 +05305702 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005703 status = voice_set_parameters(adev, parms);
5704 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005705 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005706
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005707 status = platform_set_parameters(adev->platform, parms);
5708 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005709 goto done;
5710
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005711 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5712 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005713 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005714 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5715 adev->bluetooth_nrec = true;
5716 else
5717 adev->bluetooth_nrec = false;
5718 }
5719
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005720 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5721 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005722 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5723 adev->screen_off = false;
5724 else
5725 adev->screen_off = true;
5726 }
5727
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005728 ret = str_parms_get_int(parms, "rotation", &val);
5729 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005730 bool reverse_speakers = false;
5731 switch(val) {
5732 // FIXME: note that the code below assumes that the speakers are in the correct placement
5733 // relative to the user when the device is rotated 90deg from its default rotation. This
5734 // assumption is device-specific, not platform-specific like this code.
5735 case 270:
5736 reverse_speakers = true;
5737 break;
5738 case 0:
5739 case 90:
5740 case 180:
5741 break;
5742 default:
5743 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005744 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005745 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005746 if (status == 0) {
5747 if (adev->speaker_lr_swap != reverse_speakers) {
5748 adev->speaker_lr_swap = reverse_speakers;
5749 // only update the selected device if there is active pcm playback
5750 struct audio_usecase *usecase;
5751 struct listnode *node;
5752 list_for_each(node, &adev->usecase_list) {
5753 usecase = node_to_item(node, struct audio_usecase, list);
5754 if (usecase->type == PCM_PLAYBACK) {
5755 select_devices(adev, usecase->id);
5756 break;
5757 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005758 }
5759 }
5760 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005761 }
5762
Mingming Yin514a8bc2014-07-29 15:22:21 -07005763 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5764 if (ret >= 0) {
5765 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5766 adev->bt_wb_speech_enabled = true;
5767 else
5768 adev->bt_wb_speech_enabled = false;
5769 }
5770
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005771 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5772 if (ret >= 0) {
5773 val = atoi(value);
5774 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005775 ALOGV("cache new ext disp type and edid");
5776 ret = platform_get_ext_disp_type(adev->platform);
5777 if (ret < 0) {
5778 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08005779 status = ret;
5780 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005781 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005782 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005783 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005784 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07005785 /*
5786 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
5787 * Per AudioPolicyManager, USB device is higher priority than WFD.
5788 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
5789 * If WFD use case occupies AFE proxy, it may result unintended behavior while
5790 * starting voice call on USB
5791 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005792 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5793 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08005794 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5795 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005796 }
vivek mehta344576a2016-04-12 18:56:03 -07005797 ALOGV("detected USB connect .. disable proxy");
5798 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005799 }
5800 }
5801
5802 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5803 if (ret >= 0) {
5804 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07005805 /*
5806 * The HDMI / Displayport disconnect handling has been moved to
5807 * audio extension to ensure that its parameters are not
5808 * invalidated prior to updating sysfs of the disconnect event
5809 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
5810 */
5811 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005812 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005813 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5814 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05305815 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5816 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005817 }
vivek mehta344576a2016-04-12 18:56:03 -07005818 ALOGV("detected USB disconnect .. enable proxy");
5819 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005820 }
5821 }
5822
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305823 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5824 if (ret >= 0) {
5825 struct audio_usecase *usecase;
5826 struct listnode *node;
5827 list_for_each(node, &adev->usecase_list) {
5828 usecase = node_to_item(node, struct audio_usecase, list);
5829 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005830 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305831 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005832
5833 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305834 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005835 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305836 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305837 //force device switch to re configure encoder
5838 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305839 audio_extn_a2dp_set_handoff_mode(false);
5840 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305841 break;
5842 }
5843 }
5844 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005845
5846 //handle vr audio setparam
5847 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5848 value, sizeof(value));
5849 if (ret >= 0) {
5850 ALOGI("Setting vr mode to be %s", value);
5851 if (!strncmp(value, "true", 4)) {
5852 adev->vr_audio_mode_enabled = true;
5853 ALOGI("Setting vr mode to true");
5854 } else if (!strncmp(value, "false", 5)) {
5855 adev->vr_audio_mode_enabled = false;
5856 ALOGI("Setting vr mode to false");
5857 } else {
5858 ALOGI("wrong vr mode set");
5859 }
5860 }
5861
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305862 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005863done:
5864 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005865 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305866error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005867 ALOGV("%s: exit with code(%d)", __func__, status);
5868 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005869}
5870
5871static char* adev_get_parameters(const struct audio_hw_device *dev,
5872 const char *keys)
5873{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005874 struct audio_device *adev = (struct audio_device *)dev;
5875 struct str_parms *reply = str_parms_create();
5876 struct str_parms *query = str_parms_create_str(keys);
5877 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305878 char value[256] = {0};
5879 int ret = 0;
5880
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005881 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005882 if (reply) {
5883 str_parms_destroy(reply);
5884 }
5885 if (query) {
5886 str_parms_destroy(query);
5887 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005888 ALOGE("adev_get_parameters: failed to create query or reply");
5889 return NULL;
5890 }
5891
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005892 //handle vr audio getparam
5893
5894 ret = str_parms_get_str(query,
5895 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5896 value, sizeof(value));
5897
5898 if (ret >= 0) {
5899 bool vr_audio_enabled = false;
5900 pthread_mutex_lock(&adev->lock);
5901 vr_audio_enabled = adev->vr_audio_mode_enabled;
5902 pthread_mutex_unlock(&adev->lock);
5903
5904 ALOGI("getting vr mode to %d", vr_audio_enabled);
5905
5906 if (vr_audio_enabled) {
5907 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5908 "true");
5909 goto exit;
5910 } else {
5911 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5912 "false");
5913 goto exit;
5914 }
5915 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005916
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005917 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005918 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005919 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005920 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305921 pthread_mutex_unlock(&adev->lock);
5922
Naresh Tannirud7205b62014-06-20 02:54:48 +05305923exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005924 str = str_parms_to_str(reply);
5925 str_parms_destroy(query);
5926 str_parms_destroy(reply);
5927
5928 ALOGV("%s: exit: returns - %s", __func__, str);
5929 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005930}
5931
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005932static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005933{
5934 return 0;
5935}
5936
5937static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5938{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005939 int ret;
5940 struct audio_device *adev = (struct audio_device *)dev;
5941 pthread_mutex_lock(&adev->lock);
5942 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005943 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005944 pthread_mutex_unlock(&adev->lock);
5945 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005946}
5947
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005948static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5949 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005950{
5951 return -ENOSYS;
5952}
5953
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005954static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5955 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005956{
5957 return -ENOSYS;
5958}
5959
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005960static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5961 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005962{
5963 return -ENOSYS;
5964}
5965
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005966static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5967 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005968{
5969 return -ENOSYS;
5970}
5971
5972static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5973{
5974 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005976 pthread_mutex_lock(&adev->lock);
5977 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005978 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005979 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005980 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005981 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005982 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005983 adev->current_call_output = NULL;
5984 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005985 }
5986 pthread_mutex_unlock(&adev->lock);
5987 return 0;
5988}
5989
5990static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5991{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005992 int ret;
5993
5994 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005995 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005996 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5997 pthread_mutex_unlock(&adev->lock);
5998
5999 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006000}
6001
6002static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6003{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006004 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006005 return 0;
6006}
6007
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006008static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006009 const struct audio_config *config)
6010{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006011 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006012
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006013 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6014 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006015}
6016
6017static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006018 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006019 audio_devices_t devices,
6020 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006021 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306022 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006023 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006024 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006025{
6026 struct audio_device *adev = (struct audio_device *)dev;
6027 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006028 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006029 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006030 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306031 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306032
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006033 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306034 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
6035 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006036 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306037 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006038
6039 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006040
6041 if (!in) {
6042 ALOGE("failed to allocate input stream");
6043 return -ENOMEM;
6044 }
6045
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306046 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306047 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
6048 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006049 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006050 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006052 in->stream.common.get_sample_rate = in_get_sample_rate;
6053 in->stream.common.set_sample_rate = in_set_sample_rate;
6054 in->stream.common.get_buffer_size = in_get_buffer_size;
6055 in->stream.common.get_channels = in_get_channels;
6056 in->stream.common.get_format = in_get_format;
6057 in->stream.common.set_format = in_set_format;
6058 in->stream.common.standby = in_standby;
6059 in->stream.common.dump = in_dump;
6060 in->stream.common.set_parameters = in_set_parameters;
6061 in->stream.common.get_parameters = in_get_parameters;
6062 in->stream.common.add_audio_effect = in_add_audio_effect;
6063 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6064 in->stream.set_gain = in_set_gain;
6065 in->stream.read = in_read;
6066 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6067
6068 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006069 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006070 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006071 in->standby = 1;
6072 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006073 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006074 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006075
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306076 in->usecase = USECASE_AUDIO_RECORD;
6077 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006078 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306079 is_low_latency = true;
6080#if LOW_LATENCY_CAPTURE_USE_CASE
6081 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
6082#endif
6083 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
6084 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006085 in->format = config->format;
Haynes Mathew George16081042017-05-31 17:16:49 -07006086 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6087 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
6088 in->realtime = 0;
6089 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6090 in->config = pcm_config_mmap_capture;
6091 in->stream.start = in_start;
6092 in->stream.stop = in_stop;
6093 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6094 in->stream.get_mmap_position = in_get_mmap_position;
6095 in->af_period_multiplier = 1;
6096 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
6097 } else if (in->realtime) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006098 in->config = pcm_config_audio_capture_rt;
6099 in->sample_rate = in->config.rate;
6100 in->af_period_multiplier = af_period_multiplier;
6101 } else {
6102 in->config = pcm_config_audio_capture;
6103 in->config.rate = config->sample_rate;
6104 in->sample_rate = config->sample_rate;
6105 in->af_period_multiplier = 1;
6106 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306107 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006108
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306109 /* restrict 24 bit capture for unprocessed source only
6110 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
6111 */
6112 if (config->format == AUDIO_FORMAT_DEFAULT) {
6113 config->format = AUDIO_FORMAT_PCM_16_BIT;
6114 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6115 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6116 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6117 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6118 bool ret_error = false;
6119 in->bit_width = 24;
6120 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6121 from HAL is 24_packed and 8_24
6122 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6123 24_packed return error indicating supported format is 24_packed
6124 *> In case of any other source requesting 24 bit or float return error
6125 indicating format supported is 16 bit only.
6126
6127 on error flinger will retry with supported format passed
6128 */
6129 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6130 (source != AUDIO_SOURCE_CAMCORDER)) {
6131 config->format = AUDIO_FORMAT_PCM_16_BIT;
6132 if (config->sample_rate > 48000)
6133 config->sample_rate = 48000;
6134 ret_error = true;
6135 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
6136 in->config.format = PCM_FORMAT_S24_3LE;
6137 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
6138 in->config.format = PCM_FORMAT_S24_LE;
6139 } else {
6140 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
6141 ret_error = true;
6142 }
6143
6144 if (ret_error) {
6145 ret = -EINVAL;
6146 goto err_open;
6147 }
6148 }
6149
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306150 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306151 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6152 (adev->mode != AUDIO_MODE_IN_CALL)) {
6153 ret = -EINVAL;
6154 goto err_open;
6155 }
6156
6157 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
6158 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006159 if (config->sample_rate == 0)
6160 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6161 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6162 config->sample_rate != 8000) {
6163 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6164 ret = -EINVAL;
6165 goto err_open;
6166 }
6167 if (config->format == AUDIO_FORMAT_DEFAULT)
6168 config->format = AUDIO_FORMAT_PCM_16_BIT;
6169 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6170 config->format = AUDIO_FORMAT_PCM_16_BIT;
6171 ret = -EINVAL;
6172 goto err_open;
6173 }
6174
6175 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6176 in->config = pcm_config_afe_proxy_record;
6177 in->config.channels = channel_count;
6178 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306179 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306180 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
6181 in, config, &channel_mask_updated)) {
6182 if (channel_mask_updated == true) {
6183 ALOGD("%s: return error to retry with updated channel mask (%#x)",
6184 __func__, config->channel_mask);
6185 ret = -EINVAL;
6186 goto err_open;
6187 }
Garmond Leunge2433c32017-09-28 21:51:22 -07006188 ALOGD("%s: created multi-channel session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07006189 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006190 audio_extn_compr_cap_format_supported(config->format) &&
6191 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006192 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306193 } else if (audio_extn_cin_applicable_stream(in)) {
6194 ret = audio_extn_cin_configure_input_stream(in);
6195 if (ret)
6196 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006197 } else {
6198 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006199 if (!in->realtime) {
6200 in->format = config->format;
6201 frame_size = audio_stream_in_frame_size(&in->stream);
6202 buffer_size = get_input_buffer_size(config->sample_rate,
6203 config->format,
6204 channel_count,
6205 is_low_latency);
6206 in->config.period_size = buffer_size / frame_size;
6207 }
6208
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006209#ifndef COMPRESS_VOIP_ENABLED
6210 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6211 (in->config.rate == 8000 || in->config.rate == 16000 ||
6212 in->config.rate == 32000 || in->config.rate == 48000) &&
6213 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6214
6215 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6216 in->config = default_pcm_config_voip_copp;
6217 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6218 in->config.rate = in->sample_rate;
6219#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006220 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006221 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6222 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006223 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006224 (in->config.rate == 8000 || in->config.rate == 16000 ||
6225 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006226 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6227 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006228#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006229 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006230 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006231
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306232 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6233 &adev->streams_input_cfg_list,
6234 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306235 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306236
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006237 /* This stream could be for sound trigger lab,
6238 get sound trigger pcm if present */
6239 audio_extn_sound_trigger_check_and_get_session(in);
6240
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306241 lock_input_stream(in);
6242 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6243 pthread_mutex_lock(&adev->lock);
6244 in->card_status = adev->card_status;
6245 pthread_mutex_unlock(&adev->lock);
6246 pthread_mutex_unlock(&in->lock);
6247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006248 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006249 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006250 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006251
6252err_open:
6253 free(in);
6254 *stream_in = NULL;
6255 return ret;
6256}
6257
6258static void adev_close_input_stream(struct audio_hw_device *dev,
6259 struct audio_stream_in *stream)
6260{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006261 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006262 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006263 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306264
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306265 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006266
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306267 // must deregister from sndmonitor first to prevent races
6268 // between the callback and close_stream
6269 audio_extn_snd_mon_unregister_listener(stream);
6270
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306271 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006272 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306273
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006274 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306275 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006276 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306277 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006278 if (ret != 0)
6279 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6280 __func__, ret);
6281 } else
6282 in_standby(&stream->common);
6283
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006284 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006285 audio_extn_ssr_deinit();
6286 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006287
Garmond Leunge2433c32017-09-28 21:51:22 -07006288 if (audio_extn_ffv_get_stream() == in) {
6289 audio_extn_ffv_stream_deinit();
6290 }
6291
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306292 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006293 audio_extn_compr_cap_format_supported(in->config.format))
6294 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306295
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306296 if (audio_extn_cin_attached_usecase(in->usecase))
6297 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006298
Mingming Yinfd7607b2016-01-22 12:48:44 -08006299 if (in->is_st_session) {
6300 ALOGV("%s: sound trigger pcm stop lab", __func__);
6301 audio_extn_sound_trigger_stop_lab(in);
6302 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006303 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006304 return;
6305}
6306
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306307int adev_create_audio_patch(struct audio_hw_device *dev,
6308 unsigned int num_sources,
6309 const struct audio_port_config *sources,
6310 unsigned int num_sinks,
6311 const struct audio_port_config *sinks,
6312 audio_patch_handle_t *handle)
6313{
6314
6315
6316 return audio_extn_hw_loopback_create_audio_patch(dev,
6317 num_sources,
6318 sources,
6319 num_sinks,
6320 sinks,
6321 handle);
6322
6323}
6324
6325int adev_release_audio_patch(struct audio_hw_device *dev,
6326 audio_patch_handle_t handle)
6327{
6328 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6329}
6330
6331int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6332{
6333 return audio_extn_hw_loopback_get_audio_port(dev, config);
6334}
6335
6336int adev_set_audio_port_config(struct audio_hw_device *dev,
6337 const struct audio_port_config *config)
6338{
6339 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6340}
6341
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006342static int adev_dump(const audio_hw_device_t *device __unused,
6343 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006344{
6345 return 0;
6346}
6347
6348static int adev_close(hw_device_t *device)
6349{
6350 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006351
6352 if (!adev)
6353 return 0;
6354
6355 pthread_mutex_lock(&adev_init_lock);
6356
6357 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306358 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006359 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006360 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306361 audio_extn_utils_release_streams_cfg_lists(
6362 &adev->streams_output_cfg_list,
6363 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306364 if (audio_extn_qaf_is_enabled())
6365 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006366 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006367 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006368 free(adev->snd_dev_ref_cnt);
6369 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006370 if (adev->adm_deinit)
6371 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306372 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006373 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306374 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306375 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07006376 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306377 if (adev->device_cfg_params) {
6378 free(adev->device_cfg_params);
6379 adev->device_cfg_params = NULL;
6380 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006381 free(device);
6382 adev = NULL;
6383 }
6384 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006386 return 0;
6387}
6388
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006389/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6390 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6391 * just that it _might_ work.
6392 */
6393static int period_size_is_plausible_for_low_latency(int period_size)
6394{
6395 switch (period_size) {
6396 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006397 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006398 case 240:
6399 case 320:
6400 case 480:
6401 return 1;
6402 default:
6403 return 0;
6404 }
6405}
6406
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306407static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6408{
6409 bool is_snd_card_status = false;
6410 bool is_ext_device_status = false;
6411 char value[32];
6412 int card = -1;
6413 card_status_t status;
6414
6415 if (cookie != adev || !parms)
6416 return;
6417
6418 if (!parse_snd_card_status(parms, &card, &status)) {
6419 is_snd_card_status = true;
6420 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6421 is_ext_device_status = true;
6422 } else {
6423 // not a valid event
6424 return;
6425 }
6426
6427 pthread_mutex_lock(&adev->lock);
6428 if (card == adev->snd_card || is_ext_device_status) {
6429 if (is_snd_card_status && adev->card_status != status) {
6430 adev->card_status = status;
6431 platform_snd_card_update(adev->platform, status);
6432 audio_extn_fm_set_parameters(adev, parms);
6433 } else if (is_ext_device_status) {
6434 platform_set_parameters(adev->platform, parms);
6435 }
6436 }
6437 pthread_mutex_unlock(&adev->lock);
6438 return;
6439}
6440
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306441/* out and adev lock held */
6442static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6443{
6444 struct audio_usecase *uc_info;
6445 float left_p;
6446 float right_p;
6447 audio_devices_t devices;
6448
6449 uc_info = get_usecase_from_list(adev, out->usecase);
6450 if (uc_info == NULL) {
6451 ALOGE("%s: Could not find the usecase (%d) in the list",
6452 __func__, out->usecase);
6453 return -EINVAL;
6454 }
6455
6456 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6457 out->usecase, use_case_table[out->usecase]);
6458
6459 if (restore) {
6460 // restore A2DP device for active usecases and unmute if required
6461 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6462 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6463 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6464 select_devices(adev, uc_info->id);
6465 pthread_mutex_lock(&out->compr_mute_lock);
6466 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6467 (out->a2dp_compress_mute)) {
6468 out->a2dp_compress_mute = false;
6469 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6470 }
6471 pthread_mutex_unlock(&out->compr_mute_lock);
6472 }
6473 } else {
6474 // mute compress stream if suspended
6475 pthread_mutex_lock(&out->compr_mute_lock);
6476 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6477 (!out->a2dp_compress_mute)) {
6478 if (!out->standby) {
6479 ALOGD("%s: selecting speaker and muting stream", __func__);
6480 devices = out->devices;
6481 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6482 left_p = out->volume_l;
6483 right_p = out->volume_r;
6484 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6485 compress_pause(out->compr);
6486 out_set_compr_volume(&out->stream, (float)0, (float)0);
6487 out->a2dp_compress_mute = true;
6488 select_devices(adev, out->usecase);
6489 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6490 compress_resume(out->compr);
6491 out->devices = devices;
6492 out->volume_l = left_p;
6493 out->volume_r = right_p;
6494 }
6495 }
6496 pthread_mutex_unlock(&out->compr_mute_lock);
6497 }
6498 ALOGV("%s: exit", __func__);
6499 return 0;
6500}
6501
6502int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6503{
6504 int ret = 0;
6505
6506 lock_output_stream(out);
6507 pthread_mutex_lock(&adev->lock);
6508
6509 ret = check_a2dp_restore_l(adev, out, restore);
6510
6511 pthread_mutex_unlock(&adev->lock);
6512 pthread_mutex_unlock(&out->lock);
6513 return ret;
6514}
6515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006516static int adev_open(const hw_module_t *module, const char *name,
6517 hw_device_t **device)
6518{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306519 int ret;
6520
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006521 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006522 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
6523
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006524 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07006525 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006526 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07006527 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006528 ALOGD("%s: returning existing instance of adev", __func__);
6529 ALOGD("%s: exit", __func__);
6530 pthread_mutex_unlock(&adev_init_lock);
6531 return 0;
6532 }
6533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006534 adev = calloc(1, sizeof(struct audio_device));
6535
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006536 if (!adev) {
6537 pthread_mutex_unlock(&adev_init_lock);
6538 return -ENOMEM;
6539 }
6540
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006541 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6542
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05306543#ifdef DYNAMIC_LOG_ENABLED
6544 register_for_dynamic_logging("hal");
6545#endif
6546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006547 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6548 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6549 adev->device.common.module = (struct hw_module_t *)module;
6550 adev->device.common.close = adev_close;
6551
6552 adev->device.init_check = adev_init_check;
6553 adev->device.set_voice_volume = adev_set_voice_volume;
6554 adev->device.set_master_volume = adev_set_master_volume;
6555 adev->device.get_master_volume = adev_get_master_volume;
6556 adev->device.set_master_mute = adev_set_master_mute;
6557 adev->device.get_master_mute = adev_get_master_mute;
6558 adev->device.set_mode = adev_set_mode;
6559 adev->device.set_mic_mute = adev_set_mic_mute;
6560 adev->device.get_mic_mute = adev_get_mic_mute;
6561 adev->device.set_parameters = adev_set_parameters;
6562 adev->device.get_parameters = adev_get_parameters;
6563 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6564 adev->device.open_output_stream = adev_open_output_stream;
6565 adev->device.close_output_stream = adev_close_output_stream;
6566 adev->device.open_input_stream = adev_open_input_stream;
6567 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306568 adev->device.create_audio_patch = adev_create_audio_patch;
6569 adev->device.release_audio_patch = adev_release_audio_patch;
6570 adev->device.get_audio_port = adev_get_audio_port;
6571 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006572 adev->device.dump = adev_dump;
6573
6574 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006575 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08006576 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006577 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006578 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006579 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006580 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07006581 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306582 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006583 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006584 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006585 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006586 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08006587 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006588 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05306589 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306590 adev->perf_lock_opts[0] = 0x101;
6591 adev->perf_lock_opts[1] = 0x20E;
6592 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006593 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306594
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006595 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006596 adev->platform = platform_init(adev);
6597 if (!adev->platform) {
6598 free(adev->snd_dev_ref_cnt);
6599 free(adev);
6600 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6601 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006602 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306603 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006604 return -EINVAL;
6605 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006606
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306607 if (audio_extn_qaf_is_enabled()) {
6608 ret = audio_extn_qaf_init(adev);
6609 if (ret < 0) {
6610 free(adev);
6611 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6612 *device = NULL;
6613 pthread_mutex_unlock(&adev_init_lock);
6614 pthread_mutex_destroy(&adev->lock);
6615 return ret;
6616 }
6617
6618 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6619 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6620 }
6621
Eric Laurentc4aef752013-09-12 17:45:53 -07006622 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6623 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6624 if (adev->visualizer_lib == NULL) {
6625 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6626 } else {
6627 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6628 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006629 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006630 "visualizer_hal_start_output");
6631 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006632 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006633 "visualizer_hal_stop_output");
6634 }
6635 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05306636 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08006637 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006638 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306639 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07006640 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07006641
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006642 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
6643 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6644 if (adev->offload_effects_lib == NULL) {
6645 ALOGE("%s: DLOPEN failed for %s", __func__,
6646 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6647 } else {
6648 ALOGV("%s: DLOPEN successful for %s", __func__,
6649 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6650 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05306651 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006652 "offload_effects_bundle_hal_start_output");
6653 adev->offload_effects_stop_output =
6654 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6655 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006656 adev->offload_effects_set_hpx_state =
6657 (int (*)(bool))dlsym(adev->offload_effects_lib,
6658 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05306659 adev->offload_effects_get_parameters =
6660 (void (*)(struct str_parms *, struct str_parms *))
6661 dlsym(adev->offload_effects_lib,
6662 "offload_effects_bundle_get_parameters");
6663 adev->offload_effects_set_parameters =
6664 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
6665 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006666 }
6667 }
6668
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006669 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
6670 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6671 if (adev->adm_lib == NULL) {
6672 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6673 } else {
6674 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6675 adev->adm_init = (adm_init_t)
6676 dlsym(adev->adm_lib, "adm_init");
6677 adev->adm_deinit = (adm_deinit_t)
6678 dlsym(adev->adm_lib, "adm_deinit");
6679 adev->adm_register_input_stream = (adm_register_input_stream_t)
6680 dlsym(adev->adm_lib, "adm_register_input_stream");
6681 adev->adm_register_output_stream = (adm_register_output_stream_t)
6682 dlsym(adev->adm_lib, "adm_register_output_stream");
6683 adev->adm_deregister_stream = (adm_deregister_stream_t)
6684 dlsym(adev->adm_lib, "adm_deregister_stream");
6685 adev->adm_request_focus = (adm_request_focus_t)
6686 dlsym(adev->adm_lib, "adm_request_focus");
6687 adev->adm_abandon_focus = (adm_abandon_focus_t)
6688 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006689 adev->adm_set_config = (adm_set_config_t)
6690 dlsym(adev->adm_lib, "adm_set_config");
6691 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6692 dlsym(adev->adm_lib, "adm_request_focus_v2");
6693 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6694 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6695 adev->adm_on_routing_change = (adm_on_routing_change_t)
6696 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006697 }
6698 }
6699
Mingming Yin514a8bc2014-07-29 15:22:21 -07006700 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006701 //initialize this to false for now,
6702 //this will be set to true through set param
6703 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07006704
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07006705 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006706 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006707 adev->dsp_bit_width_enforce_mode =
6708 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006709
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306710 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
6711 &adev->streams_output_cfg_list,
6712 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006713
Kiran Kandi910e1862013-10-29 13:29:42 -07006714 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006715
6716 char value[PROPERTY_VALUE_MAX];
6717 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006718 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006719 trial = atoi(value);
6720 if (period_size_is_plausible_for_low_latency(trial)) {
6721 pcm_config_low_latency.period_size = trial;
6722 pcm_config_low_latency.start_threshold = trial / 4;
6723 pcm_config_low_latency.avail_min = trial / 4;
6724 configured_low_latency_capture_period_size = trial;
6725 }
6726 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006727 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006728 trial = atoi(value);
6729 if (period_size_is_plausible_for_low_latency(trial)) {
6730 configured_low_latency_capture_period_size = trial;
6731 }
6732 }
6733
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006734 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006735 af_period_multiplier = atoi(value);
6736 if (af_period_multiplier < 0)
6737 af_period_multiplier = 2;
6738 else if (af_period_multiplier > 4)
6739 af_period_multiplier = 4;
6740
6741 ALOGV("new period_multiplier = %d", af_period_multiplier);
6742 }
6743
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006744 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006745 pthread_mutex_unlock(&adev_init_lock);
6746
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006747 if (adev->adm_init)
6748 adev->adm_data = adev->adm_init();
6749
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306750 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306751 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006752 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306753
6754 audio_extn_snd_mon_init();
6755 pthread_mutex_lock(&adev->lock);
6756 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
6757 adev->card_status = CARD_STATUS_ONLINE;
6758 pthread_mutex_unlock(&adev->lock);
6759 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306760 /* Allocate memory for Device config params */
6761 adev->device_cfg_params = (struct audio_device_config_param*)
6762 calloc(platform_get_max_codec_backend(),
6763 sizeof(struct audio_device_config_param));
6764 if (adev->device_cfg_params == NULL)
6765 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306766
Eric Laurent994a6932013-07-17 11:51:42 -07006767 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006768 return 0;
6769}
6770
6771static struct hw_module_methods_t hal_module_methods = {
6772 .open = adev_open,
6773};
6774
6775struct audio_module HAL_MODULE_INFO_SYM = {
6776 .common = {
6777 .tag = HARDWARE_MODULE_TAG,
6778 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6779 .hal_api_version = HARDWARE_HAL_API_VERSION,
6780 .id = AUDIO_HARDWARE_MODULE_ID,
6781 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08006782 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006783 .methods = &hal_module_methods,
6784 },
6785};