blob: d0c0cfada076b88664c4ebca4ef00ff4f4d3367a [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
Mingming Yin3a941d42016-02-17 18:08:05 -08005151 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005152 if(config->offload_info.format == 0)
5153 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08005154 if (config->offload_info.sample_rate == 0)
5155 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005156 }
5157
Mingming Yin90310102013-11-13 16:57:00 -08005158 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305159 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005160 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005161 ret = -EINVAL;
5162 goto error_open;
5163 }
5164
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005165 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5166 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5167 (audio_extn_passthru_is_passthrough_stream(out)) &&
5168 !((config->sample_rate == 48000) ||
5169 (config->sample_rate == 96000) ||
5170 (config->sample_rate == 192000))) {
5171 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5172 __func__, config->sample_rate, config->offload_info.format);
5173 ret = -EINVAL;
5174 goto error_open;
5175 }
5176
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005177 out->compr_config.codec = (struct snd_codec *)
5178 calloc(1, sizeof(struct snd_codec));
5179
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005180 if (!out->compr_config.codec) {
5181 ret = -ENOMEM;
5182 goto error_open;
5183 }
5184
Dhananjay Kumarac341582017-02-23 23:42:25 +05305185 out->stream.pause = out_pause;
5186 out->stream.resume = out_resume;
5187 out->stream.flush = out_flush;
5188 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005189 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07005190 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305191 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005192 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305193 } else {
5194 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5195 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005196 }
vivek mehta446c3962015-09-14 10:57:35 -07005197
5198 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005199 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5200 config->format == 0 && config->sample_rate == 0 &&
5201 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005202 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005203 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5204 } else {
5205 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5206 ret = -EEXIST;
5207 goto error_open;
5208 }
vivek mehta446c3962015-09-14 10:57:35 -07005209 }
5210
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005211 if (config->offload_info.channel_mask)
5212 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005213 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005214 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005215 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005216 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305217 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005218 ret = -EINVAL;
5219 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005220 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005221
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005222 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005223 out->sample_rate = config->offload_info.sample_rate;
5224
Mingming Yin3ee55c62014-08-04 14:23:35 -07005225 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005226
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305227 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305228 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305229 audio_extn_dolby_send_ddp_endp_params(adev);
5230 audio_extn_dolby_set_dmid(adev);
5231 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005232
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005233 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005234 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005235 out->compr_config.codec->bit_rate =
5236 config->offload_info.bit_rate;
5237 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305238 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005239 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305240 /* Update bit width only for non passthrough usecases.
5241 * For passthrough usecases, the output will always be opened @16 bit
5242 */
5243 if (!audio_extn_passthru_is_passthrough_stream(out))
5244 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305245
5246 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5247 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5248 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5249
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005250 /*TODO: Do we need to change it for passthrough */
5251 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005252
Manish Dewangana6fc5442015-08-24 20:30:31 +05305253 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5254 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305255 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305256 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305257 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5258 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305259
5260 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5261 AUDIO_FORMAT_PCM) {
5262
5263 /*Based on platform support, configure appropriate alsa format for corresponding
5264 *hal input format.
5265 */
5266 out->compr_config.codec->format = hal_format_to_alsa(
5267 config->offload_info.format);
5268
Ashish Jain83a6cc22016-06-28 14:34:17 +05305269 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305270 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305271 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305272
Dhananjay Kumarac341582017-02-23 23:42:25 +05305273 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305274 *hal input format and alsa format might differ based on platform support.
5275 */
5276 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305277 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305278
5279 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5280
5281 /* Check if alsa session is configured with the same format as HAL input format,
5282 * if not then derive correct fragment size needed to accomodate the
5283 * conversion of HAL input format to alsa format.
5284 */
5285 audio_extn_utils_update_direct_pcm_fragment_size(out);
5286
5287 /*if hal input and output fragment size is different this indicates HAL input format is
5288 *not same as the alsa format
5289 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305290 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305291 /*Allocate a buffer to convert input data to the alsa configured format.
5292 *size of convert buffer is equal to the size required to hold one fragment size
5293 *worth of pcm data, this is because flinger does not write more than fragment_size
5294 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305295 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5296 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305297 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5298 ret = -ENOMEM;
5299 goto error_open;
5300 }
5301 }
5302 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5303 out->compr_config.fragment_size =
5304 audio_extn_passthru_get_buffer_size(&config->offload_info);
5305 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5306 } else {
5307 out->compr_config.fragment_size =
5308 platform_get_compress_offload_buffer_size(&config->offload_info);
5309 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5310 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005311
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305312 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5313 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5314 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005315 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305316 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005317
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305318 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5319 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5320 }
5321
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005322 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5323 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005324
Manish Dewangan69426c82017-01-30 17:35:36 +05305325 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5326 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5327 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5328 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5329 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5330 } else {
5331 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5332 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005333
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305334 memset(&out->channel_map_param, 0,
5335 sizeof(struct audio_out_channel_map_param));
5336
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005337 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305338 out->send_next_track_params = false;
5339 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005340 out->offload_state = OFFLOAD_STATE_IDLE;
5341 out->playback_started = 0;
5342
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005343 audio_extn_dts_create_state_notifier_node(out->usecase);
5344
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005345 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5346 __func__, config->offload_info.version,
5347 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305348
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305349 /* Check if DSD audio format is supported in codec
5350 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305351 */
5352
5353 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305354 (!platform_check_codec_dsd_support(adev->platform) ||
5355 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305356 ret = -EINVAL;
5357 goto error_open;
5358 }
5359
Ashish Jain5106d362016-05-11 19:23:33 +05305360 /* Disable gapless if any of the following is true
5361 * passthrough playback
5362 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305363 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305364 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305365 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305366 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005367 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305368 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305369 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305370 check_and_set_gapless_mode(adev, false);
5371 } else
5372 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005373
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305374 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005375 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5376 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305377 if (config->format == AUDIO_FORMAT_DSD) {
5378 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5379 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5380 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005381
5382 create_offload_callback_thread(out);
5383
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005384 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305385 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005386 if (ret != 0) {
5387 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5388 __func__, ret);
5389 goto error_open;
5390 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005391 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5392 if (config->sample_rate == 0)
5393 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5394 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5395 config->sample_rate != 8000) {
5396 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5397 ret = -EINVAL;
5398 goto error_open;
5399 }
5400 out->sample_rate = config->sample_rate;
5401 out->config.rate = config->sample_rate;
5402 if (config->format == AUDIO_FORMAT_DEFAULT)
5403 config->format = AUDIO_FORMAT_PCM_16_BIT;
5404 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5405 config->format = AUDIO_FORMAT_PCM_16_BIT;
5406 ret = -EINVAL;
5407 goto error_open;
5408 }
5409 out->format = config->format;
5410 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5411 out->config = pcm_config_afe_proxy_playback;
5412 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005413 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305414 unsigned int channels = 0;
5415 /*Update config params to default if not set by the caller*/
5416 if (config->sample_rate == 0)
5417 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5418 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5419 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5420 if (config->format == AUDIO_FORMAT_DEFAULT)
5421 config->format = AUDIO_FORMAT_PCM_16_BIT;
5422
5423 channels = audio_channel_count_from_out_mask(out->channel_mask);
5424
Varun Balaraje49253e2017-07-06 19:48:56 +05305425 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
5426 out->usecase = get_interactive_usecase(adev);
5427 out->config = pcm_config_low_latency;
5428 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305429 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005430 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5431 out->flags);
5432 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005433 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5434 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5435 out->config = pcm_config_mmap_playback;
5436 out->stream.start = out_start;
5437 out->stream.stop = out_stop;
5438 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5439 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305440 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5441 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005442 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5443 if (!out->dynamic_pm_qos_enabled) {
5444 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5445 } else {
5446 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5447 //the mixer path will be a string similar to "low-latency-playback resume"
5448 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5449 strlcat(out->pm_qos_mixer_path,
5450 " resume", MAX_MIXER_PATH_LEN);
5451 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5452 out->pm_qos_mixer_path);
5453 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305454 out->config = pcm_config_low_latency;
5455 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5456 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5457 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305458 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5459 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5460 if (out->config.period_size <= 0) {
5461 ALOGE("Invalid configuration period size is not valid");
5462 ret = -EINVAL;
5463 goto error_open;
5464 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305465 } else {
5466 /* primary path is the default path selected if no other outputs are available/suitable */
5467 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5468 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5469 }
5470 out->hal_ip_format = format = out->format;
5471 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5472 out->hal_op_format = pcm_format_to_hal(out->config.format);
5473 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5474 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005475 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305476 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305477 if (out->hal_ip_format != out->hal_op_format) {
5478 uint32_t buffer_size = out->config.period_size *
5479 format_to_bitwidth_table[out->hal_op_format] *
5480 out->config.channels;
5481 out->convert_buffer = calloc(1, buffer_size);
5482 if (out->convert_buffer == NULL){
5483 ALOGE("Allocation failed for convert buffer for size %d",
5484 out->compr_config.fragment_size);
5485 ret = -ENOMEM;
5486 goto error_open;
5487 }
5488 ALOGD("Convert buffer allocated of size %d", buffer_size);
5489 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005490 }
5491
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005492 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5493 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305494
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005495 /* TODO remove this hardcoding and check why width is zero*/
5496 if (out->bit_width == 0)
5497 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305498 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005499 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07005500 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305501 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305502 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005503 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5504 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5505 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005506 if(adev->primary_output == NULL)
5507 adev->primary_output = out;
5508 else {
5509 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005510 ret = -EEXIST;
5511 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005512 }
5513 }
5514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005515 /* Check if this usecase is already existing */
5516 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005517 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5518 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005519 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005520 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005521 ret = -EEXIST;
5522 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005523 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005525 pthread_mutex_unlock(&adev->lock);
5526
5527 out->stream.common.get_sample_rate = out_get_sample_rate;
5528 out->stream.common.set_sample_rate = out_set_sample_rate;
5529 out->stream.common.get_buffer_size = out_get_buffer_size;
5530 out->stream.common.get_channels = out_get_channels;
5531 out->stream.common.get_format = out_get_format;
5532 out->stream.common.set_format = out_set_format;
5533 out->stream.common.standby = out_standby;
5534 out->stream.common.dump = out_dump;
5535 out->stream.common.set_parameters = out_set_parameters;
5536 out->stream.common.get_parameters = out_get_parameters;
5537 out->stream.common.add_audio_effect = out_add_audio_effect;
5538 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5539 out->stream.get_latency = out_get_latency;
5540 out->stream.set_volume = out_set_volume;
5541 out->stream.write = out_write;
5542 out->stream.get_render_position = out_get_render_position;
5543 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005544 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005545
Haynes Mathew George16081042017-05-31 17:16:49 -07005546 if (out->realtime)
5547 out->af_period_multiplier = af_period_multiplier;
5548 else
5549 out->af_period_multiplier = 1;
5550
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005551 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005552 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005553 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005554
5555 config->format = out->stream.common.get_format(&out->stream.common);
5556 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5557 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5558
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305559 /*
5560 By locking output stream before registering, we allow the callback
5561 to update stream's state only after stream's initial state is set to
5562 adev state.
5563 */
5564 lock_output_stream(out);
5565 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5566 pthread_mutex_lock(&adev->lock);
5567 out->card_status = adev->card_status;
5568 pthread_mutex_unlock(&adev->lock);
5569 pthread_mutex_unlock(&out->lock);
5570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005571 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305572 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07005573 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005574
5575 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
5576 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5577 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005578 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05305579 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005580 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005581 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05305582 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005583 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5584 out->usecase, PCM_PLAYBACK);
5585 hdlr_stream_cfg.flags = out->flags;
5586 hdlr_stream_cfg.type = PCM_PLAYBACK;
5587 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5588 &hdlr_stream_cfg);
5589 if (ret) {
5590 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5591 out->adsp_hdlr_stream_handle = NULL;
5592 }
5593 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05305594 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07005595 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07005596 if (ret < 0) {
5597 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5598 out->ip_hdlr_handle = NULL;
5599 }
5600 }
Eric Laurent994a6932013-07-17 11:51:42 -07005601 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005602 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005603
5604error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305605 if (out->convert_buffer)
5606 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005607 free(out);
5608 *stream_out = NULL;
5609 ALOGD("%s: exit: ret %d", __func__, ret);
5610 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005611}
5612
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305613void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005614 struct audio_stream_out *stream)
5615{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005616 struct stream_out *out = (struct stream_out *)stream;
5617 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005618 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005619
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305620 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
5621
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305622 // must deregister from sndmonitor first to prevent races
5623 // between the callback and close_stream
5624 audio_extn_snd_mon_unregister_listener(out);
5625
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005626 /* close adsp hdrl session before standby */
5627 if (out->adsp_hdlr_stream_handle) {
5628 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5629 if (ret)
5630 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5631 out->adsp_hdlr_stream_handle = NULL;
5632 }
5633
Manish Dewangan21a850a2017-08-14 12:03:55 +05305634 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07005635 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5636 out->ip_hdlr_handle = NULL;
5637 }
5638
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005639 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305640 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005641 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305642 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305643 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005644 if(ret != 0)
5645 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5646 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005647 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005648 out_standby(&stream->common);
5649
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005650 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005651 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005652 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005653 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005654 if (out->compr_config.codec != NULL)
5655 free(out->compr_config.codec);
5656 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005657
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305658 out->a2dp_compress_mute = false;
5659
Varun Balaraje49253e2017-07-06 19:48:56 +05305660 if (is_interactive_usecase(out->usecase))
5661 free_interactive_usecase(adev, out->usecase);
5662
Ashish Jain83a6cc22016-06-28 14:34:17 +05305663 if (out->convert_buffer != NULL) {
5664 free(out->convert_buffer);
5665 out->convert_buffer = NULL;
5666 }
5667
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005668 if (adev->voice_tx_output == out)
5669 adev->voice_tx_output = NULL;
5670
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305671 if (adev->primary_output == out)
5672 adev->primary_output = NULL;
5673
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005674 pthread_cond_destroy(&out->cond);
5675 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005676 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005677 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005678}
5679
5680static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5681{
5682 struct audio_device *adev = (struct audio_device *)dev;
5683 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005684 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005685 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005686 int ret;
5687 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005688
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005689 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005690 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005691
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305692 if (!parms)
5693 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305694
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305695 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5696 if (ret >= 0) {
5697 /* When set to false, HAL should disable EC and NS */
5698 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5699 adev->bt_sco_on = true;
5700 else
5701 adev->bt_sco_on = false;
5702 }
5703
Naresh Tanniru4c630392014-05-12 01:05:52 +05305704 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005705 status = voice_set_parameters(adev, parms);
5706 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005707 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005708
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005709 status = platform_set_parameters(adev->platform, parms);
5710 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005711 goto done;
5712
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005713 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5714 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005715 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005716 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5717 adev->bluetooth_nrec = true;
5718 else
5719 adev->bluetooth_nrec = false;
5720 }
5721
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005722 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5723 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005724 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5725 adev->screen_off = false;
5726 else
5727 adev->screen_off = true;
5728 }
5729
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005730 ret = str_parms_get_int(parms, "rotation", &val);
5731 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005732 bool reverse_speakers = false;
5733 switch(val) {
5734 // FIXME: note that the code below assumes that the speakers are in the correct placement
5735 // relative to the user when the device is rotated 90deg from its default rotation. This
5736 // assumption is device-specific, not platform-specific like this code.
5737 case 270:
5738 reverse_speakers = true;
5739 break;
5740 case 0:
5741 case 90:
5742 case 180:
5743 break;
5744 default:
5745 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005746 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005747 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005748 if (status == 0) {
5749 if (adev->speaker_lr_swap != reverse_speakers) {
5750 adev->speaker_lr_swap = reverse_speakers;
5751 // only update the selected device if there is active pcm playback
5752 struct audio_usecase *usecase;
5753 struct listnode *node;
5754 list_for_each(node, &adev->usecase_list) {
5755 usecase = node_to_item(node, struct audio_usecase, list);
5756 if (usecase->type == PCM_PLAYBACK) {
5757 select_devices(adev, usecase->id);
5758 break;
5759 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005760 }
5761 }
5762 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005763 }
5764
Mingming Yin514a8bc2014-07-29 15:22:21 -07005765 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5766 if (ret >= 0) {
5767 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5768 adev->bt_wb_speech_enabled = true;
5769 else
5770 adev->bt_wb_speech_enabled = false;
5771 }
5772
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005773 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5774 if (ret >= 0) {
5775 val = atoi(value);
5776 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005777 ALOGV("cache new ext disp type and edid");
5778 ret = platform_get_ext_disp_type(adev->platform);
5779 if (ret < 0) {
5780 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08005781 status = ret;
5782 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005783 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005784 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005785 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005786 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07005787 /*
5788 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
5789 * Per AudioPolicyManager, USB device is higher priority than WFD.
5790 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
5791 * If WFD use case occupies AFE proxy, it may result unintended behavior while
5792 * starting voice call on USB
5793 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005794 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5795 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08005796 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5797 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005798 }
vivek mehta344576a2016-04-12 18:56:03 -07005799 ALOGV("detected USB connect .. disable proxy");
5800 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005801 }
5802 }
5803
5804 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5805 if (ret >= 0) {
5806 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07005807 /*
5808 * The HDMI / Displayport disconnect handling has been moved to
5809 * audio extension to ensure that its parameters are not
5810 * invalidated prior to updating sysfs of the disconnect event
5811 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
5812 */
5813 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005814 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005815 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5816 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05305817 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5818 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005819 }
vivek mehta344576a2016-04-12 18:56:03 -07005820 ALOGV("detected USB disconnect .. enable proxy");
5821 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005822 }
5823 }
5824
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305825 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5826 if (ret >= 0) {
5827 struct audio_usecase *usecase;
5828 struct listnode *node;
5829 list_for_each(node, &adev->usecase_list) {
5830 usecase = node_to_item(node, struct audio_usecase, list);
5831 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005832 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305833 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005834
5835 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305836 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005837 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305838 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305839 //force device switch to re configure encoder
5840 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305841 audio_extn_a2dp_set_handoff_mode(false);
5842 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305843 break;
5844 }
5845 }
5846 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005847
5848 //handle vr audio setparam
5849 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5850 value, sizeof(value));
5851 if (ret >= 0) {
5852 ALOGI("Setting vr mode to be %s", value);
5853 if (!strncmp(value, "true", 4)) {
5854 adev->vr_audio_mode_enabled = true;
5855 ALOGI("Setting vr mode to true");
5856 } else if (!strncmp(value, "false", 5)) {
5857 adev->vr_audio_mode_enabled = false;
5858 ALOGI("Setting vr mode to false");
5859 } else {
5860 ALOGI("wrong vr mode set");
5861 }
5862 }
5863
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305864 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005865done:
5866 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005867 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305868error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005869 ALOGV("%s: exit with code(%d)", __func__, status);
5870 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005871}
5872
5873static char* adev_get_parameters(const struct audio_hw_device *dev,
5874 const char *keys)
5875{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005876 struct audio_device *adev = (struct audio_device *)dev;
5877 struct str_parms *reply = str_parms_create();
5878 struct str_parms *query = str_parms_create_str(keys);
5879 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305880 char value[256] = {0};
5881 int ret = 0;
5882
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005883 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005884 if (reply) {
5885 str_parms_destroy(reply);
5886 }
5887 if (query) {
5888 str_parms_destroy(query);
5889 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005890 ALOGE("adev_get_parameters: failed to create query or reply");
5891 return NULL;
5892 }
5893
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005894 //handle vr audio getparam
5895
5896 ret = str_parms_get_str(query,
5897 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5898 value, sizeof(value));
5899
5900 if (ret >= 0) {
5901 bool vr_audio_enabled = false;
5902 pthread_mutex_lock(&adev->lock);
5903 vr_audio_enabled = adev->vr_audio_mode_enabled;
5904 pthread_mutex_unlock(&adev->lock);
5905
5906 ALOGI("getting vr mode to %d", vr_audio_enabled);
5907
5908 if (vr_audio_enabled) {
5909 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5910 "true");
5911 goto exit;
5912 } else {
5913 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5914 "false");
5915 goto exit;
5916 }
5917 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005918
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005919 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005920 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005921 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005922 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305923 pthread_mutex_unlock(&adev->lock);
5924
Naresh Tannirud7205b62014-06-20 02:54:48 +05305925exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005926 str = str_parms_to_str(reply);
5927 str_parms_destroy(query);
5928 str_parms_destroy(reply);
5929
5930 ALOGV("%s: exit: returns - %s", __func__, str);
5931 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005932}
5933
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005934static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005935{
5936 return 0;
5937}
5938
5939static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5940{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005941 int ret;
5942 struct audio_device *adev = (struct audio_device *)dev;
5943 pthread_mutex_lock(&adev->lock);
5944 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005945 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005946 pthread_mutex_unlock(&adev->lock);
5947 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005948}
5949
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005950static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5951 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005952{
5953 return -ENOSYS;
5954}
5955
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005956static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5957 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005958{
5959 return -ENOSYS;
5960}
5961
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005962static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5963 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005964{
5965 return -ENOSYS;
5966}
5967
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005968static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5969 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005970{
5971 return -ENOSYS;
5972}
5973
5974static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5975{
5976 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005978 pthread_mutex_lock(&adev->lock);
5979 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005980 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005981 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005982 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005983 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005984 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005985 adev->current_call_output = NULL;
5986 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005987 }
5988 pthread_mutex_unlock(&adev->lock);
5989 return 0;
5990}
5991
5992static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5993{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005994 int ret;
5995
5996 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005997 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005998 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5999 pthread_mutex_unlock(&adev->lock);
6000
6001 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006002}
6003
6004static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6005{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006006 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006007 return 0;
6008}
6009
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006010static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006011 const struct audio_config *config)
6012{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006013 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006014
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006015 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6016 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006017}
6018
6019static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006020 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006021 audio_devices_t devices,
6022 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006023 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306024 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006025 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006026 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006027{
6028 struct audio_device *adev = (struct audio_device *)dev;
6029 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006030 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006031 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006032 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306033 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006035 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306036 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
6037 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006038 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306039 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006040
6041 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006042
6043 if (!in) {
6044 ALOGE("failed to allocate input stream");
6045 return -ENOMEM;
6046 }
6047
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306048 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306049 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
6050 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006051 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006052 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006054 in->stream.common.get_sample_rate = in_get_sample_rate;
6055 in->stream.common.set_sample_rate = in_set_sample_rate;
6056 in->stream.common.get_buffer_size = in_get_buffer_size;
6057 in->stream.common.get_channels = in_get_channels;
6058 in->stream.common.get_format = in_get_format;
6059 in->stream.common.set_format = in_set_format;
6060 in->stream.common.standby = in_standby;
6061 in->stream.common.dump = in_dump;
6062 in->stream.common.set_parameters = in_set_parameters;
6063 in->stream.common.get_parameters = in_get_parameters;
6064 in->stream.common.add_audio_effect = in_add_audio_effect;
6065 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6066 in->stream.set_gain = in_set_gain;
6067 in->stream.read = in_read;
6068 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6069
6070 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006071 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006072 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006073 in->standby = 1;
6074 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006075 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006076 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006077
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306078 in->usecase = USECASE_AUDIO_RECORD;
6079 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006080 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306081 is_low_latency = true;
6082#if LOW_LATENCY_CAPTURE_USE_CASE
6083 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
6084#endif
6085 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
6086 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006087 in->format = config->format;
Haynes Mathew George16081042017-05-31 17:16:49 -07006088 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6089 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
6090 in->realtime = 0;
6091 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6092 in->config = pcm_config_mmap_capture;
6093 in->stream.start = in_start;
6094 in->stream.stop = in_stop;
6095 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6096 in->stream.get_mmap_position = in_get_mmap_position;
6097 in->af_period_multiplier = 1;
6098 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
6099 } else if (in->realtime) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006100 in->config = pcm_config_audio_capture_rt;
6101 in->sample_rate = in->config.rate;
6102 in->af_period_multiplier = af_period_multiplier;
6103 } else {
6104 in->config = pcm_config_audio_capture;
6105 in->config.rate = config->sample_rate;
6106 in->sample_rate = config->sample_rate;
6107 in->af_period_multiplier = 1;
6108 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306109 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006110
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306111 /* restrict 24 bit capture for unprocessed source only
6112 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
6113 */
6114 if (config->format == AUDIO_FORMAT_DEFAULT) {
6115 config->format = AUDIO_FORMAT_PCM_16_BIT;
6116 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6117 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6118 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6119 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6120 bool ret_error = false;
6121 in->bit_width = 24;
6122 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6123 from HAL is 24_packed and 8_24
6124 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6125 24_packed return error indicating supported format is 24_packed
6126 *> In case of any other source requesting 24 bit or float return error
6127 indicating format supported is 16 bit only.
6128
6129 on error flinger will retry with supported format passed
6130 */
6131 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6132 (source != AUDIO_SOURCE_CAMCORDER)) {
6133 config->format = AUDIO_FORMAT_PCM_16_BIT;
6134 if (config->sample_rate > 48000)
6135 config->sample_rate = 48000;
6136 ret_error = true;
6137 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
6138 in->config.format = PCM_FORMAT_S24_3LE;
6139 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
6140 in->config.format = PCM_FORMAT_S24_LE;
6141 } else {
6142 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
6143 ret_error = true;
6144 }
6145
6146 if (ret_error) {
6147 ret = -EINVAL;
6148 goto err_open;
6149 }
6150 }
6151
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306152 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306153 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6154 (adev->mode != AUDIO_MODE_IN_CALL)) {
6155 ret = -EINVAL;
6156 goto err_open;
6157 }
6158
6159 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
6160 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006161 if (config->sample_rate == 0)
6162 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6163 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6164 config->sample_rate != 8000) {
6165 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6166 ret = -EINVAL;
6167 goto err_open;
6168 }
6169 if (config->format == AUDIO_FORMAT_DEFAULT)
6170 config->format = AUDIO_FORMAT_PCM_16_BIT;
6171 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6172 config->format = AUDIO_FORMAT_PCM_16_BIT;
6173 ret = -EINVAL;
6174 goto err_open;
6175 }
6176
6177 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6178 in->config = pcm_config_afe_proxy_record;
6179 in->config.channels = channel_count;
6180 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306181 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306182 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
6183 in, config, &channel_mask_updated)) {
6184 if (channel_mask_updated == true) {
6185 ALOGD("%s: return error to retry with updated channel mask (%#x)",
6186 __func__, config->channel_mask);
6187 ret = -EINVAL;
6188 goto err_open;
6189 }
Garmond Leunge2433c32017-09-28 21:51:22 -07006190 ALOGD("%s: created multi-channel session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07006191 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006192 audio_extn_compr_cap_format_supported(config->format) &&
6193 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006194 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306195 } else if (audio_extn_cin_applicable_stream(in)) {
6196 ret = audio_extn_cin_configure_input_stream(in);
6197 if (ret)
6198 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006199 } else {
6200 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006201 if (!in->realtime) {
6202 in->format = config->format;
6203 frame_size = audio_stream_in_frame_size(&in->stream);
6204 buffer_size = get_input_buffer_size(config->sample_rate,
6205 config->format,
6206 channel_count,
6207 is_low_latency);
6208 in->config.period_size = buffer_size / frame_size;
6209 }
6210
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006211#ifndef COMPRESS_VOIP_ENABLED
6212 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6213 (in->config.rate == 8000 || in->config.rate == 16000 ||
6214 in->config.rate == 32000 || in->config.rate == 48000) &&
6215 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6216
6217 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6218 in->config = default_pcm_config_voip_copp;
6219 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6220 in->config.rate = in->sample_rate;
6221#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006222 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006223 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6224 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006225 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006226 (in->config.rate == 8000 || in->config.rate == 16000 ||
6227 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006228 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6229 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006230#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006231 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006232 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006233
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306234 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6235 &adev->streams_input_cfg_list,
6236 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306237 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306238
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006239 /* This stream could be for sound trigger lab,
6240 get sound trigger pcm if present */
6241 audio_extn_sound_trigger_check_and_get_session(in);
6242
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306243 lock_input_stream(in);
6244 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6245 pthread_mutex_lock(&adev->lock);
6246 in->card_status = adev->card_status;
6247 pthread_mutex_unlock(&adev->lock);
6248 pthread_mutex_unlock(&in->lock);
6249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006250 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006251 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006252 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006253
6254err_open:
6255 free(in);
6256 *stream_in = NULL;
6257 return ret;
6258}
6259
6260static void adev_close_input_stream(struct audio_hw_device *dev,
6261 struct audio_stream_in *stream)
6262{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006263 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006264 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006265 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306266
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306267 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006268
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306269 // must deregister from sndmonitor first to prevent races
6270 // between the callback and close_stream
6271 audio_extn_snd_mon_unregister_listener(stream);
6272
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306273 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006274 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306275
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006276 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306277 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006278 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306279 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006280 if (ret != 0)
6281 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6282 __func__, ret);
6283 } else
6284 in_standby(&stream->common);
6285
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006286 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006287 audio_extn_ssr_deinit();
6288 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006289
Garmond Leunge2433c32017-09-28 21:51:22 -07006290 if (audio_extn_ffv_get_stream() == in) {
6291 audio_extn_ffv_stream_deinit();
6292 }
6293
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306294 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006295 audio_extn_compr_cap_format_supported(in->config.format))
6296 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306297
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306298 if (audio_extn_cin_attached_usecase(in->usecase))
6299 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006300
Mingming Yinfd7607b2016-01-22 12:48:44 -08006301 if (in->is_st_session) {
6302 ALOGV("%s: sound trigger pcm stop lab", __func__);
6303 audio_extn_sound_trigger_stop_lab(in);
6304 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006305 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006306 return;
6307}
6308
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306309int adev_create_audio_patch(struct audio_hw_device *dev,
6310 unsigned int num_sources,
6311 const struct audio_port_config *sources,
6312 unsigned int num_sinks,
6313 const struct audio_port_config *sinks,
6314 audio_patch_handle_t *handle)
6315{
6316
6317
6318 return audio_extn_hw_loopback_create_audio_patch(dev,
6319 num_sources,
6320 sources,
6321 num_sinks,
6322 sinks,
6323 handle);
6324
6325}
6326
6327int adev_release_audio_patch(struct audio_hw_device *dev,
6328 audio_patch_handle_t handle)
6329{
6330 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6331}
6332
6333int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6334{
6335 return audio_extn_hw_loopback_get_audio_port(dev, config);
6336}
6337
6338int adev_set_audio_port_config(struct audio_hw_device *dev,
6339 const struct audio_port_config *config)
6340{
6341 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6342}
6343
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006344static int adev_dump(const audio_hw_device_t *device __unused,
6345 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006346{
6347 return 0;
6348}
6349
6350static int adev_close(hw_device_t *device)
6351{
6352 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006353
6354 if (!adev)
6355 return 0;
6356
6357 pthread_mutex_lock(&adev_init_lock);
6358
6359 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306360 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006361 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006362 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306363 audio_extn_utils_release_streams_cfg_lists(
6364 &adev->streams_output_cfg_list,
6365 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306366 if (audio_extn_qaf_is_enabled())
6367 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006368 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006369 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006370 free(adev->snd_dev_ref_cnt);
6371 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006372 if (adev->adm_deinit)
6373 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306374 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006375 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306376 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306377 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07006378 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306379 if (adev->device_cfg_params) {
6380 free(adev->device_cfg_params);
6381 adev->device_cfg_params = NULL;
6382 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006383 free(device);
6384 adev = NULL;
6385 }
6386 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006387
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006388 return 0;
6389}
6390
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006391/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6392 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6393 * just that it _might_ work.
6394 */
6395static int period_size_is_plausible_for_low_latency(int period_size)
6396{
6397 switch (period_size) {
6398 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006399 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006400 case 240:
6401 case 320:
6402 case 480:
6403 return 1;
6404 default:
6405 return 0;
6406 }
6407}
6408
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306409static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6410{
6411 bool is_snd_card_status = false;
6412 bool is_ext_device_status = false;
6413 char value[32];
6414 int card = -1;
6415 card_status_t status;
6416
6417 if (cookie != adev || !parms)
6418 return;
6419
6420 if (!parse_snd_card_status(parms, &card, &status)) {
6421 is_snd_card_status = true;
6422 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6423 is_ext_device_status = true;
6424 } else {
6425 // not a valid event
6426 return;
6427 }
6428
6429 pthread_mutex_lock(&adev->lock);
6430 if (card == adev->snd_card || is_ext_device_status) {
6431 if (is_snd_card_status && adev->card_status != status) {
6432 adev->card_status = status;
6433 platform_snd_card_update(adev->platform, status);
6434 audio_extn_fm_set_parameters(adev, parms);
6435 } else if (is_ext_device_status) {
6436 platform_set_parameters(adev->platform, parms);
6437 }
6438 }
6439 pthread_mutex_unlock(&adev->lock);
6440 return;
6441}
6442
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306443/* out and adev lock held */
6444static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6445{
6446 struct audio_usecase *uc_info;
6447 float left_p;
6448 float right_p;
6449 audio_devices_t devices;
6450
6451 uc_info = get_usecase_from_list(adev, out->usecase);
6452 if (uc_info == NULL) {
6453 ALOGE("%s: Could not find the usecase (%d) in the list",
6454 __func__, out->usecase);
6455 return -EINVAL;
6456 }
6457
6458 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6459 out->usecase, use_case_table[out->usecase]);
6460
6461 if (restore) {
6462 // restore A2DP device for active usecases and unmute if required
6463 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6464 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6465 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6466 select_devices(adev, uc_info->id);
6467 pthread_mutex_lock(&out->compr_mute_lock);
6468 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6469 (out->a2dp_compress_mute)) {
6470 out->a2dp_compress_mute = false;
6471 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6472 }
6473 pthread_mutex_unlock(&out->compr_mute_lock);
6474 }
6475 } else {
6476 // mute compress stream if suspended
6477 pthread_mutex_lock(&out->compr_mute_lock);
6478 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6479 (!out->a2dp_compress_mute)) {
6480 if (!out->standby) {
6481 ALOGD("%s: selecting speaker and muting stream", __func__);
6482 devices = out->devices;
6483 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6484 left_p = out->volume_l;
6485 right_p = out->volume_r;
6486 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6487 compress_pause(out->compr);
6488 out_set_compr_volume(&out->stream, (float)0, (float)0);
6489 out->a2dp_compress_mute = true;
6490 select_devices(adev, out->usecase);
6491 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6492 compress_resume(out->compr);
6493 out->devices = devices;
6494 out->volume_l = left_p;
6495 out->volume_r = right_p;
6496 }
6497 }
6498 pthread_mutex_unlock(&out->compr_mute_lock);
6499 }
6500 ALOGV("%s: exit", __func__);
6501 return 0;
6502}
6503
6504int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6505{
6506 int ret = 0;
6507
6508 lock_output_stream(out);
6509 pthread_mutex_lock(&adev->lock);
6510
6511 ret = check_a2dp_restore_l(adev, out, restore);
6512
6513 pthread_mutex_unlock(&adev->lock);
6514 pthread_mutex_unlock(&out->lock);
6515 return ret;
6516}
6517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006518static int adev_open(const hw_module_t *module, const char *name,
6519 hw_device_t **device)
6520{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306521 int ret;
6522
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006523 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006524 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
6525
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006526 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07006527 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006528 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07006529 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006530 ALOGD("%s: returning existing instance of adev", __func__);
6531 ALOGD("%s: exit", __func__);
6532 pthread_mutex_unlock(&adev_init_lock);
6533 return 0;
6534 }
6535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006536 adev = calloc(1, sizeof(struct audio_device));
6537
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006538 if (!adev) {
6539 pthread_mutex_unlock(&adev_init_lock);
6540 return -ENOMEM;
6541 }
6542
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006543 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6544
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05306545#ifdef DYNAMIC_LOG_ENABLED
6546 register_for_dynamic_logging("hal");
6547#endif
6548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006549 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6550 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6551 adev->device.common.module = (struct hw_module_t *)module;
6552 adev->device.common.close = adev_close;
6553
6554 adev->device.init_check = adev_init_check;
6555 adev->device.set_voice_volume = adev_set_voice_volume;
6556 adev->device.set_master_volume = adev_set_master_volume;
6557 adev->device.get_master_volume = adev_get_master_volume;
6558 adev->device.set_master_mute = adev_set_master_mute;
6559 adev->device.get_master_mute = adev_get_master_mute;
6560 adev->device.set_mode = adev_set_mode;
6561 adev->device.set_mic_mute = adev_set_mic_mute;
6562 adev->device.get_mic_mute = adev_get_mic_mute;
6563 adev->device.set_parameters = adev_set_parameters;
6564 adev->device.get_parameters = adev_get_parameters;
6565 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6566 adev->device.open_output_stream = adev_open_output_stream;
6567 adev->device.close_output_stream = adev_close_output_stream;
6568 adev->device.open_input_stream = adev_open_input_stream;
6569 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306570 adev->device.create_audio_patch = adev_create_audio_patch;
6571 adev->device.release_audio_patch = adev_release_audio_patch;
6572 adev->device.get_audio_port = adev_get_audio_port;
6573 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006574 adev->device.dump = adev_dump;
6575
6576 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006577 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08006578 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006579 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006580 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006581 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006582 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07006583 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306584 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006585 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006586 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006587 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006588 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08006589 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006590 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05306591 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306592 adev->perf_lock_opts[0] = 0x101;
6593 adev->perf_lock_opts[1] = 0x20E;
6594 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006595 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006597 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006598 adev->platform = platform_init(adev);
6599 if (!adev->platform) {
6600 free(adev->snd_dev_ref_cnt);
6601 free(adev);
6602 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6603 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006604 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306605 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006606 return -EINVAL;
6607 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006608
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306609 if (audio_extn_qaf_is_enabled()) {
6610 ret = audio_extn_qaf_init(adev);
6611 if (ret < 0) {
6612 free(adev);
6613 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6614 *device = NULL;
6615 pthread_mutex_unlock(&adev_init_lock);
6616 pthread_mutex_destroy(&adev->lock);
6617 return ret;
6618 }
6619
6620 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6621 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6622 }
6623
Eric Laurentc4aef752013-09-12 17:45:53 -07006624 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6625 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6626 if (adev->visualizer_lib == NULL) {
6627 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6628 } else {
6629 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6630 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006631 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006632 "visualizer_hal_start_output");
6633 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006634 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006635 "visualizer_hal_stop_output");
6636 }
6637 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05306638 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08006639 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006640 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306641 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07006642 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07006643
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006644 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
6645 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6646 if (adev->offload_effects_lib == NULL) {
6647 ALOGE("%s: DLOPEN failed for %s", __func__,
6648 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6649 } else {
6650 ALOGV("%s: DLOPEN successful for %s", __func__,
6651 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6652 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05306653 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006654 "offload_effects_bundle_hal_start_output");
6655 adev->offload_effects_stop_output =
6656 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6657 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006658 adev->offload_effects_set_hpx_state =
6659 (int (*)(bool))dlsym(adev->offload_effects_lib,
6660 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05306661 adev->offload_effects_get_parameters =
6662 (void (*)(struct str_parms *, struct str_parms *))
6663 dlsym(adev->offload_effects_lib,
6664 "offload_effects_bundle_get_parameters");
6665 adev->offload_effects_set_parameters =
6666 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
6667 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006668 }
6669 }
6670
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006671 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
6672 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6673 if (adev->adm_lib == NULL) {
6674 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6675 } else {
6676 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6677 adev->adm_init = (adm_init_t)
6678 dlsym(adev->adm_lib, "adm_init");
6679 adev->adm_deinit = (adm_deinit_t)
6680 dlsym(adev->adm_lib, "adm_deinit");
6681 adev->adm_register_input_stream = (adm_register_input_stream_t)
6682 dlsym(adev->adm_lib, "adm_register_input_stream");
6683 adev->adm_register_output_stream = (adm_register_output_stream_t)
6684 dlsym(adev->adm_lib, "adm_register_output_stream");
6685 adev->adm_deregister_stream = (adm_deregister_stream_t)
6686 dlsym(adev->adm_lib, "adm_deregister_stream");
6687 adev->adm_request_focus = (adm_request_focus_t)
6688 dlsym(adev->adm_lib, "adm_request_focus");
6689 adev->adm_abandon_focus = (adm_abandon_focus_t)
6690 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006691 adev->adm_set_config = (adm_set_config_t)
6692 dlsym(adev->adm_lib, "adm_set_config");
6693 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6694 dlsym(adev->adm_lib, "adm_request_focus_v2");
6695 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6696 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6697 adev->adm_on_routing_change = (adm_on_routing_change_t)
6698 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006699 }
6700 }
6701
Mingming Yin514a8bc2014-07-29 15:22:21 -07006702 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006703 //initialize this to false for now,
6704 //this will be set to true through set param
6705 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07006706
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07006707 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006708 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006709 adev->dsp_bit_width_enforce_mode =
6710 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306712 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
6713 &adev->streams_output_cfg_list,
6714 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006715
Kiran Kandi910e1862013-10-29 13:29:42 -07006716 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006717
6718 char value[PROPERTY_VALUE_MAX];
6719 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006720 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006721 trial = atoi(value);
6722 if (period_size_is_plausible_for_low_latency(trial)) {
6723 pcm_config_low_latency.period_size = trial;
6724 pcm_config_low_latency.start_threshold = trial / 4;
6725 pcm_config_low_latency.avail_min = trial / 4;
6726 configured_low_latency_capture_period_size = trial;
6727 }
6728 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006729 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006730 trial = atoi(value);
6731 if (period_size_is_plausible_for_low_latency(trial)) {
6732 configured_low_latency_capture_period_size = trial;
6733 }
6734 }
6735
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006736 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006737 af_period_multiplier = atoi(value);
6738 if (af_period_multiplier < 0)
6739 af_period_multiplier = 2;
6740 else if (af_period_multiplier > 4)
6741 af_period_multiplier = 4;
6742
6743 ALOGV("new period_multiplier = %d", af_period_multiplier);
6744 }
6745
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006746 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006747 pthread_mutex_unlock(&adev_init_lock);
6748
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006749 if (adev->adm_init)
6750 adev->adm_data = adev->adm_init();
6751
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306752 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306753 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006754 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306755
6756 audio_extn_snd_mon_init();
6757 pthread_mutex_lock(&adev->lock);
6758 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
6759 adev->card_status = CARD_STATUS_ONLINE;
6760 pthread_mutex_unlock(&adev->lock);
6761 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306762 /* Allocate memory for Device config params */
6763 adev->device_cfg_params = (struct audio_device_config_param*)
6764 calloc(platform_get_max_codec_backend(),
6765 sizeof(struct audio_device_config_param));
6766 if (adev->device_cfg_params == NULL)
6767 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306768
Eric Laurent994a6932013-07-17 11:51:42 -07006769 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006770 return 0;
6771}
6772
6773static struct hw_module_methods_t hal_module_methods = {
6774 .open = adev_open,
6775};
6776
6777struct audio_module HAL_MODULE_INFO_SYM = {
6778 .common = {
6779 .tag = HARDWARE_MODULE_TAG,
6780 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6781 .hal_api_version = HARDWARE_HAL_API_VERSION,
6782 .id = AUDIO_HARDWARE_MODULE_ID,
6783 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08006784 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006785 .methods = &hal_module_methods,
6786 },
6787};