blob: 12bc76bbc240a90304cc8a303d82eec931da5c14 [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",
Eric Laurentb23d5282013-05-14 15:27:20 -0700330};
331
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700332static const audio_usecase_t offload_usecases[] = {
333 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700334 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
335 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
336 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
337 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
338 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
339 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
340 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
341 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700342};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800343
Varun Balaraje49253e2017-07-06 19:48:56 +0530344static const audio_usecase_t interactive_usecases[] = {
345 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
346 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
347 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
348 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
349 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
350 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
351 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
352 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
353};
354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800355#define STRING_TO_ENUM(string) { #string, string }
356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800357struct string_to_enum {
358 const char *name;
359 uint32_t value;
360};
361
362static const struct string_to_enum out_channels_name_to_enum_table[] = {
363 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800364 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
365 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
366 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700367 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800368 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
369 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800370 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
371};
372
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700373static const struct string_to_enum out_formats_name_to_enum_table[] = {
374 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
375 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
376 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700377 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800378 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
379 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700380 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800381};
382
383//list of all supported sample rates by HDMI specification.
384static const int out_hdmi_sample_rates[] = {
385 32000, 44100, 48000, 88200, 96000, 176400, 192000,
386};
387
388static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
389 STRING_TO_ENUM(32000),
390 STRING_TO_ENUM(44100),
391 STRING_TO_ENUM(48000),
392 STRING_TO_ENUM(88200),
393 STRING_TO_ENUM(96000),
394 STRING_TO_ENUM(176400),
395 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700396};
397
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700398static struct audio_device *adev = NULL;
399static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700400static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700401//cache last MBDRC cal step level
402static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700403
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530404static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
405static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
406
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700407static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
408 int flags __unused)
409{
410 int dir = 0;
411 switch (uc_id) {
412 case USECASE_AUDIO_RECORD_LOW_LATENCY:
413 dir = 1;
414 case USECASE_AUDIO_PLAYBACK_ULL:
415 break;
416 default:
417 return false;
418 }
419
420 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
421 PCM_PLAYBACK : PCM_CAPTURE);
422 if (adev->adm_is_noirq_avail)
423 return adev->adm_is_noirq_avail(adev->adm_data,
424 adev->snd_card, dev_id, dir);
425 return false;
426}
427
428static void register_out_stream(struct stream_out *out)
429{
430 struct audio_device *adev = out->dev;
431 if (is_offload_usecase(out->usecase) ||
432 !adev->adm_register_output_stream)
433 return;
434
435 // register stream first for backward compatibility
436 adev->adm_register_output_stream(adev->adm_data,
437 out->handle,
438 out->flags);
439
440 if (!adev->adm_set_config)
441 return;
442
443 if (out->realtime)
444 adev->adm_set_config(adev->adm_data,
445 out->handle,
446 out->pcm, &out->config);
447}
448
449static void register_in_stream(struct stream_in *in)
450{
451 struct audio_device *adev = in->dev;
452 if (!adev->adm_register_input_stream)
453 return;
454
455 adev->adm_register_input_stream(adev->adm_data,
456 in->capture_handle,
457 in->flags);
458
459 if (!adev->adm_set_config)
460 return;
461
462 if (in->realtime)
463 adev->adm_set_config(adev->adm_data,
464 in->capture_handle,
465 in->pcm,
466 &in->config);
467}
468
469static void request_out_focus(struct stream_out *out, long ns)
470{
471 struct audio_device *adev = out->dev;
472
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700473 if (adev->adm_request_focus_v2)
474 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
475 else if (adev->adm_request_focus)
476 adev->adm_request_focus(adev->adm_data, out->handle);
477}
478
479static void request_in_focus(struct stream_in *in, long ns)
480{
481 struct audio_device *adev = in->dev;
482
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700483 if (adev->adm_request_focus_v2)
484 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
485 else if (adev->adm_request_focus)
486 adev->adm_request_focus(adev->adm_data, in->capture_handle);
487}
488
489static void release_out_focus(struct stream_out *out)
490{
491 struct audio_device *adev = out->dev;
492
493 if (adev->adm_abandon_focus)
494 adev->adm_abandon_focus(adev->adm_data, out->handle);
495}
496
497static void release_in_focus(struct stream_in *in)
498{
499 struct audio_device *adev = in->dev;
500 if (adev->adm_abandon_focus)
501 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
502}
503
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530504static int parse_snd_card_status(struct str_parms *parms, int *card,
505 card_status_t *status)
506{
507 char value[32]={0};
508 char state[32]={0};
509
510 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
511 if (ret < 0)
512 return -1;
513
514 // sscanf should be okay as value is of max length 32.
515 // same as sizeof state.
516 if (sscanf(value, "%d,%s", card, state) < 2)
517 return -1;
518
519 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
520 CARD_STATUS_OFFLINE;
521 return 0;
522}
523
vivek mehtaa76401a2015-04-24 14:12:15 -0700524__attribute__ ((visibility ("default")))
525bool audio_hw_send_gain_dep_calibration(int level) {
526 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700527 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700528
529 pthread_mutex_lock(&adev_init_lock);
530
531 if (adev != NULL && adev->platform != NULL) {
532 pthread_mutex_lock(&adev->lock);
533 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700534
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530535 // cache level info for any of the use case which
536 // was not started.
537 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700538
vivek mehtaa76401a2015-04-24 14:12:15 -0700539 pthread_mutex_unlock(&adev->lock);
540 } else {
541 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
542 }
543
544 pthread_mutex_unlock(&adev_init_lock);
545
546 return ret_val;
547}
548
Ashish Jain5106d362016-05-11 19:23:33 +0530549static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
550{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800551 bool gapless_enabled = false;
552 const char *mixer_ctl_name = "Compress Gapless Playback";
553 struct mixer_ctl *ctl;
554
555 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700556 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530557
558 /*Disable gapless if its AV playback*/
559 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800560
561 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
562 if (!ctl) {
563 ALOGE("%s: Could not get ctl for mixer cmd - %s",
564 __func__, mixer_ctl_name);
565 return -EINVAL;
566 }
567
568 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
569 ALOGE("%s: Could not set gapless mode %d",
570 __func__, gapless_enabled);
571 return -EINVAL;
572 }
573 return 0;
574}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700575
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700576__attribute__ ((visibility ("default")))
577int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
578 int table_size) {
579 int ret_val = 0;
580 ALOGV("%s: enter ... ", __func__);
581
582 pthread_mutex_lock(&adev_init_lock);
583 if (adev == NULL) {
584 ALOGW("%s: adev is NULL .... ", __func__);
585 goto done;
586 }
587
588 pthread_mutex_lock(&adev->lock);
589 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
590 pthread_mutex_unlock(&adev->lock);
591done:
592 pthread_mutex_unlock(&adev_init_lock);
593 ALOGV("%s: exit ... ", __func__);
594 return ret_val;
595}
596
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700597static bool is_supported_format(audio_format_t format)
598{
Eric Laurent86e17132013-09-12 17:49:30 -0700599 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530600 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530601 format == AUDIO_FORMAT_AAC_LC ||
602 format == AUDIO_FORMAT_AAC_HE_V1 ||
603 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530604 format == AUDIO_FORMAT_AAC_ADTS_LC ||
605 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
606 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530607 format == AUDIO_FORMAT_AAC_LATM_LC ||
608 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
609 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530610 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
611 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530612 format == AUDIO_FORMAT_PCM_FLOAT ||
613 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700614 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530615 format == AUDIO_FORMAT_AC3 ||
616 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700617 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530618 format == AUDIO_FORMAT_DTS ||
619 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800620 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530621 format == AUDIO_FORMAT_ALAC ||
622 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530623 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530624 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800625 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530626 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700627 format == AUDIO_FORMAT_APTX ||
628 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800629 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700630
631 return false;
632}
633
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700634static inline bool is_mmap_usecase(audio_usecase_t uc_id)
635{
636 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
637 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
638}
639
Avinash Vaish71a8b972014-07-24 15:36:33 +0530640static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
641 struct audio_usecase *uc_info)
642{
643 struct listnode *node;
644 struct audio_usecase *usecase;
645
646 if (uc_info == NULL)
647 return -EINVAL;
648
649 /* Re-route all voice usecases on the shared backend other than the
650 specified usecase to new snd devices */
651 list_for_each(node, &adev->usecase_list) {
652 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800653 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530654 enable_audio_route(adev, usecase);
655 }
656 return 0;
657}
658
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530659static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530660{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530661 ALOGV("%s", __func__);
662 audio_route_apply_and_update_path(adev->audio_route,
663 "asrc-mode");
664 adev->asrc_mode_enabled = true;
665}
666
667static void disable_asrc_mode(struct audio_device *adev)
668{
669 ALOGV("%s", __func__);
670 audio_route_reset_and_update_path(adev->audio_route,
671 "asrc-mode");
672 adev->asrc_mode_enabled = false;
673}
674
675/*
676 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
677 * 44.1 or Native DSD backends are enabled for any of current use case.
678 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
679 * - Disable current mix path use case(Headphone backend) and re-enable it with
680 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
681 * e.g. Naitve DSD or Headphone 44.1 -> + 48
682 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530683static void check_and_set_asrc_mode(struct audio_device *adev,
684 struct audio_usecase *uc_info,
685 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530686{
687 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530688 int i, num_new_devices = 0;
689 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
690 /*
691 *Split snd device for new combo use case
692 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
693 */
694 if (platform_split_snd_device(adev->platform,
695 snd_device,
696 &num_new_devices,
697 split_new_snd_devices) == 0) {
698 for (i = 0; i < num_new_devices; i++)
699 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
700 } else {
701 int new_backend_idx = platform_get_backend_index(snd_device);
702 if (((new_backend_idx == HEADPHONE_BACKEND) ||
703 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
704 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
705 !adev->asrc_mode_enabled) {
706 struct listnode *node = NULL;
707 struct audio_usecase *uc = NULL;
708 struct stream_out *curr_out = NULL;
709 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
710 int i, num_devices, ret = 0;
711 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530712
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530713 list_for_each(node, &adev->usecase_list) {
714 uc = node_to_item(node, struct audio_usecase, list);
715 curr_out = (struct stream_out*) uc->stream.out;
716 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
717 /*
718 *Split snd device for existing combo use case
719 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
720 */
721 ret = platform_split_snd_device(adev->platform,
722 uc->out_snd_device,
723 &num_devices,
724 split_snd_devices);
725 if (ret < 0 || num_devices == 0) {
726 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
727 split_snd_devices[0] = uc->out_snd_device;
728 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800729 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530730 for (i = 0; i < num_devices; i++) {
731 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
732 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
733 if((new_backend_idx == HEADPHONE_BACKEND) &&
734 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
735 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
736 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
737 __func__);
738 enable_asrc_mode(adev);
739 break;
740 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
741 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
742 (usecase_backend_idx == HEADPHONE_BACKEND)) {
743 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
744 __func__);
745 disable_audio_route(adev, uc);
746 disable_snd_device(adev, uc->out_snd_device);
747 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
748 if (new_backend_idx == DSD_NATIVE_BACKEND)
749 audio_route_apply_and_update_path(adev->audio_route,
750 "hph-true-highquality-mode");
751 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
752 (curr_out->bit_width >= 24))
753 audio_route_apply_and_update_path(adev->audio_route,
754 "hph-highquality-mode");
755 enable_asrc_mode(adev);
756 enable_snd_device(adev, uc->out_snd_device);
757 enable_audio_route(adev, uc);
758 break;
759 }
760 }
761 // reset split devices count
762 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800763 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530764 if (adev->asrc_mode_enabled)
765 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530766 }
767 }
768 }
769}
770
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700771int pcm_ioctl(struct pcm *pcm, int request, ...)
772{
773 va_list ap;
774 void * arg;
775 int pcm_fd = *(int*)pcm;
776
777 va_start(ap, request);
778 arg = va_arg(ap, void *);
779 va_end(ap);
780
781 return ioctl(pcm_fd, request, arg);
782}
783
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700784int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700785 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800786{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700787 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700788 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530789 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800790
791 if (usecase == NULL)
792 return -EINVAL;
793
794 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
795
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800796 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700797 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800798 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700799 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800800
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800801#ifdef DS1_DOLBY_DAP_ENABLED
802 audio_extn_dolby_set_dmid(adev);
803 audio_extn_dolby_set_endpoint(adev);
804#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700805 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700806 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530807 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700808 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530809 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530810 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
811 out = usecase->stream.out;
812 if (out && out->compr)
813 audio_extn_utils_compress_set_clk_rec_mode(usecase);
814 }
815
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800816 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700817 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700818 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700819 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800820 ALOGV("%s: exit", __func__);
821 return 0;
822}
823
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700824int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700825 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800826{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700828 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800829
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530830 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800831 return -EINVAL;
832
833 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 if (usecase->type == PCM_CAPTURE)
835 snd_device = usecase->in_snd_device;
836 else
837 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800838 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700839 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700840 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700841 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700842 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530843 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800844 ALOGV("%s: exit", __func__);
845 return 0;
846}
847
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700848int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700849 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800850{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530851 int i, num_devices = 0;
852 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700853 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
854
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800855 if (snd_device < SND_DEVICE_MIN ||
856 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800857 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800858 return -EINVAL;
859 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700860
861 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700862
863 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
864 ALOGE("%s: Invalid sound device returned", __func__);
865 return -EINVAL;
866 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700868 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700869 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 return 0;
871 }
872
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530873
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700874 if (audio_extn_spkr_prot_is_enabled())
875 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700876
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800877 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
878 audio_extn_spkr_prot_is_enabled()) {
879 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700880 adev->snd_dev_ref_cnt[snd_device]--;
881 return -EINVAL;
882 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200883 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800884 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800885 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200886 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800887 return -EINVAL;
888 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700889 } else if (platform_split_snd_device(adev->platform,
890 snd_device,
891 &num_devices,
892 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530893 for (i = 0; i < num_devices; i++) {
894 enable_snd_device(adev, new_snd_devices[i]);
895 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800896 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700897 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530898
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530899
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530900 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
901 (audio_extn_a2dp_start_playback() < 0)) {
902 ALOGE(" fail to configure A2dp control path ");
903 return -EINVAL;
904 }
905
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700906 /* due to the possibility of calibration overwrite between listen
907 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700908 audio_extn_sound_trigger_update_device_status(snd_device,
909 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530910 audio_extn_listen_update_device_status(snd_device,
911 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700912 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700913 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700914 audio_extn_sound_trigger_update_device_status(snd_device,
915 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530916 audio_extn_listen_update_device_status(snd_device,
917 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700918 return -EINVAL;
919 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300920 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700921 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530922
923 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
924 !adev->native_playback_enabled &&
925 audio_is_true_native_stream_active(adev)) {
926 ALOGD("%s: %d: napb: enabling native mode in hardware",
927 __func__, __LINE__);
928 audio_route_apply_and_update_path(adev->audio_route,
929 "true-native-mode");
930 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530931 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800932 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933 return 0;
934}
935
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700936int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700937 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800938{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530939 int i, num_devices = 0;
940 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700941 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
942
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800943 if (snd_device < SND_DEVICE_MIN ||
944 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800945 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800946 return -EINVAL;
947 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
949 ALOGE("%s: device ref cnt is already 0", __func__);
950 return -EINVAL;
951 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700952
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700954
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700955 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
956 ALOGE("%s: Invalid sound device returned", __func__);
957 return -EINVAL;
958 }
959
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700961 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530962
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800963 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
964 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700965 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700966 } else if (platform_split_snd_device(adev->platform,
967 snd_device,
968 &num_devices,
969 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530970 for (i = 0; i < num_devices; i++) {
971 disable_snd_device(adev, new_snd_devices[i]);
972 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300973 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700974 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300975 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700976
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530977 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
978 audio_extn_a2dp_stop_playback();
979
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700980 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530981 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530982 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
983 adev->native_playback_enabled) {
984 ALOGD("%s: %d: napb: disabling native mode in hardware",
985 __func__, __LINE__);
986 audio_route_reset_and_update_path(adev->audio_route,
987 "true-native-mode");
988 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530989 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
990 adev->asrc_mode_enabled) {
991 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530992 disable_asrc_mode(adev);
993 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530994 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530995
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200996 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700997 audio_extn_sound_trigger_update_device_status(snd_device,
998 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530999 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001000 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001002
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001003 return 0;
1004}
1005
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001006/*
1007 legend:
1008 uc - existing usecase
1009 new_uc - new usecase
1010 d1, d11, d2 - SND_DEVICE enums
1011 a1, a2 - corresponding ANDROID device enums
1012 B1, B2 - backend strings
1013
1014case 1
1015 uc->dev d1 (a1) B1
1016 new_uc->dev d1 (a1), d2 (a2) B1, B2
1017
1018 resolution: disable and enable uc->dev on d1
1019
1020case 2
1021 uc->dev d1 (a1) B1
1022 new_uc->dev d11 (a1) B1
1023
1024 resolution: need to switch uc since d1 and d11 are related
1025 (e.g. speaker and voice-speaker)
1026 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1027
1028case 3
1029 uc->dev d1 (a1) B1
1030 new_uc->dev d2 (a2) B2
1031
1032 resolution: no need to switch uc
1033
1034case 4
1035 uc->dev d1 (a1) B1
1036 new_uc->dev d2 (a2) B1
1037
1038 resolution: disable enable uc-dev on d2 since backends match
1039 we cannot enable two streams on two different devices if they
1040 share the same backend. e.g. if offload is on speaker device using
1041 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1042 using the same backend, offload must also be switched to voice-handset.
1043
1044case 5
1045 uc->dev d1 (a1) B1
1046 new_uc->dev d1 (a1), d2 (a2) B1
1047
1048 resolution: disable enable uc-dev on d2 since backends match
1049 we cannot enable two streams on two different devices if they
1050 share the same backend.
1051
1052case 6
1053 uc->dev d1 (a1) B1
1054 new_uc->dev d2 (a1) B2
1055
1056 resolution: no need to switch
1057
1058case 7
1059 uc->dev d1 (a1), d2 (a2) B1, B2
1060 new_uc->dev d1 (a1) B1
1061
1062 resolution: no need to switch
1063
1064*/
1065static snd_device_t derive_playback_snd_device(void * platform,
1066 struct audio_usecase *uc,
1067 struct audio_usecase *new_uc,
1068 snd_device_t new_snd_device)
1069{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301070 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001071
1072 snd_device_t d1 = uc->out_snd_device;
1073 snd_device_t d2 = new_snd_device;
1074
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301075 switch (uc->type) {
1076 case TRANSCODE_LOOPBACK :
1077 a1 = uc->stream.inout->out_config.devices;
1078 a2 = new_uc->stream.inout->out_config.devices;
1079 break;
1080 default :
1081 a1 = uc->stream.out->devices;
1082 a2 = new_uc->stream.out->devices;
1083 break;
1084 }
1085
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001086 // Treat as a special case when a1 and a2 are not disjoint
1087 if ((a1 != a2) && (a1 & a2)) {
1088 snd_device_t d3[2];
1089 int num_devices = 0;
1090 int ret = platform_split_snd_device(platform,
1091 popcount(a1) > 1 ? d1 : d2,
1092 &num_devices,
1093 d3);
1094 if (ret < 0) {
1095 if (ret != -ENOSYS) {
1096 ALOGW("%s failed to split snd_device %d",
1097 __func__,
1098 popcount(a1) > 1 ? d1 : d2);
1099 }
1100 goto end;
1101 }
1102
1103 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1104 // But if it does happen, we need to give priority to d2 if
1105 // the combo devices active on the existing usecase share a backend.
1106 // This is because we cannot have a usecase active on a combo device
1107 // and a new usecase requests one device in this combo pair.
1108 if (platform_check_backends_match(d3[0], d3[1])) {
1109 return d2; // case 5
1110 } else {
1111 return d1; // case 1
1112 }
1113 } else {
1114 if (platform_check_backends_match(d1, d2)) {
1115 return d2; // case 2, 4
1116 } else {
1117 return d1; // case 6, 3
1118 }
1119 }
1120
1121end:
1122 return d2; // return whatever was calculated before.
1123}
1124
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301126 struct audio_usecase *uc_info,
1127 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128{
1129 struct listnode *node;
1130 struct audio_usecase *usecase;
1131 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301132 snd_device_t uc_derive_snd_device;
1133 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001135 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301136 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 /*
1138 * This function is to make sure that all the usecases that are active on
1139 * the hardware codec backend are always routed to any one device that is
1140 * handled by the hardware codec.
1141 * For example, if low-latency and deep-buffer usecases are currently active
1142 * on speaker and out_set_parameters(headset) is received on low-latency
1143 * output, then we have to make sure deep-buffer is also switched to headset,
1144 * because of the limitation that both the devices cannot be enabled
1145 * at the same time as they share the same backend.
1146 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001147 /*
1148 * This call is to check if we need to force routing for a particular stream
1149 * If there is a backend configuration change for the device when a
1150 * new stream starts, then ADM needs to be closed and re-opened with the new
1151 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001152 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001153 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001154 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1155 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301156 /* For a2dp device reconfigure all active sessions
1157 * with new AFE encoder format based on a2dp state
1158 */
1159 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1160 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1161 audio_extn_a2dp_is_force_device_switch()) {
1162 force_routing = true;
1163 force_restart_session = true;
1164 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301165 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1166
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001168 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001169 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1171 switch_device[i] = false;
1172
1173 list_for_each(node, &adev->usecase_list) {
1174 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001175
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301176 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1177 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301178 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301179 platform_get_snd_device_name(usecase->out_snd_device),
1180 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301181 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1182 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1183 usecase, uc_info, snd_device);
1184 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1185 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1186 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1187 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1188 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1189 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1190 ((force_restart_session) ||
1191 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301192 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1193 __func__, use_case_table[usecase->id],
1194 platform_get_snd_device_name(usecase->out_snd_device));
1195 disable_audio_route(adev, usecase);
1196 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301197 /* Enable existing usecase on derived playback device */
1198 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301199 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301200 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001201 }
1202 }
1203
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301204 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1205 num_uc_to_switch);
1206
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001207 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001208 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001209
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301210 /* Make sure the previous devices to be disabled first and then enable the
1211 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001212 list_for_each(node, &adev->usecase_list) {
1213 usecase = node_to_item(node, struct audio_usecase, list);
1214 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001215 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001216 }
1217 }
1218
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001219 list_for_each(node, &adev->usecase_list) {
1220 usecase = node_to_item(node, struct audio_usecase, list);
1221 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301222 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001223 }
1224 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001225
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226 /* Re-route all the usecases on the shared backend other than the
1227 specified usecase to new snd devices */
1228 list_for_each(node, &adev->usecase_list) {
1229 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301230 /* Update the out_snd_device only before enabling the audio route */
1231 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301232 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301233 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301234 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301235 use_case_table[usecase->id],
1236 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001237 /* Update voc calibration before enabling VoIP route */
1238 if (usecase->type == VOIP_CALL)
1239 status = platform_switch_voice_call_device_post(adev->platform,
1240 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001241 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301242 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301243 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001244 }
1245 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001246 }
1247}
1248
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301249static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001250 struct audio_usecase *uc_info,
1251 snd_device_t snd_device)
1252{
1253 struct listnode *node;
1254 struct audio_usecase *usecase;
1255 bool switch_device[AUDIO_USECASE_MAX];
1256 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301257 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001258 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001259
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301260 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1261 snd_device);
1262 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301263
1264 /*
1265 * Make sure out devices is checked against out codec backend device and
1266 * also in devices against in codec backend. Checking out device against in
1267 * codec backend or vice versa causes issues.
1268 */
1269 if (uc_info->type == PCM_CAPTURE)
1270 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001271 /*
1272 * This function is to make sure that all the active capture usecases
1273 * are always routed to the same input sound device.
1274 * For example, if audio-record and voice-call usecases are currently
1275 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1276 * is received for voice call then we have to make sure that audio-record
1277 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1278 * because of the limitation that two devices cannot be enabled
1279 * at the same time if they share the same backend.
1280 */
1281 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1282 switch_device[i] = false;
1283
1284 list_for_each(node, &adev->usecase_list) {
1285 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301286 /*
1287 * TODO: Enhance below condition to handle BT sco/USB multi recording
1288 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001289 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001290 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301291 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301292 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301293 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301294 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001295 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001296 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1297 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001298 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001299 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001300 switch_device[usecase->id] = true;
1301 num_uc_to_switch++;
1302 }
1303 }
1304
1305 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001306 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001307
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301308 /* Make sure the previous devices to be disabled first and then enable the
1309 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001310 list_for_each(node, &adev->usecase_list) {
1311 usecase = node_to_item(node, struct audio_usecase, list);
1312 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001313 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001314 }
1315 }
1316
1317 list_for_each(node, &adev->usecase_list) {
1318 usecase = node_to_item(node, struct audio_usecase, list);
1319 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001320 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001321 }
1322 }
1323
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001324 /* Re-route all the usecases on the shared backend other than the
1325 specified usecase to new snd devices */
1326 list_for_each(node, &adev->usecase_list) {
1327 usecase = node_to_item(node, struct audio_usecase, list);
1328 /* Update the in_snd_device only before enabling the audio route */
1329 if (switch_device[usecase->id] ) {
1330 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001331 if (usecase->type != VOICE_CALL) {
1332 /* Update voc calibration before enabling VoIP route */
1333 if (usecase->type == VOIP_CALL)
1334 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001335 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001336 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301337 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001338 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001339 }
1340 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001341 }
1342}
1343
Mingming Yin3a941d42016-02-17 18:08:05 -08001344static void reset_hdmi_sink_caps(struct stream_out *out) {
1345 int i = 0;
1346
1347 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1348 out->supported_channel_masks[i] = 0;
1349 }
1350 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1351 out->supported_formats[i] = 0;
1352 }
1353 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1354 out->supported_sample_rates[i] = 0;
1355 }
1356}
1357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001359static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001360{
Mingming Yin3a941d42016-02-17 18:08:05 -08001361 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001362 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001363
Mingming Yin3a941d42016-02-17 18:08:05 -08001364 reset_hdmi_sink_caps(out);
1365
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001366 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001367 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001368 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001369 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001370 }
1371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001374 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001375 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001376 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1377 case 6:
1378 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1379 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1380 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1381 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1382 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1383 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384 break;
1385 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001386 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001387 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388 break;
1389 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001390
1391 // check channel format caps
1392 i = 0;
1393 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1394 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1395 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1396 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1397 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1398 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1399 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1400 }
1401
Ben Romberger1aaaf862017-04-06 17:49:46 -07001402 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1403 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1404 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1405 }
1406
Mingming Yin3a941d42016-02-17 18:08:05 -08001407 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1408 ALOGV(":%s HDMI supports DTS format", __func__);
1409 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1410 }
1411
1412 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1413 ALOGV(":%s HDMI supports DTS HD format", __func__);
1414 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1415 }
1416
Naresh Tanniru928f0862017-04-07 16:44:23 -07001417 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1418 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1419 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1420 }
1421
Mingming Yin3a941d42016-02-17 18:08:05 -08001422
1423 // check sample rate caps
1424 i = 0;
1425 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1426 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1427 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1428 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1429 }
1430 }
1431
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001432 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433}
1434
Alexy Josephb1379942016-01-29 15:49:38 -08001435audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001436 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001437{
1438 struct audio_usecase *usecase;
1439 struct listnode *node;
1440
1441 list_for_each(node, &adev->usecase_list) {
1442 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001443 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001444 ALOGV("%s: usecase id %d", __func__, usecase->id);
1445 return usecase->id;
1446 }
1447 }
1448 return USECASE_INVALID;
1449}
1450
Alexy Josephb1379942016-01-29 15:49:38 -08001451struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001452 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001453{
1454 struct audio_usecase *usecase;
1455 struct listnode *node;
1456
1457 list_for_each(node, &adev->usecase_list) {
1458 usecase = node_to_item(node, struct audio_usecase, list);
1459 if (usecase->id == uc_id)
1460 return usecase;
1461 }
1462 return NULL;
1463}
1464
Dhananjay Kumard4833242016-10-06 22:09:12 +05301465struct stream_in *get_next_active_input(const struct audio_device *adev)
1466{
1467 struct audio_usecase *usecase;
1468 struct listnode *node;
1469
1470 list_for_each_reverse(node, &adev->usecase_list) {
1471 usecase = node_to_item(node, struct audio_usecase, list);
1472 if (usecase->type == PCM_CAPTURE)
1473 return usecase->stream.in;
1474 }
1475 return NULL;
1476}
1477
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301478/*
1479 * is a true native playback active
1480 */
1481bool audio_is_true_native_stream_active(struct audio_device *adev)
1482{
1483 bool active = false;
1484 int i = 0;
1485 struct listnode *node;
1486
1487 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1488 ALOGV("%s:napb: not in true mode or non hdphones device",
1489 __func__);
1490 active = false;
1491 goto exit;
1492 }
1493
1494 list_for_each(node, &adev->usecase_list) {
1495 struct audio_usecase *uc;
1496 uc = node_to_item(node, struct audio_usecase, list);
1497 struct stream_out *curr_out =
1498 (struct stream_out*) uc->stream.out;
1499
1500 if (curr_out && PCM_PLAYBACK == uc->type) {
1501 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1502 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1503 uc->id, curr_out->sample_rate,
1504 curr_out->bit_width,
1505 platform_get_snd_device_name(uc->out_snd_device));
1506
1507 if (is_offload_usecase(uc->id) &&
1508 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1509 active = true;
1510 ALOGD("%s:napb:native stream detected", __func__);
1511 }
1512 }
1513 }
1514exit:
1515 return active;
1516}
1517
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001518uint32_t adev_get_dsp_bit_width_enforce_mode()
1519{
1520 if (adev == NULL) {
1521 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1522 return 0;
1523 }
1524 return adev->dsp_bit_width_enforce_mode;
1525}
1526
1527static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1528{
1529 char value[PROPERTY_VALUE_MAX];
1530 int trial;
1531 uint32_t dsp_bit_width_enforce_mode = 0;
1532
1533 if (!mixer) {
1534 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1535 __func__);
1536 return 0;
1537 }
1538
1539 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1540 value, NULL) > 0) {
1541 trial = atoi(value);
1542 switch (trial) {
1543 case 16:
1544 dsp_bit_width_enforce_mode = 16;
1545 break;
1546 case 24:
1547 dsp_bit_width_enforce_mode = 24;
1548 break;
1549 case 32:
1550 dsp_bit_width_enforce_mode = 32;
1551 break;
1552 default:
1553 dsp_bit_width_enforce_mode = 0;
1554 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1555 break;
1556 }
1557 }
1558
1559 return dsp_bit_width_enforce_mode;
1560}
1561
1562static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1563 uint32_t enforce_mode,
1564 bool enable)
1565{
1566 struct mixer_ctl *ctl = NULL;
1567 const char *mixer_ctl_name = "ASM Bit Width";
1568 uint32_t asm_bit_width_mode = 0;
1569
1570 if (enforce_mode == 0) {
1571 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1572 return;
1573 }
1574
1575 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1576 if (!ctl) {
1577 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1578 __func__, mixer_ctl_name);
1579 return;
1580 }
1581
1582 if (enable)
1583 asm_bit_width_mode = enforce_mode;
1584 else
1585 asm_bit_width_mode = 0;
1586
1587 ALOGV("%s DSP bit width feature status is %d width=%d",
1588 __func__, enable, asm_bit_width_mode);
1589 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1590 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1591 asm_bit_width_mode);
1592
1593 return;
1594}
1595
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301596/*
1597 * if native DSD playback active
1598 */
1599bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1600{
1601 bool active = false;
1602 struct listnode *node = NULL;
1603 struct audio_usecase *uc = NULL;
1604 struct stream_out *curr_out = NULL;
1605
1606 list_for_each(node, &adev->usecase_list) {
1607 uc = node_to_item(node, struct audio_usecase, list);
1608 curr_out = (struct stream_out*) uc->stream.out;
1609
1610 if (curr_out && PCM_PLAYBACK == uc->type &&
1611 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1612 active = true;
1613 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301614 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301615 }
1616 }
1617 return active;
1618}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301619
1620static bool force_device_switch(struct audio_usecase *usecase)
1621{
1622 bool ret = false;
1623 bool is_it_true_mode = false;
1624
1625 if (is_offload_usecase(usecase->id) &&
1626 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001627 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1628 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1629 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301630 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1631 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1632 (!is_it_true_mode && adev->native_playback_enabled)){
1633 ret = true;
1634 ALOGD("napb: time to toggle native mode");
1635 }
1636 }
1637
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301638 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301639 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1640 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301641 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001642 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301643 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301644 ALOGD("Force a2dp device switch to update new encoder config");
1645 ret = true;
1646 }
1647
Manish Dewangan671a4202017-08-18 17:30:46 +05301648 if (usecase->stream.out->stream_config_changed) {
1649 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1650 return true;
1651 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301652 return ret;
1653}
1654
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301655bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1656{
1657 bool ret=false;
1658 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1659 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1660 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1661 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1662 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1663 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1664 ret = true;
1665
1666 return ret;
1667}
1668
1669bool is_a2dp_device(snd_device_t out_snd_device)
1670{
1671 bool ret=false;
1672 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1673 ret = true;
1674
1675 return ret;
1676}
1677
1678bool is_bt_soc_on(struct audio_device *adev)
1679{
1680 struct mixer_ctl *ctl;
1681 char *mixer_ctl_name = "BT SOC status";
1682 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1683 bool bt_soc_status = true;
1684 if (!ctl) {
1685 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1686 __func__, mixer_ctl_name);
1687 /*This is to ensure we dont break targets which dont have the kernel change*/
1688 return true;
1689 }
1690 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1691 ALOGD("BT SOC status: %d",bt_soc_status);
1692 return bt_soc_status;
1693}
1694
1695int out_standby_l(struct audio_stream *stream);
1696
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001697int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001699 snd_device_t out_snd_device = SND_DEVICE_NONE;
1700 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001701 struct audio_usecase *usecase = NULL;
1702 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001703 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001704 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301705 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001706 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001707 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301709 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1710
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001711 usecase = get_usecase_from_list(adev, uc_id);
1712 if (usecase == NULL) {
1713 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1714 return -EINVAL;
1715 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001717 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001718 (usecase->type == VOIP_CALL) ||
1719 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301720 if(usecase->stream.out == NULL) {
1721 ALOGE("%s: stream.out is NULL", __func__);
1722 return -EINVAL;
1723 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001724 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001725 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001726 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001727 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301728 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1729 if (usecase->stream.inout == NULL) {
1730 ALOGE("%s: stream.inout is NULL", __func__);
1731 return -EINVAL;
1732 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301733 stream_out.devices = usecase->stream.inout->out_config.devices;
1734 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
1735 stream_out.format = usecase->stream.inout->out_config.format;
1736 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
1737 out_snd_device = platform_get_output_snd_device(adev->platform,
1738 &stream_out);
1739 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301740 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001741 } else {
1742 /*
1743 * If the voice call is active, use the sound devices of voice call usecase
1744 * so that it would not result any device switch. All the usecases will
1745 * be switched to new device when select_devices() is called for voice call
1746 * usecase. This is to avoid switching devices for voice call when
1747 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001748 * choose voice call device only if the use case device is
1749 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001750 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001751 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001752 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001753 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001754 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1755 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301756 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1757 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001758 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001759 in_snd_device = vc_usecase->in_snd_device;
1760 out_snd_device = vc_usecase->out_snd_device;
1761 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001762 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001763 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001764 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001765 if ((voip_usecase != NULL) &&
1766 (usecase->type == PCM_PLAYBACK) &&
1767 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001768 out_snd_device_backend_match = platform_check_backends_match(
1769 voip_usecase->out_snd_device,
1770 platform_get_output_snd_device(
1771 adev->platform,
1772 usecase->stream.out));
1773 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001774 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001775 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1776 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001777 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001778 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001779 in_snd_device = voip_usecase->in_snd_device;
1780 out_snd_device = voip_usecase->out_snd_device;
1781 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001782 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001783 hfp_ucid = audio_extn_hfp_get_usecase();
1784 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001785 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001786 in_snd_device = hfp_usecase->in_snd_device;
1787 out_snd_device = hfp_usecase->out_snd_device;
1788 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001789 }
1790 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301791 if (usecase->stream.out == NULL) {
1792 ALOGE("%s: stream.out is NULL", __func__);
1793 return -EINVAL;
1794 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795 usecase->devices = usecase->stream.out->devices;
1796 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001797 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001798 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001799 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001800 if (usecase->stream.out == adev->primary_output &&
1801 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001802 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001803 select_devices(adev, adev->active_input->usecase);
1804 }
1805 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001806 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301807 if (usecase->stream.in == NULL) {
1808 ALOGE("%s: stream.in is NULL", __func__);
1809 return -EINVAL;
1810 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001811 usecase->devices = usecase->stream.in->device;
1812 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001813 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001814 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001815 if (adev->active_input &&
1816 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301817 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1818 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1819 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001820 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001821 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001822 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1823 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001824 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001825 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001826 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001827 }
1828 }
1829
1830 if (out_snd_device == usecase->out_snd_device &&
1831 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301832
1833 if (!force_device_switch(usecase))
1834 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835 }
1836
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301837 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1838 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1839 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1840 return 0;
1841 }
1842
sangwoobc677242013-08-08 16:53:43 +09001843 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001844 out_snd_device, platform_get_snd_device_name(out_snd_device),
1845 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 /*
1848 * Limitation: While in call, to do a device switch we need to disable
1849 * and enable both RX and TX devices though one of them is same as current
1850 * device.
1851 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001852 if ((usecase->type == VOICE_CALL) &&
1853 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1854 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001855 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001856 }
1857
1858 if (((usecase->type == VOICE_CALL) ||
1859 (usecase->type == VOIP_CALL)) &&
1860 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1861 /* Disable sidetone only if voice/voip call already exists */
1862 if (voice_is_call_state_active(adev) ||
1863 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001864 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001865
1866 /* Disable aanc only if voice call exists */
1867 if (voice_is_call_state_active(adev))
1868 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001869 }
1870
Zhou Songc66eb7e2017-08-08 18:29:07 +08001871 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301872 (!audio_extn_a2dp_is_ready())) {
1873 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08001874 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301875 }
1876
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001877 /* Disable current sound devices */
1878 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001879 disable_audio_route(adev, usecase);
1880 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 }
1882
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001884 disable_audio_route(adev, usecase);
1885 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 }
1887
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001888 /* Applicable only on the targets that has external modem.
1889 * New device information should be sent to modem before enabling
1890 * the devices to reduce in-call device switch time.
1891 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001892 if ((usecase->type == VOICE_CALL) &&
1893 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1894 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001895 status = platform_switch_voice_call_enable_device_config(adev->platform,
1896 out_snd_device,
1897 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001898 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001899
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001900 /* Enable new sound devices */
1901 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001902 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301903 if (platform_check_codec_asrc_support(adev->platform))
1904 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001905 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 }
1907
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001908 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301909 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001910 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001911 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001912
Avinash Vaish71a8b972014-07-24 15:36:33 +05301913 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001914 status = platform_switch_voice_call_device_post(adev->platform,
1915 out_snd_device,
1916 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301917 enable_audio_route_for_voice_usecases(adev, usecase);
1918 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001919
sangwoo170731f2013-06-08 15:36:36 +09001920 usecase->in_snd_device = in_snd_device;
1921 usecase->out_snd_device = out_snd_device;
1922
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301923 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1924 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301925 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001926 if ((24 == usecase->stream.out->bit_width) &&
1927 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1928 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1929 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1930 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1931 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1932 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1933 /*
1934 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1935 * configured device sample rate, if not update the COPP rate to be equal to the
1936 * device sample rate, else open COPP at stream sample rate
1937 */
1938 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1939 usecase->stream.out->sample_rate,
1940 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301941 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1942 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001943 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1944 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1945 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1946 }
1947
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001948 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001949 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001950 audio_extn_gef_notify_device_config(
1951 usecase->stream.out->devices,
1952 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001953 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001954 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001955 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301956 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001957 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001958
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001959 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001960 /* Enable aanc only if voice call exists */
1961 if (voice_is_call_state_active(adev))
1962 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1963
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001964 /* Enable sidetone only if other voice/voip call already exists */
1965 if (voice_is_call_state_active(adev) ||
1966 voice_extn_compress_voip_is_started(adev))
1967 voice_set_sidetone(adev, out_snd_device, true);
1968 }
1969
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001970 /* Applicable only on the targets that has external modem.
1971 * Enable device command should be sent to modem only after
1972 * enabling voice call mixer controls
1973 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001974 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001975 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1976 out_snd_device,
1977 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301978
1979 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1980
1981 if (usecase->type == VOIP_CALL) {
1982 if (adev->active_input != NULL &&
1983 !adev->active_input->standby) {
1984 if (is_bt_soc_on(adev) == false){
1985 ALOGD("BT SCO MIC disconnected while in connection");
1986 if (adev->active_input->pcm != NULL)
1987 pcm_stop(adev->active_input->pcm);
1988 }
1989 }
1990 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
1991 && usecase->stream.out->started) {
1992 if (is_bt_soc_on(adev) == false) {
1993 ALOGD("BT SCO/A2DP disconnected while in connection");
1994 out_standby_l(&usecase->stream.out->stream.common);
1995 }
1996 }
1997 } else if ((usecase->stream.out != NULL) &&
1998 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
1999 usecase->stream.out->started) {
2000 if (is_bt_soc_on(adev) == false) {
2001 ALOGD("BT SCO/A2dp disconnected while in connection");
2002 out_standby_l(&usecase->stream.out->stream.common);
2003 }
2004 }
2005 }
2006
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302007 ALOGD("%s: done",__func__);
2008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 return status;
2010}
2011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012static int stop_input_stream(struct stream_in *in)
2013{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302014 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015 struct audio_usecase *uc_info;
2016 struct audio_device *adev = in->dev;
2017
Eric Laurent994a6932013-07-17 11:51:42 -07002018 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002019 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020 uc_info = get_usecase_from_list(adev, in->usecase);
2021 if (uc_info == NULL) {
2022 ALOGE("%s: Could not find the usecase (%d) in the list",
2023 __func__, in->usecase);
2024 return -EINVAL;
2025 }
2026
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002027 /* Close in-call recording streams */
2028 voice_check_and_stop_incall_rec_usecase(adev, in);
2029
Eric Laurent150dbfe2013-02-27 14:31:02 -08002030 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002031 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002032
2033 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002034 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002036 list_remove(&uc_info->list);
2037 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002039 adev->active_input = get_next_active_input(adev);
2040
Eric Laurent994a6932013-07-17 11:51:42 -07002041 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 return ret;
2043}
2044
2045int start_input_stream(struct stream_in *in)
2046{
2047 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002048 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 struct audio_usecase *uc_info;
2050 struct audio_device *adev = in->dev;
2051
Mingming Yin2664a5b2015-09-03 10:53:11 -07002052 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
2053 if (get_usecase_from_list(adev, usecase) == NULL)
2054 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302055 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2056 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002057
Naresh Tanniru80659832014-06-04 18:17:56 +05302058
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302059 if (CARD_STATUS_OFFLINE == in->card_status||
2060 CARD_STATUS_OFFLINE == adev->card_status) {
2061 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302062 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302063 goto error_config;
2064 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302065
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302066 if (audio_is_bluetooth_sco_device(in->device)) {
2067 if (!adev->bt_sco_on) {
2068 ALOGE("%s: SCO profile is not ready, return error", __func__);
2069 ret = -EIO;
2070 goto error_config;
2071 }
2072 }
2073
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002074 /* Check if source matches incall recording usecase criteria */
2075 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2076 if (ret)
2077 goto error_config;
2078 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002079 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2080
2081 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2082 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2083 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002084 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002085 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002086
Eric Laurentb23d5282013-05-14 15:27:20 -07002087 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088 if (in->pcm_device_id < 0) {
2089 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2090 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002091 ret = -EINVAL;
2092 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002094
2095 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002097
2098 if (!uc_info) {
2099 ret = -ENOMEM;
2100 goto error_config;
2101 }
2102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 uc_info->id = in->usecase;
2104 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002105 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002106 uc_info->devices = in->device;
2107 uc_info->in_snd_device = SND_DEVICE_NONE;
2108 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002110 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302111 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2112 adev->perf_lock_opts,
2113 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002114 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115
Haynes Mathew George16081042017-05-31 17:16:49 -07002116 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302117 ret = audio_extn_cin_start_input_stream(in);
2118 if (ret)
2119 goto error_open;
2120 else
2121 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002122 }
2123
Haynes Mathew George16081042017-05-31 17:16:49 -07002124 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002125 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002126 ALOGE("%s: pcm stream not ready", __func__);
2127 goto error_open;
2128 }
2129 ret = pcm_start(in->pcm);
2130 if (ret < 0) {
2131 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2132 goto error_open;
2133 }
2134 } else {
2135 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2136 unsigned int pcm_open_retry_count = 0;
2137
2138 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2139 flags |= PCM_MMAP | PCM_NOIRQ;
2140 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2141 } else if (in->realtime) {
2142 flags |= PCM_MMAP | PCM_NOIRQ;
2143 }
2144
2145 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2146 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2147
2148 while (1) {
2149 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
2150 flags, &in->config);
2151 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2152 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2153 if (in->pcm != NULL) {
2154 pcm_close(in->pcm);
2155 in->pcm = NULL;
2156 }
2157 if (pcm_open_retry_count-- == 0) {
2158 ret = -EIO;
2159 goto error_open;
2160 }
2161 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2162 continue;
2163 }
2164 break;
2165 }
2166
2167 ALOGV("%s: pcm_prepare", __func__);
2168 ret = pcm_prepare(in->pcm);
2169 if (ret < 0) {
2170 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2171 pcm_close(in->pcm);
2172 in->pcm = NULL;
2173 goto error_open;
2174 }
2175 register_in_stream(in);
2176 if (in->realtime) {
2177 ret = pcm_start(in->pcm);
2178 if (ret < 0) {
2179 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002180 pcm_close(in->pcm);
2181 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002182 goto error_open;
2183 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002184 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002185 }
2186
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302187done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302188 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002189 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002190
Eric Laurentc8400632013-02-14 19:04:54 -08002191 return ret;
2192
2193error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302194 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002196error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302197 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302198 /*
2199 * sleep 50ms to allow sufficient time for kernel
2200 * drivers to recover incases like SSR.
2201 */
2202 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002203 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002204
2205 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206}
2207
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002208void lock_input_stream(struct stream_in *in)
2209{
2210 pthread_mutex_lock(&in->pre_lock);
2211 pthread_mutex_lock(&in->lock);
2212 pthread_mutex_unlock(&in->pre_lock);
2213}
2214
2215void lock_output_stream(struct stream_out *out)
2216{
2217 pthread_mutex_lock(&out->pre_lock);
2218 pthread_mutex_lock(&out->lock);
2219 pthread_mutex_unlock(&out->pre_lock);
2220}
2221
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222/* must be called with out->lock locked */
2223static int send_offload_cmd_l(struct stream_out* out, int command)
2224{
2225 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2226
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002227 if (!cmd) {
2228 ALOGE("failed to allocate mem for command 0x%x", command);
2229 return -ENOMEM;
2230 }
2231
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 ALOGVV("%s %d", __func__, command);
2233
2234 cmd->cmd = command;
2235 list_add_tail(&out->offload_cmd_list, &cmd->node);
2236 pthread_cond_signal(&out->offload_cond);
2237 return 0;
2238}
2239
2240/* must be called iwth out->lock locked */
2241static void stop_compressed_output_l(struct stream_out *out)
2242{
2243 out->offload_state = OFFLOAD_STATE_IDLE;
2244 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002245 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 if (out->compr != NULL) {
2247 compress_stop(out->compr);
2248 while (out->offload_thread_blocked) {
2249 pthread_cond_wait(&out->cond, &out->lock);
2250 }
2251 }
2252}
2253
Varun Balaraje49253e2017-07-06 19:48:56 +05302254bool is_interactive_usecase(audio_usecase_t uc_id)
2255{
2256 unsigned int i;
2257 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2258 if (uc_id == interactive_usecases[i])
2259 return true;
2260 }
2261 return false;
2262}
2263
2264static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2265{
2266 audio_usecase_t ret_uc = USECASE_INVALID;
2267 unsigned int intract_uc_index;
2268 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2269
2270 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2271 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2272 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2273 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2274 ret_uc = interactive_usecases[intract_uc_index];
2275 break;
2276 }
2277 }
2278
2279 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2280 return ret_uc;
2281}
2282
2283static void free_interactive_usecase(struct audio_device *adev,
2284 audio_usecase_t uc_id)
2285{
2286 unsigned int interact_uc_index;
2287 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2288
2289 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2290 if (interactive_usecases[interact_uc_index] == uc_id) {
2291 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2292 break;
2293 }
2294 }
2295 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2296}
2297
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002298bool is_offload_usecase(audio_usecase_t uc_id)
2299{
2300 unsigned int i;
2301 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2302 if (uc_id == offload_usecases[i])
2303 return true;
2304 }
2305 return false;
2306}
2307
Dhananjay Kumarac341582017-02-23 23:42:25 +05302308static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002309{
vivek mehta446c3962015-09-14 10:57:35 -07002310 audio_usecase_t ret_uc = USECASE_INVALID;
2311 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002312 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002313 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302314 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002315 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2316 else
2317 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002318
vivek mehta446c3962015-09-14 10:57:35 -07002319 pthread_mutex_lock(&adev->lock);
2320 if (get_usecase_from_list(adev, ret_uc) != NULL)
2321 ret_uc = USECASE_INVALID;
2322 pthread_mutex_unlock(&adev->lock);
2323
2324 return ret_uc;
2325 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002326
2327 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002328 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2329 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2330 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2331 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002332 break;
2333 }
2334 }
vivek mehta446c3962015-09-14 10:57:35 -07002335
2336 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2337 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002338}
2339
2340static void free_offload_usecase(struct audio_device *adev,
2341 audio_usecase_t uc_id)
2342{
vivek mehta446c3962015-09-14 10:57:35 -07002343 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002344 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002345
2346 if (!adev->multi_offload_enable)
2347 return;
2348
2349 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2350 if (offload_usecases[offload_uc_index] == uc_id) {
2351 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002352 break;
2353 }
2354 }
2355 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2356}
2357
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358static void *offload_thread_loop(void *context)
2359{
2360 struct stream_out *out = (struct stream_out *) context;
2361 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002362 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2365 set_sched_policy(0, SP_FOREGROUND);
2366 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2367
2368 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002369 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 for (;;) {
2371 struct offload_cmd *cmd = NULL;
2372 stream_callback_event_t event;
2373 bool send_callback = false;
2374
2375 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2376 __func__, list_empty(&out->offload_cmd_list),
2377 out->offload_state);
2378 if (list_empty(&out->offload_cmd_list)) {
2379 ALOGV("%s SLEEPING", __func__);
2380 pthread_cond_wait(&out->offload_cond, &out->lock);
2381 ALOGV("%s RUNNING", __func__);
2382 continue;
2383 }
2384
2385 item = list_head(&out->offload_cmd_list);
2386 cmd = node_to_item(item, struct offload_cmd, node);
2387 list_remove(item);
2388
2389 ALOGVV("%s STATE %d CMD %d out->compr %p",
2390 __func__, out->offload_state, cmd->cmd, out->compr);
2391
2392 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2393 free(cmd);
2394 break;
2395 }
2396
2397 if (out->compr == NULL) {
2398 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002399 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002400 pthread_cond_signal(&out->cond);
2401 continue;
2402 }
2403 out->offload_thread_blocked = true;
2404 pthread_mutex_unlock(&out->lock);
2405 send_callback = false;
2406 switch(cmd->cmd) {
2407 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002408 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002410 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002411 send_callback = true;
2412 event = STREAM_CBK_EVENT_WRITE_READY;
2413 break;
2414 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002415 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302416 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002417 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302418 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002419 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302420 if (ret < 0)
2421 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302422 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302423 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002424 compress_drain(out->compr);
2425 else
2426 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302427 if (ret != -ENETRESET) {
2428 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302429 pthread_mutex_lock(&out->lock);
2430 out->send_new_metadata = 1;
2431 out->send_next_track_params = true;
2432 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302433 event = STREAM_CBK_EVENT_DRAIN_READY;
2434 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2435 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302436 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 break;
2438 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002439 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002440 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002441 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002442 send_callback = true;
2443 event = STREAM_CBK_EVENT_DRAIN_READY;
2444 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302445 case OFFLOAD_CMD_ERROR:
2446 ALOGD("copl(%p): sending error callback to AF", out);
2447 send_callback = true;
2448 event = STREAM_CBK_EVENT_ERROR;
2449 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002450 default:
2451 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2452 break;
2453 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002454 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 out->offload_thread_blocked = false;
2456 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002457 if (send_callback && out->client_callback) {
2458 ALOGVV("%s: sending client_callback event %d", __func__, event);
2459 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002460 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002461 free(cmd);
2462 }
2463
2464 pthread_cond_signal(&out->cond);
2465 while (!list_empty(&out->offload_cmd_list)) {
2466 item = list_head(&out->offload_cmd_list);
2467 list_remove(item);
2468 free(node_to_item(item, struct offload_cmd, node));
2469 }
2470 pthread_mutex_unlock(&out->lock);
2471
2472 return NULL;
2473}
2474
2475static int create_offload_callback_thread(struct stream_out *out)
2476{
2477 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2478 list_init(&out->offload_cmd_list);
2479 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2480 offload_thread_loop, out);
2481 return 0;
2482}
2483
2484static int destroy_offload_callback_thread(struct stream_out *out)
2485{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002486 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487 stop_compressed_output_l(out);
2488 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2489
2490 pthread_mutex_unlock(&out->lock);
2491 pthread_join(out->offload_thread, (void **) NULL);
2492 pthread_cond_destroy(&out->offload_cond);
2493
2494 return 0;
2495}
2496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497static int stop_output_stream(struct stream_out *out)
2498{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302499 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 struct audio_usecase *uc_info;
2501 struct audio_device *adev = out->dev;
2502
Eric Laurent994a6932013-07-17 11:51:42 -07002503 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002504 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 uc_info = get_usecase_from_list(adev, out->usecase);
2506 if (uc_info == NULL) {
2507 ALOGE("%s: Could not find the usecase (%d) in the list",
2508 __func__, out->usecase);
2509 return -EINVAL;
2510 }
2511
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002512 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302513 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002514 if (adev->visualizer_stop_output != NULL)
2515 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002516
2517 audio_extn_dts_remove_state_notifier_node(out->usecase);
2518
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002519 if (adev->offload_effects_stop_output != NULL)
2520 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2521 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002522
Eric Laurent150dbfe2013-02-27 14:31:02 -08002523 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002524 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002525
2526 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002527 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002529 if (is_offload_usecase(out->usecase)) {
2530 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2531 adev->dsp_bit_width_enforce_mode,
2532 false);
2533 }
2534
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002535 list_remove(&uc_info->list);
2536 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302537 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002538 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302539 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002540 ALOGV("Disable passthrough , reset mixer to pcm");
2541 /* NO_PASSTHROUGH */
2542 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002543 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002544 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2545 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002546
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302547 /* Must be called after removing the usecase from list */
2548 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302549 audio_extn_keep_alive_start();
2550
Manish Dewangan21a850a2017-08-14 12:03:55 +05302551 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002552 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2553 if (ret < 0)
2554 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2555 }
2556
Eric Laurent994a6932013-07-17 11:51:42 -07002557 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 return ret;
2559}
2560
2561int start_output_stream(struct stream_out *out)
2562{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 struct audio_usecase *uc_info;
2565 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002566 char mixer_ctl_name[128];
2567 struct mixer_ctl *ctl = NULL;
2568 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302569 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002571 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2572 ret = -EINVAL;
2573 goto error_config;
2574 }
2575
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302576 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2577 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2578 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302579
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302580 if (CARD_STATUS_OFFLINE == out->card_status ||
2581 CARD_STATUS_OFFLINE == adev->card_status) {
2582 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302583 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302584 goto error_config;
2585 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302586
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302587 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2588 if (!audio_extn_a2dp_is_ready()) {
2589 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302590 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302591 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302592 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2593 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2594 ret = -EAGAIN;
2595 goto error_config;
2596 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302597 }
2598 }
2599 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302600 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2601 if (!adev->bt_sco_on) {
2602 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2603 //combo usecase just by pass a2dp
2604 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2605 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2606 } else {
2607 ALOGE("%s: SCO profile is not ready, return error", __func__);
2608 ret = -EAGAIN;
2609 goto error_config;
2610 }
2611 }
2612 }
2613
Eric Laurentb23d5282013-05-14 15:27:20 -07002614 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615 if (out->pcm_device_id < 0) {
2616 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2617 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002618 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002619 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620 }
2621
2622 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002623
2624 if (!uc_info) {
2625 ret = -ENOMEM;
2626 goto error_config;
2627 }
2628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 uc_info->id = out->usecase;
2630 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002631 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002632 uc_info->devices = out->devices;
2633 uc_info->in_snd_device = SND_DEVICE_NONE;
2634 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002635 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302637 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2638 adev->perf_lock_opts,
2639 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302640
2641 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2642 audio_extn_keep_alive_stop();
2643 if (audio_extn_passthru_is_enabled() &&
2644 audio_extn_passthru_is_passthrough_stream(out)) {
2645 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302646 }
2647 }
2648
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302649 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2650 (!audio_extn_a2dp_is_ready())) {
2651 if (!a2dp_combo) {
2652 check_a2dp_restore_l(adev, out, false);
2653 } else {
2654 audio_devices_t dev = out->devices;
2655 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2656 select_devices(adev, out->usecase);
2657 out->devices = dev;
2658 }
2659 } else {
2660 select_devices(adev, out->usecase);
2661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002662
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002663 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2664 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07002665
2666 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2667 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2668 ALOGE("%s: pcm stream not ready", __func__);
2669 goto error_open;
2670 }
2671 ret = pcm_start(out->pcm);
2672 if (ret < 0) {
2673 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2674 goto error_open;
2675 }
2676 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002677 unsigned int flags = PCM_OUT;
2678 unsigned int pcm_open_retry_count = 0;
2679 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2680 flags |= PCM_MMAP | PCM_NOIRQ;
2681 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002682 } else if (out->realtime) {
2683 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002684 } else
2685 flags |= PCM_MONOTONIC;
2686
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002687 if ((adev->vr_audio_mode_enabled) &&
2688 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2689 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2690 "PCM_Dev %d Topology", out->pcm_device_id);
2691 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2692 if (!ctl) {
2693 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2694 __func__, mixer_ctl_name);
2695 } else {
2696 //if success use ULLPP
2697 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2698 __func__, mixer_ctl_name, out->pcm_device_id);
2699 //There is a still a possibility that some sessions
2700 // that request for FAST|RAW when 3D audio is active
2701 //can go through ULLPP. Ideally we expects apps to
2702 //listen to audio focus and stop concurrent playback
2703 //Also, we will look for mode flag (voice_in_communication)
2704 //before enabling the realtime flag.
2705 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2706 }
2707 }
2708
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002709 while (1) {
2710 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2711 flags, &out->config);
2712 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2713 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2714 if (out->pcm != NULL) {
2715 pcm_close(out->pcm);
2716 out->pcm = NULL;
2717 }
2718 if (pcm_open_retry_count-- == 0) {
2719 ret = -EIO;
2720 goto error_open;
2721 }
2722 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2723 continue;
2724 }
2725 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002726 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002727
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002728 ALOGV("%s: pcm_prepare", __func__);
2729 if (pcm_is_ready(out->pcm)) {
2730 ret = pcm_prepare(out->pcm);
2731 if (ret < 0) {
2732 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2733 pcm_close(out->pcm);
2734 out->pcm = NULL;
2735 goto error_open;
2736 }
2737 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302738 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302739 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2740
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002741 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002742 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302743 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002744 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2745 adev->dsp_bit_width_enforce_mode,
2746 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002748 out->compr = compress_open(adev->snd_card,
2749 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002750 COMPRESS_IN, &out->compr_config);
2751 if (out->compr && !is_compress_ready(out->compr)) {
2752 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2753 compress_close(out->compr);
2754 out->compr = NULL;
2755 ret = -EIO;
2756 goto error_open;
2757 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302758 /* compress_open sends params of the track, so reset the flag here */
2759 out->is_compr_metadata_avail = false;
2760
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002761 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002762 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002763
Fred Oh3f43e742015-03-04 18:42:34 -08002764 /* Since small bufs uses blocking writes, a write will be blocked
2765 for the default max poll time (20s) in the event of an SSR.
2766 Reduce the poll time to observe and deal with SSR faster.
2767 */
Ashish Jain5106d362016-05-11 19:23:33 +05302768 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002769 compress_set_max_poll_wait(out->compr, 1000);
2770 }
2771
Manish Dewangan69426c82017-01-30 17:35:36 +05302772 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302773 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302774
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002775 audio_extn_dts_create_state_notifier_node(out->usecase);
2776 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2777 popcount(out->channel_mask),
2778 out->playback_started);
2779
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002780#ifdef DS1_DOLBY_DDP_ENABLED
2781 if (audio_extn_is_dolby_format(out->format))
2782 audio_extn_dolby_send_ddp_endp_params(adev);
2783#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302784 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2785 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002786 if (adev->visualizer_start_output != NULL)
2787 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2788 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302789 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002790 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002793
2794 if (ret == 0) {
2795 register_out_stream(out);
2796 if (out->realtime) {
2797 ret = pcm_start(out->pcm);
2798 if (ret < 0)
2799 goto error_open;
2800 }
2801 }
2802
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302803 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002804 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002805
Manish Dewangan21a850a2017-08-14 12:03:55 +05302806 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002807 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002808 if (ret < 0)
2809 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2810 }
2811
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002812 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002813error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302814 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002816error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302817 /*
2818 * sleep 50ms to allow sufficient time for kernel
2819 * drivers to recover incases like SSR.
2820 */
2821 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002822 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823}
2824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825static int check_input_parameters(uint32_t sample_rate,
2826 audio_format_t format,
2827 int channel_count)
2828{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002829 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302831 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2832 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2833 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002834 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302835 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002836
2837 switch (channel_count) {
2838 case 1:
2839 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302840 case 3:
2841 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002842 case 6:
2843 break;
2844 default:
2845 ret = -EINVAL;
2846 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847
2848 switch (sample_rate) {
2849 case 8000:
2850 case 11025:
2851 case 12000:
2852 case 16000:
2853 case 22050:
2854 case 24000:
2855 case 32000:
2856 case 44100:
2857 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302858 case 96000:
2859 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860 break;
2861 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002862 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 }
2864
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002865 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866}
2867
2868static size_t get_input_buffer_size(uint32_t sample_rate,
2869 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002870 int channel_count,
2871 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872{
2873 size_t size = 0;
2874
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002875 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2876 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002878 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002879 if (is_low_latency)
2880 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302881
2882 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002884 /* make sure the size is multiple of 32 bytes
2885 * At 48 kHz mono 16-bit PCM:
2886 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2887 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2888 */
2889 size += 0x1f;
2890 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002891
2892 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893}
2894
Ashish Jain058165c2016-09-28 23:18:48 +05302895static size_t get_output_period_size(uint32_t sample_rate,
2896 audio_format_t format,
2897 int channel_count,
2898 int duration /*in millisecs*/)
2899{
2900 size_t size = 0;
2901 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2902
2903 if ((duration == 0) || (sample_rate == 0) ||
2904 (bytes_per_sample == 0) || (channel_count == 0)) {
2905 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2906 bytes_per_sample, channel_count);
2907 return -EINVAL;
2908 }
2909
2910 size = (sample_rate *
2911 duration *
2912 bytes_per_sample *
2913 channel_count) / 1000;
2914 /*
2915 * To have same PCM samples for all channels, the buffer size requires to
2916 * be multiple of (number of channels * bytes per sample)
2917 * For writes to succeed, the buffer must be written at address which is multiple of 32
2918 */
2919 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2920
2921 return (size/(channel_count * bytes_per_sample));
2922}
2923
Ashish Jain5106d362016-05-11 19:23:33 +05302924static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2925{
2926 uint64_t actual_frames_rendered = 0;
2927 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2928
2929 /* This adjustment accounts for buffering after app processor.
2930 * It is based on estimated DSP latency per use case, rather than exact.
2931 */
2932 int64_t platform_latency = platform_render_latency(out->usecase) *
2933 out->sample_rate / 1000000LL;
2934
2935 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2936 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2937 * hence only estimate.
2938 */
2939 int64_t signed_frames = out->written - kernel_buffer_size;
2940
2941 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2942
2943 if (signed_frames > 0)
2944 actual_frames_rendered = signed_frames;
2945
2946 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2947 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2948 (long long int)out->written, (int)kernel_buffer_size,
2949 audio_bytes_per_sample(out->compr_config.codec->format),
2950 popcount(out->channel_mask));
2951
2952 return actual_frames_rendered;
2953}
2954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2956{
2957 struct stream_out *out = (struct stream_out *)stream;
2958
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002959 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960}
2961
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002962static int out_set_sample_rate(struct audio_stream *stream __unused,
2963 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964{
2965 return -ENOSYS;
2966}
2967
2968static size_t out_get_buffer_size(const struct audio_stream *stream)
2969{
2970 struct stream_out *out = (struct stream_out *)stream;
2971
Varun Balaraje49253e2017-07-06 19:48:56 +05302972 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05302973 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05302974 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302975 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2976 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2977 else
2978 return out->compr_config.fragment_size;
2979 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002980 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07002981 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
2982 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 +05302983 else if (is_offload_usecase(out->usecase) &&
2984 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302985 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002986
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002987 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002988 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989}
2990
2991static uint32_t out_get_channels(const struct audio_stream *stream)
2992{
2993 struct stream_out *out = (struct stream_out *)stream;
2994
2995 return out->channel_mask;
2996}
2997
2998static audio_format_t out_get_format(const struct audio_stream *stream)
2999{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 struct stream_out *out = (struct stream_out *)stream;
3001
3002 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003}
3004
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003005static int out_set_format(struct audio_stream *stream __unused,
3006 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007{
3008 return -ENOSYS;
3009}
3010
3011static int out_standby(struct audio_stream *stream)
3012{
3013 struct stream_out *out = (struct stream_out *)stream;
3014 struct audio_device *adev = out->dev;
kunleiza9d11682017-08-04 14:14:09 +08003015 struct audio_usecase *uc_info;
3016 struct listnode *node;
Haynes Mathew George16081042017-05-31 17:16:49 -07003017 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003018
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303019 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3020 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003022 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003024 if (adev->adm_deregister_stream)
3025 adev->adm_deregister_stream(adev->adm_data, out->handle);
3026
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003027 if (is_offload_usecase(out->usecase))
3028 stop_compressed_output_l(out);
3029
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003030 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003032 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3033 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303034 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003035 pthread_mutex_unlock(&adev->lock);
3036 pthread_mutex_unlock(&out->lock);
3037 ALOGD("VOIP output entered standby");
3038 return 0;
3039 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040 if (out->pcm) {
3041 pcm_close(out->pcm);
3042 out->pcm = NULL;
3043 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003044 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3045 do_stop = out->playback_started;
3046 out->playback_started = false;
3047 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003049 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303050 out->send_next_track_params = false;
3051 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003052 out->gapless_mdata.encoder_delay = 0;
3053 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054 if (out->compr != NULL) {
3055 compress_close(out->compr);
3056 out->compr = NULL;
3057 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003058 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003059 if (do_stop) {
3060 stop_output_stream(out);
3061 }
kunleiza9d11682017-08-04 14:14:09 +08003062 //restore output device for active usecase when current snd device and output device mismatch
3063 list_for_each(node, &adev->usecase_list) {
3064 uc_info = node_to_item(node, struct audio_usecase, list);
3065 if ((uc_info->type == PCM_PLAYBACK) &&
3066 (uc_info->out_snd_device != platform_get_output_snd_device(adev->platform, uc_info->stream.out)))
3067 select_devices(adev, uc_info->id);
3068 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003069 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 }
3071 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303072 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 return 0;
3074}
3075
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303076static int out_on_error(struct audio_stream *stream)
3077{
3078 struct stream_out *out = (struct stream_out *)stream;
3079 bool do_standby = false;
3080
3081 lock_output_stream(out);
3082 if (!out->standby) {
3083 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3084 stop_compressed_output_l(out);
3085 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
3086 } else
3087 do_standby = true;
3088 }
3089 pthread_mutex_unlock(&out->lock);
3090
3091 if (do_standby)
3092 return out_standby(&out->stream.common);
3093
3094 return 0;
3095}
3096
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303097/*
3098 *standby implementation without locks, assumes that the callee already
3099 *has taken adev and out lock.
3100 */
3101int out_standby_l(struct audio_stream *stream)
3102{
3103 struct stream_out *out = (struct stream_out *)stream;
3104 struct audio_device *adev = out->dev;
3105
3106 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3107 stream, out->usecase, use_case_table[out->usecase]);
3108
3109 if (!out->standby) {
3110 if (adev->adm_deregister_stream)
3111 adev->adm_deregister_stream(adev->adm_data, out->handle);
3112
3113 if (is_offload_usecase(out->usecase))
3114 stop_compressed_output_l(out);
3115
3116 out->standby = true;
3117 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3118 voice_extn_compress_voip_close_output_stream(stream);
3119 out->started = 0;
3120 ALOGD("VOIP output entered standby");
3121 return 0;
3122 } else if (!is_offload_usecase(out->usecase)) {
3123 if (out->pcm) {
3124 pcm_close(out->pcm);
3125 out->pcm = NULL;
3126 }
3127 } else {
3128 ALOGD("copl(%p):standby", out);
3129 out->send_next_track_params = false;
3130 out->is_compr_metadata_avail = false;
3131 out->gapless_mdata.encoder_delay = 0;
3132 out->gapless_mdata.encoder_padding = 0;
3133 if (out->compr != NULL) {
3134 compress_close(out->compr);
3135 out->compr = NULL;
3136 }
3137 }
3138 stop_output_stream(out);
3139 }
3140 ALOGD("%s: exit", __func__);
3141 return 0;
3142}
3143
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003144static int out_dump(const struct audio_stream *stream __unused,
3145 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146{
3147 return 0;
3148}
3149
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003150static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3151{
3152 int ret = 0;
3153 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003154
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003155 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003156 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003157 return -EINVAL;
3158 }
3159
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303160 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003161
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003162 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3163 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303164 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003165 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003166 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3167 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303168 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003169 }
3170
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003171 ALOGV("%s new encoder delay %u and padding %u", __func__,
3172 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3173
3174 return 0;
3175}
3176
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003177static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3178{
3179 return out == adev->primary_output || out == adev->voice_tx_output;
3180}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003181
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303182// note: this call is safe only if the stream_cb is
3183// removed first in close_output_stream (as is done now).
3184static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3185{
3186 if (!stream || !parms)
3187 return;
3188
3189 struct stream_out *out = (struct stream_out *)stream;
3190 struct audio_device *adev = out->dev;
3191
3192 card_status_t status;
3193 int card;
3194 if (parse_snd_card_status(parms, &card, &status) < 0)
3195 return;
3196
3197 pthread_mutex_lock(&adev->lock);
3198 bool valid_cb = (card == adev->snd_card);
3199 pthread_mutex_unlock(&adev->lock);
3200
3201 if (!valid_cb)
3202 return;
3203
3204 lock_output_stream(out);
3205 if (out->card_status != status)
3206 out->card_status = status;
3207 pthread_mutex_unlock(&out->lock);
3208
3209 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3210 use_case_table[out->usecase],
3211 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3212
3213 if (status == CARD_STATUS_OFFLINE)
3214 out_on_error(stream);
3215
3216 return;
3217}
3218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3220{
3221 struct stream_out *out = (struct stream_out *)stream;
3222 struct audio_device *adev = out->dev;
3223 struct str_parms *parms;
3224 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003225 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303226 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227
sangwoobc677242013-08-08 16:53:43 +09003228 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003229 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303231 if (!parms)
3232 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003233 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3234 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003236 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003237 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003239 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003240 * When HDMI cable is unplugged the music playback is paused and
3241 * the policy manager sends routing=0. But the audioflinger continues
3242 * to write data until standby time (3sec). As the HDMI core is
3243 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003244 * Avoid this by routing audio to speaker until standby.
3245 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003246 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3247 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303248 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003249 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3250 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003251 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303252 /*
3253 * When A2DP is disconnected the
3254 * music playback is paused and the policy manager sends routing=0
3255 * But the audioflingercontinues to write data until standby time
3256 * (3sec). As BT is turned off, the write gets blocked.
3257 * Avoid this by routing audio to speaker until standby.
3258 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003259 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303260 (val == AUDIO_DEVICE_NONE)) {
3261 val = AUDIO_DEVICE_OUT_SPEAKER;
3262 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303263 /* To avoid a2dp to sco overlapping / BT device improper state
3264 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303265 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303266 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3267 if (!audio_extn_a2dp_is_ready()) {
3268 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3269 //combo usecase just by pass a2dp
3270 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303271 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303272 } else {
3273 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3274 /* update device to a2dp and don't route as BT returned error
3275 * However it is still possible a2dp routing called because
3276 * of current active device disconnection (like wired headset)
3277 */
3278 out->devices = val;
3279 pthread_mutex_unlock(&out->lock);
3280 pthread_mutex_unlock(&adev->lock);
3281 goto error;
3282 }
3283 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303284 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003285 /*
3286 * select_devices() call below switches all the usecases on the same
3287 * backend to the new device. Refer to check_usecases_codec_backend() in
3288 * the select_devices(). But how do we undo this?
3289 *
3290 * For example, music playback is active on headset (deep-buffer usecase)
3291 * and if we go to ringtones and select a ringtone, low-latency usecase
3292 * will be started on headset+speaker. As we can't enable headset+speaker
3293 * and headset devices at the same time, select_devices() switches the music
3294 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3295 * So when the ringtone playback is completed, how do we undo the same?
3296 *
3297 * We are relying on the out_set_parameters() call on deep-buffer output,
3298 * once the ringtone playback is ended.
3299 * NOTE: We should not check if the current devices are same as new devices.
3300 * Because select_devices() must be called to switch back the music
3301 * playback to headset.
3302 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003303 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003304 audio_devices_t new_dev = val;
3305 bool same_dev = out->devices == new_dev;
3306 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003307
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003308 if (output_drives_call(adev, out)) {
3309 if(!voice_is_in_call(adev)) {
3310 if (adev->mode == AUDIO_MODE_IN_CALL) {
3311 adev->current_call_output = out;
3312 ret = voice_start_call(adev);
3313 }
3314 } else {
3315 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003316 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003317 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003318 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003319
3320 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003321 if (!same_dev) {
3322 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303323 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3324 adev->perf_lock_opts,
3325 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003326 if (adev->adm_on_routing_change)
3327 adev->adm_on_routing_change(adev->adm_data,
3328 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003329 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303330 if (!bypass_a2dp) {
3331 select_devices(adev, out->usecase);
3332 } else {
3333 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3334 select_devices(adev, out->usecase);
3335 out->devices = new_dev;
3336 }
Sudheer Papothi80266982016-08-16 02:36:18 +05303337 if (!same_dev)
3338 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303339 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3340 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003341 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303342 pthread_mutex_lock(&out->compr_mute_lock);
3343 out->a2dp_compress_mute = false;
3344 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3345 pthread_mutex_unlock(&out->compr_mute_lock);
3346 }
3347
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003348 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003349 }
3350
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003352 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003354
3355 if (out == adev->primary_output) {
3356 pthread_mutex_lock(&adev->lock);
3357 audio_extn_set_parameters(adev, parms);
3358 pthread_mutex_unlock(&adev->lock);
3359 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003360 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003361 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003362 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003363
3364 audio_extn_dts_create_state_notifier_node(out->usecase);
3365 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3366 popcount(out->channel_mask),
3367 out->playback_started);
3368
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003369 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003370 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003371
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303372 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3373 if (err >= 0) {
3374 strlcpy(out->profile, value, sizeof(out->profile));
3375 ALOGV("updating stream profile with value '%s'", out->profile);
3376 lock_output_stream(out);
3377 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3378 &adev->streams_output_cfg_list,
3379 out->devices, out->flags, out->format,
3380 out->sample_rate, out->bit_width,
3381 out->channel_mask, out->profile,
3382 &out->app_type_cfg);
3383 pthread_mutex_unlock(&out->lock);
3384 }
3385
Alexy Joseph98988832017-01-13 14:56:59 -08003386 //suspend, resume handling block
3387 if (out->dynamic_pm_qos_enabled) {
3388 //check suspend parameter only for low latency and if the property
3389 //is enabled
3390 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3391 ALOGI("%s: got suspend_playback %s", __func__, value);
3392 lock_output_stream(out);
3393 if (!strncmp(value, "false", 5)) {
3394 //suspend_playback=false is supposed to set QOS value back to 75%
3395 //the mixer control sent with value Enable will achieve that
3396 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3397 } else if (!strncmp (value, "true", 4)) {
3398 //suspend_playback=true is supposed to remove QOS value
3399 //resetting the mixer control will set the default value
3400 //for the mixer control which is Disable and this removes the QOS vote
3401 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3402 } else {
3403 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3404 " got %s", __func__, value);
3405 ret = -1;
3406 }
3407
3408 if (ret != 0) {
3409 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3410 __func__, out->pm_qos_mixer_path, ret);
3411 }
3412
3413 pthread_mutex_unlock(&out->lock);
3414 }
3415 }
3416 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303418error:
Eric Laurent994a6932013-07-17 11:51:42 -07003419 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 return ret;
3421}
3422
3423static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3424{
3425 struct stream_out *out = (struct stream_out *)stream;
3426 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003427 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 char value[256];
3429 struct str_parms *reply = str_parms_create();
3430 size_t i, j;
3431 int ret;
3432 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003433
3434 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003435 if (reply) {
3436 str_parms_destroy(reply);
3437 }
3438 if (query) {
3439 str_parms_destroy(query);
3440 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003441 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3442 return NULL;
3443 }
3444
Eric Laurent994a6932013-07-17 11:51:42 -07003445 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3447 if (ret >= 0) {
3448 value[0] = '\0';
3449 i = 0;
3450 while (out->supported_channel_masks[i] != 0) {
3451 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3452 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3453 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003454 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003456 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457 first = false;
3458 break;
3459 }
3460 }
3461 i++;
3462 }
3463 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3464 str = str_parms_to_str(reply);
3465 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003466 voice_extn_out_get_parameters(out, query, reply);
3467 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003469
Alexy Joseph62142aa2015-11-16 15:10:34 -08003470
3471 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3472 if (ret >= 0) {
3473 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303474 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3475 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003476 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303477 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003478 } else {
3479 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303480 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003481 }
3482 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003483 if (str)
3484 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003485 str = str_parms_to_str(reply);
3486 }
3487
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003488 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3489 if (ret >= 0) {
3490 value[0] = '\0';
3491 i = 0;
3492 first = true;
3493 while (out->supported_formats[i] != 0) {
3494 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3495 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3496 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003497 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003498 }
3499 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3500 first = false;
3501 break;
3502 }
3503 }
3504 i++;
3505 }
3506 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003507 if (str)
3508 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003509 str = str_parms_to_str(reply);
3510 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003511
3512 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3513 if (ret >= 0) {
3514 value[0] = '\0';
3515 i = 0;
3516 first = true;
3517 while (out->supported_sample_rates[i] != 0) {
3518 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3519 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3520 if (!first) {
3521 strlcat(value, "|", sizeof(value));
3522 }
3523 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3524 first = false;
3525 break;
3526 }
3527 }
3528 i++;
3529 }
3530 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3531 if (str)
3532 free(str);
3533 str = str_parms_to_str(reply);
3534 }
3535
Alexy Joseph98988832017-01-13 14:56:59 -08003536 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
3537 //only low latency track supports suspend_resume
3538 str_parms_add_int(reply, "supports_hw_suspend",
3539 (out->dynamic_pm_qos_enabled));
3540 if (str)
3541 free(str);
3542 str = str_parms_to_str(reply);
3543 }
3544
3545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 str_parms_destroy(query);
3547 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003548 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 return str;
3550}
3551
3552static uint32_t out_get_latency(const struct audio_stream_out *stream)
3553{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003554 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003556 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557
Alexy Josephaa54c872014-12-03 02:46:47 -08003558 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303559 lock_output_stream(out);
3560 latency = audio_extn_utils_compress_get_dsp_latency(out);
3561 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07003562 } else if ((out->realtime) ||
3563 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003564 // since the buffer won't be filled up faster than realtime,
3565 // return a smaller number
3566 if (out->config.rate)
3567 period_ms = (out->af_period_multiplier * out->config.period_size *
3568 1000) / (out->config.rate);
3569 else
3570 period_ms = 0;
3571 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003572 } else {
3573 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003574 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003575 }
3576
yidongh0515e042017-07-06 15:00:34 +08003577 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003578 latency += audio_extn_a2dp_get_encoder_latency();
3579
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303580 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003581 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582}
3583
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303584static float AmpToDb(float amplification)
3585{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303586 float db = DSD_VOLUME_MIN_DB;
3587 if (amplification > 0) {
3588 db = 20 * log10(amplification);
3589 if(db < DSD_VOLUME_MIN_DB)
3590 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303591 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303592 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303593}
3594
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303595static int out_set_compr_volume(struct audio_stream_out *stream, float left,
3596 float right)
3597{
3598 struct stream_out *out = (struct stream_out *)stream;
3599 int volume[2];
3600 char mixer_ctl_name[128];
3601 struct audio_device *adev = out->dev;
3602 struct mixer_ctl *ctl;
3603 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3604 PCM_PLAYBACK);
3605
3606 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3607 "Compress Playback %d Volume", pcm_device_id);
3608 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3609 if (!ctl) {
3610 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3611 __func__, mixer_ctl_name);
3612 return -EINVAL;
3613 }
3614 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
3615 __func__, mixer_ctl_name, left, right);
3616 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3617 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3618 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3619
3620 return 0;
3621}
3622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623static int out_set_volume(struct audio_stream_out *stream, float left,
3624 float right)
3625{
Eric Laurenta9024de2013-04-04 09:19:12 -07003626 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003627 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303628 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003629
Eric Laurenta9024de2013-04-04 09:19:12 -07003630 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3631 /* only take left channel into account: the API is for stereo anyway */
3632 out->muted = (left == 0.0f);
3633 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003634 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303635 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003636 /*
3637 * Set mute or umute on HDMI passthrough stream.
3638 * Only take left channel into account.
3639 * Mute is 0 and unmute 1
3640 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303641 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303642 } else if (out->format == AUDIO_FORMAT_DSD){
3643 char mixer_ctl_name[128] = "DSD Volume";
3644 struct audio_device *adev = out->dev;
3645 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3646
3647 if (!ctl) {
3648 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3649 __func__, mixer_ctl_name);
3650 return -EINVAL;
3651 }
3652 volume[0] = (int)(AmpToDb(left));
3653 volume[1] = (int)(AmpToDb(right));
3654 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3655 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003656 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303657 pthread_mutex_lock(&out->compr_mute_lock);
3658 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3659 if (!out->a2dp_compress_mute)
3660 ret = out_set_compr_volume(stream, left, right);
3661 out->volume_l = left;
3662 out->volume_r = right;
3663 pthread_mutex_unlock(&out->compr_mute_lock);
3664 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003665 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003666 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3667 char mixer_ctl_name[] = "App Type Gain";
3668 struct audio_device *adev = out->dev;
3669 struct mixer_ctl *ctl;
3670 uint32_t set_values[4];
3671
3672 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3673 if (!ctl) {
3674 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3675 __func__, mixer_ctl_name);
3676 return -EINVAL;
3677 }
3678
3679 set_values[0] = 0; //0: Rx Session 1:Tx Session
3680 set_values[1] = out->app_type_cfg.app_type;
3681 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3682 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3683
3684 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
3685 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003686 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 return -ENOSYS;
3689}
3690
Zhou Songc9672822017-08-16 16:01:39 +08003691static void update_frames_written(struct stream_out *out, size_t bytes)
3692{
3693 size_t bpf = 0;
3694
3695 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3696 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3697 bpf = 1;
3698 else if (!is_offload_usecase(out->usecase))
3699 bpf = audio_bytes_per_sample(out->format) *
3700 audio_channel_count_from_out_mask(out->channel_mask);
3701 if (bpf != 0)
3702 out->written += bytes / bpf;
3703}
3704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3706 size_t bytes)
3707{
3708 struct stream_out *out = (struct stream_out *)stream;
3709 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003710 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303711 int channels = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003713 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303714
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303715 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003716
Dhananjay Kumarac341582017-02-23 23:42:25 +05303717 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303718 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303719 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3720 pthread_mutex_unlock(&out->lock);
3721 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303722 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05303723 ALOGD(" %s: sound card is not active/SSR state", __func__);
3724 ret= -EIO;
3725 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303726 }
3727 }
3728
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303729 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303730 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303731 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303732 goto exit;
3733 }
3734
Haynes Mathew George16081042017-05-31 17:16:49 -07003735 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3736 ret = -EINVAL;
3737 goto exit;
3738 }
3739
Manish Dewangan37864bc2017-06-09 12:28:37 +05303740 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303741 channels = platform_edid_get_max_channels(out->dev->platform);
Manish Dewangan672001f2017-08-16 13:44:07 +05303742 if (audio_extn_passthru_is_enabled() &&
3743 !out->is_iec61937_info_available &&
3744 audio_extn_passthru_is_passthrough_stream(out)) {
Manish Dewangan37864bc2017-06-09 12:28:37 +05303745 audio_extn_passthru_update_stream_configuration(adev, out,
3746 buffer, bytes);
3747 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05303748
3749 if((out->format == AUDIO_FORMAT_DTS) ||
3750 (out->format == AUDIO_FORMAT_DTS_HD)) {
3751 ret = audio_extn_passthru_update_dts_stream_configuration(out,
3752 buffer, bytes);
3753 if (ret) {
3754 if (ret != -ENOSYS) {
3755 out->is_iec61937_info_available = false;
3756 ALOGD("iec61937 transmission info not yet updated retry");
3757 }
3758 } else {
3759 /* if stream has started and after that there is
3760 * stream config change (iec transmission config)
3761 * then trigger select_device to update backend configuration.
3762 */
3763 out->stream_config_changed = true;
3764 pthread_mutex_lock(&adev->lock);
3765 select_devices(adev, out->usecase);
3766 pthread_mutex_unlock(&adev->lock);
3767 out->stream_config_changed = false;
3768 out->is_iec61937_info_available = true;
3769 }
3770 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303771
Garmond Leung317cbf12017-09-13 16:20:50 -07003772 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303773 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
3774 (out->is_iec61937_info_available == true)) {
3775 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
3776 ret = -EINVAL;
3777 goto exit;
3778 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05303779 }
3780 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303781
3782 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3783 (audio_extn_a2dp_is_suspended())) {
3784 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
3785 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303786 ret = -EIO;
3787 goto exit;
3788 }
3789 }
3790 }
3791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003793 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003794 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003795 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3796 ret = voice_extn_compress_voip_start_output_stream(out);
3797 else
3798 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003799 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003800 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003802 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 goto exit;
3804 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303805 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003806 if (last_known_cal_step != -1) {
3807 ALOGD("%s: retry previous failed cal level set", __func__);
3808 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05303809 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003810 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812
Ashish Jain81eb2a82015-05-13 10:52:34 +05303813 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003814 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303815 adev->is_channel_status_set = true;
3816 }
3817
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003818 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003819 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003820 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003821 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003822 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3823 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303824 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3825 ALOGD("copl(%p):send next track params in gapless", out);
3826 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3827 out->send_next_track_params = false;
3828 out->is_compr_metadata_avail = false;
3829 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003830 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303831 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303832 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003833
Ashish Jain83a6cc22016-06-28 14:34:17 +05303834 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303835 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303836 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303837 pthread_mutex_unlock(&out->lock);
3838 return -EINVAL;
3839 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303840 audio_format_t dst_format = out->hal_op_format;
3841 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303842
3843 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3844 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3845
Ashish Jain83a6cc22016-06-28 14:34:17 +05303846 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303847 dst_format,
3848 buffer,
3849 src_format,
3850 frames);
3851
Ashish Jain83a6cc22016-06-28 14:34:17 +05303852 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303853 bytes_to_write);
3854
3855 /*Convert written bytes in audio flinger format*/
3856 if (ret > 0)
3857 ret = ((ret * format_to_bitwidth_table[out->format]) /
3858 format_to_bitwidth_table[dst_format]);
3859 }
3860 } else
3861 ret = compress_write(out->compr, buffer, bytes);
3862
Zhou Songc9672822017-08-16 16:01:39 +08003863 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
3864 update_frames_written(out, bytes);
3865
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303866 if (ret < 0)
3867 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303868 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303869 /*msg to cb thread only if non blocking write is enabled*/
3870 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303871 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003872 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303873 } else if (-ENETRESET == ret) {
3874 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303875 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303876 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05303877 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05303878 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003879 }
Ashish Jain5106d362016-05-11 19:23:33 +05303880
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303881 /* Call compr start only when non-zero bytes of data is there to be rendered */
3882 if (!out->playback_started && ret > 0) {
3883 int status = compress_start(out->compr);
3884 if (status < 0) {
3885 ret = status;
3886 ALOGE("%s: compr start failed with err %d", __func__, errno);
3887 goto exit;
3888 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003889 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003890 out->playback_started = 1;
3891 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003892
3893 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3894 popcount(out->channel_mask),
3895 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003896 }
3897 pthread_mutex_unlock(&out->lock);
3898 return ret;
3899 } else {
3900 if (out->pcm) {
3901 if (out->muted)
3902 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003903
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303904 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003905
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003906 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003907
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003908 if (out->config.rate)
3909 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3910 out->config.rate;
3911
3912 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3913
3914 request_out_focus(out, ns);
3915
3916 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003917 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003918 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303919 out->convert_buffer != NULL) {
3920
3921 memcpy_by_audio_format(out->convert_buffer,
3922 out->hal_op_format,
3923 buffer,
3924 out->hal_ip_format,
3925 out->config.period_size * out->config.channels);
3926
3927 ret = pcm_write(out->pcm, out->convert_buffer,
3928 (out->config.period_size *
3929 out->config.channels *
3930 format_to_bitwidth_table[out->hal_op_format]));
3931 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303932 /*
3933 * To avoid underrun in DSP when the application is not pumping
3934 * data at required rate, check for the no. of bytes and ignore
3935 * pcm_write if it is less than actual buffer size.
3936 * It is a work around to a change in compress VOIP driver.
3937 */
3938 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3939 bytes < (out->config.period_size * out->config.channels *
3940 audio_bytes_per_sample(out->format))) {
3941 size_t voip_buf_size =
3942 out->config.period_size * out->config.channels *
3943 audio_bytes_per_sample(out->format);
3944 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3945 __func__, bytes, voip_buf_size);
3946 usleep(((uint64_t)voip_buf_size - bytes) *
3947 1000000 / audio_stream_out_frame_size(stream) /
3948 out_get_sample_rate(&out->stream.common));
3949 ret = 0;
3950 } else
3951 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303952 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003953
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003954 release_out_focus(out);
3955
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303956 if (ret < 0)
3957 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08003958 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303959 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003960 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 }
3962
3963exit:
Zhou Songc9672822017-08-16 16:01:39 +08003964 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303965 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303966 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303967 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003968 pthread_mutex_unlock(&out->lock);
3969
3970 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003971 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003972 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303973 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303974 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303975 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303976 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303977 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303978 out->standby = true;
3979 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303980 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303981 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3982 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3983 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07003984
3985 if (audio_extn_passthru_is_passthrough_stream(out)) {
Garmond Leung317cbf12017-09-13 16:20:50 -07003986 ALOGE("%s: write error, ret = %ld", __func__, ret);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07003987 return ret;
3988 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003989 }
3990 return bytes;
3991}
3992
3993static int out_get_render_position(const struct audio_stream_out *stream,
3994 uint32_t *dsp_frames)
3995{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003996 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08003997
3998 if (dsp_frames == NULL)
3999 return -EINVAL;
4000
4001 *dsp_frames = 0;
4002 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004003 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304004
4005 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4006 * this operation and adev_close_output_stream(where out gets reset).
4007 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304008 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304009 *dsp_frames = get_actual_pcm_frames_rendered(out);
4010 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
4011 return 0;
4012 }
4013
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004014 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304015 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304016 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004017 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304018 if (ret < 0)
4019 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004020 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304021 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004022 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304023 if (-ENETRESET == ret) {
4024 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304025 out->card_status = CARD_STATUS_OFFLINE;
4026 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304027 } else if(ret < 0) {
4028 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304029 ret = -EINVAL;
4030 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304031 /*
4032 * Handle corner case where compress session is closed during SSR
4033 * and timestamp is queried
4034 */
4035 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304036 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304037 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304038 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05304039 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304040 pthread_mutex_unlock(&out->lock);
4041 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004042 } else if (audio_is_linear_pcm(out->format)) {
4043 *dsp_frames = out->written;
4044 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004045 } else
4046 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004047}
4048
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004049static int out_add_audio_effect(const struct audio_stream *stream __unused,
4050 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051{
4052 return 0;
4053}
4054
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004055static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4056 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057{
4058 return 0;
4059}
4060
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004061static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4062 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004063{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304064 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065}
4066
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004067static int out_get_presentation_position(const struct audio_stream_out *stream,
4068 uint64_t *frames, struct timespec *timestamp)
4069{
4070 struct stream_out *out = (struct stream_out *)stream;
4071 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07004072 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004073
Ashish Jain5106d362016-05-11 19:23:33 +05304074 /* below piece of code is not guarded against any lock because audioFliner serializes
4075 * this operation and adev_close_output_stream( where out gets reset).
4076 */
4077 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304078 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304079 *frames = get_actual_pcm_frames_rendered(out);
4080 /* this is the best we can do */
4081 clock_gettime(CLOCK_MONOTONIC, timestamp);
4082 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4083 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4084 return 0;
4085 }
4086
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004087 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004088
Ashish Jain5106d362016-05-11 19:23:33 +05304089 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4090 ret = compress_get_tstamp(out->compr, &dsp_frames,
4091 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004092 // Adjustment accounts for A2dp encoder latency with offload usecases
4093 // Note: Encoder latency is returned in ms.
4094 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4095 unsigned long offset =
4096 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4097 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4098 }
Ashish Jain5106d362016-05-11 19:23:33 +05304099 ALOGVV("%s rendered frames %ld sample_rate %d",
4100 __func__, dsp_frames, out->sample_rate);
4101 *frames = dsp_frames;
4102 if (ret < 0)
4103 ret = -errno;
4104 if (-ENETRESET == ret) {
4105 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304106 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304107 ret = -EINVAL;
4108 } else
4109 ret = 0;
4110 /* this is the best we can do */
4111 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004112 } else {
4113 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004114 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07004115 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4116 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07004117 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004118 // This adjustment accounts for buffering after app processor.
4119 // It is based on estimated DSP latency per use case, rather than exact.
4120 signed_frames -=
4121 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
4122
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004123 // Adjustment accounts for A2dp encoder latency with non offload usecases
4124 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4125 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4126 signed_frames -=
4127 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4128 }
4129
Eric Laurent949a0892013-09-20 09:20:13 -07004130 // It would be unusual for this value to be negative, but check just in case ...
4131 if (signed_frames >= 0) {
4132 *frames = signed_frames;
4133 ret = 0;
4134 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004135 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304136 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304137 *frames = out->written;
4138 clock_gettime(CLOCK_MONOTONIC, timestamp);
4139 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004140 }
4141 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004142 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004143 return ret;
4144}
4145
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004146static int out_set_callback(struct audio_stream_out *stream,
4147 stream_callback_t callback, void *cookie)
4148{
4149 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004150 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004151
4152 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004153 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004154 out->client_callback = callback;
4155 out->client_cookie = cookie;
4156 if (out->adsp_hdlr_stream_handle) {
4157 ret = audio_extn_adsp_hdlr_stream_set_callback(
4158 out->adsp_hdlr_stream_handle,
4159 callback,
4160 cookie);
4161 if (ret)
4162 ALOGW("%s:adsp hdlr callback registration failed %d",
4163 __func__, ret);
4164 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004165 pthread_mutex_unlock(&out->lock);
4166 return 0;
4167}
4168
4169static int out_pause(struct audio_stream_out* stream)
4170{
4171 struct stream_out *out = (struct stream_out *)stream;
4172 int status = -ENOSYS;
4173 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004174 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004175 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004176 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004177 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304178 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304179 status = compress_pause(out->compr);
4180
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004181 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004182
Mingming Yin21854652016-04-13 11:54:02 -07004183 if (audio_extn_passthru_is_active()) {
4184 ALOGV("offload use case, pause passthru");
4185 audio_extn_passthru_on_pause(out);
4186 }
4187
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304188 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004189 audio_extn_dts_notify_playback_state(out->usecase, 0,
4190 out->sample_rate, popcount(out->channel_mask),
4191 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004192 }
4193 pthread_mutex_unlock(&out->lock);
4194 }
4195 return status;
4196}
4197
4198static int out_resume(struct audio_stream_out* stream)
4199{
4200 struct stream_out *out = (struct stream_out *)stream;
4201 int status = -ENOSYS;
4202 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004203 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004204 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004205 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004206 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004207 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304208 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304209 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004210 }
4211 if (!status) {
4212 out->offload_state = OFFLOAD_STATE_PLAYING;
4213 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304214 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004215 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4216 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004217 }
4218 pthread_mutex_unlock(&out->lock);
4219 }
4220 return status;
4221}
4222
4223static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4224{
4225 struct stream_out *out = (struct stream_out *)stream;
4226 int status = -ENOSYS;
4227 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004228 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004229 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004230 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4231 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4232 else
4233 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4234 pthread_mutex_unlock(&out->lock);
4235 }
4236 return status;
4237}
4238
4239static int out_flush(struct audio_stream_out* stream)
4240{
4241 struct stream_out *out = (struct stream_out *)stream;
4242 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004243 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004244 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004245 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004246 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4247 stop_compressed_output_l(out);
4248 out->written = 0;
4249 } else {
4250 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4251 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004252 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004253 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004254 return 0;
4255 }
4256 return -ENOSYS;
4257}
4258
Haynes Mathew George16081042017-05-31 17:16:49 -07004259static int out_stop(const struct audio_stream_out* stream)
4260{
4261 struct stream_out *out = (struct stream_out *)stream;
4262 struct audio_device *adev = out->dev;
4263 int ret = -ENOSYS;
4264
4265 ALOGV("%s", __func__);
4266 pthread_mutex_lock(&adev->lock);
4267 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4268 out->playback_started && out->pcm != NULL) {
4269 pcm_stop(out->pcm);
4270 ret = stop_output_stream(out);
4271 out->playback_started = false;
4272 }
4273 pthread_mutex_unlock(&adev->lock);
4274 return ret;
4275}
4276
4277static int out_start(const struct audio_stream_out* stream)
4278{
4279 struct stream_out *out = (struct stream_out *)stream;
4280 struct audio_device *adev = out->dev;
4281 int ret = -ENOSYS;
4282
4283 ALOGV("%s", __func__);
4284 pthread_mutex_lock(&adev->lock);
4285 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4286 !out->playback_started && out->pcm != NULL) {
4287 ret = start_output_stream(out);
4288 if (ret == 0) {
4289 out->playback_started = true;
4290 }
4291 }
4292 pthread_mutex_unlock(&adev->lock);
4293 return ret;
4294}
4295
4296/*
4297 * Modify config->period_count based on min_size_frames
4298 */
4299static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4300{
4301 int periodCountRequested = (min_size_frames + config->period_size - 1)
4302 / config->period_size;
4303 int periodCount = MMAP_PERIOD_COUNT_MIN;
4304
4305 ALOGV("%s original config.period_size = %d config.period_count = %d",
4306 __func__, config->period_size, config->period_count);
4307
4308 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4309 periodCount *= 2;
4310 }
4311 config->period_count = periodCount;
4312
4313 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4314}
4315
4316static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4317 int32_t min_size_frames,
4318 struct audio_mmap_buffer_info *info)
4319{
4320 struct stream_out *out = (struct stream_out *)stream;
4321 struct audio_device *adev = out->dev;
4322 int ret = 0;
4323 unsigned int offset1;
4324 unsigned int frames1;
4325 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004326 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004327
4328 ALOGV("%s", __func__);
4329 pthread_mutex_lock(&adev->lock);
4330
4331 if (info == NULL || min_size_frames == 0) {
4332 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4333 ret = -EINVAL;
4334 goto exit;
4335 }
4336 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4337 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4338 ret = -ENOSYS;
4339 goto exit;
4340 }
4341 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4342 if (out->pcm_device_id < 0) {
4343 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4344 __func__, out->pcm_device_id, out->usecase);
4345 ret = -EINVAL;
4346 goto exit;
4347 }
4348
4349 adjust_mmap_period_count(&out->config, min_size_frames);
4350
4351 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4352 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4353 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4354 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4355 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4356 step = "open";
4357 ret = -ENODEV;
4358 goto exit;
4359 }
4360 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4361 if (ret < 0) {
4362 step = "begin";
4363 goto exit;
4364 }
4365 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4366 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004367 ret = platform_get_mmap_data_fd(adev->platform,
4368 out->pcm_device_id, 0 /*playback*/,
4369 &info->shared_memory_fd,
4370 &mmap_size);
4371 if (ret < 0) {
4372 step = "get_mmap_fd";
4373 goto exit;
4374 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004375 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004376 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07004377
4378 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4379 if (ret < 0) {
4380 step = "commit";
4381 goto exit;
4382 }
4383
4384 out->standby = false;
4385 ret = 0;
4386
4387 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4388 __func__, info->shared_memory_address, info->buffer_size_frames);
4389
4390exit:
4391 if (ret != 0) {
4392 if (out->pcm == NULL) {
4393 ALOGE("%s: %s - %d", __func__, step, ret);
4394 } else {
4395 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4396 pcm_close(out->pcm);
4397 out->pcm = NULL;
4398 }
4399 }
4400 pthread_mutex_unlock(&adev->lock);
4401 return ret;
4402}
4403
4404static int out_get_mmap_position(const struct audio_stream_out *stream,
4405 struct audio_mmap_position *position)
4406{
4407 struct stream_out *out = (struct stream_out *)stream;
4408 ALOGVV("%s", __func__);
4409 if (position == NULL) {
4410 return -EINVAL;
4411 }
4412 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
4413 return -ENOSYS;
4414 }
4415 if (out->pcm == NULL) {
4416 return -ENOSYS;
4417 }
4418
4419 struct timespec ts = { 0, 0 };
4420 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4421 if (ret < 0) {
4422 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4423 return ret;
4424 }
4425 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4426 return 0;
4427}
4428
4429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430/** audio_stream_in implementation **/
4431static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4432{
4433 struct stream_in *in = (struct stream_in *)stream;
4434
4435 return in->config.rate;
4436}
4437
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004438static int in_set_sample_rate(struct audio_stream *stream __unused,
4439 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004440{
4441 return -ENOSYS;
4442}
4443
4444static size_t in_get_buffer_size(const struct audio_stream *stream)
4445{
4446 struct stream_in *in = (struct stream_in *)stream;
4447
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004448 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4449 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004450 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4451 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 -07004452 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4453 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304454 else if(audio_extn_cin_attached_usecase(in->usecase))
4455 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004456
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004457 return in->config.period_size * in->af_period_multiplier *
4458 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004459}
4460
4461static uint32_t in_get_channels(const struct audio_stream *stream)
4462{
4463 struct stream_in *in = (struct stream_in *)stream;
4464
4465 return in->channel_mask;
4466}
4467
4468static audio_format_t in_get_format(const struct audio_stream *stream)
4469{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004470 struct stream_in *in = (struct stream_in *)stream;
4471
4472 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004473}
4474
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004475static int in_set_format(struct audio_stream *stream __unused,
4476 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477{
4478 return -ENOSYS;
4479}
4480
4481static int in_standby(struct audio_stream *stream)
4482{
4483 struct stream_in *in = (struct stream_in *)stream;
4484 struct audio_device *adev = in->dev;
4485 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304486 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4487 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004488 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304489
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004490 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004491 if (!in->standby && in->is_st_session) {
4492 ALOGD("%s: sound trigger pcm stop lab", __func__);
4493 audio_extn_sound_trigger_stop_lab(in);
4494 in->standby = 1;
4495 }
4496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004497 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004498 if (adev->adm_deregister_stream)
4499 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4500
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004501 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004502 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004503 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08004504 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08004505 voice_extn_compress_voip_close_input_stream(stream);
4506 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07004507 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4508 do_stop = in->capture_started;
4509 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08004510 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304511 if (audio_extn_cin_attached_usecase(in->usecase))
4512 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08004513 }
4514
4515 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08004516 if (in->pcm) {
4517 pcm_close(in->pcm);
4518 in->pcm = NULL;
4519 }
4520 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004521 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004522 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523 }
4524 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004525 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526 return status;
4527}
4528
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004529static int in_dump(const struct audio_stream *stream __unused,
4530 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531{
4532 return 0;
4533}
4534
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304535static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4536{
4537 if (!stream || !parms)
4538 return;
4539
4540 struct stream_in *in = (struct stream_in *)stream;
4541 struct audio_device *adev = in->dev;
4542
4543 card_status_t status;
4544 int card;
4545 if (parse_snd_card_status(parms, &card, &status) < 0)
4546 return;
4547
4548 pthread_mutex_lock(&adev->lock);
4549 bool valid_cb = (card == adev->snd_card);
4550 pthread_mutex_unlock(&adev->lock);
4551
4552 if (!valid_cb)
4553 return;
4554
4555 lock_input_stream(in);
4556 if (in->card_status != status)
4557 in->card_status = status;
4558 pthread_mutex_unlock(&in->lock);
4559
4560 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4561 use_case_table[in->usecase],
4562 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4563
4564 // a better solution would be to report error back to AF and let
4565 // it put the stream to standby
4566 if (status == CARD_STATUS_OFFLINE)
4567 in_standby(&in->stream.common);
4568
4569 return;
4570}
4571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4573{
4574 struct stream_in *in = (struct stream_in *)stream;
4575 struct audio_device *adev = in->dev;
4576 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004578 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304580 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004581 parms = str_parms_create_str(kvpairs);
4582
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304583 if (!parms)
4584 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004585 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004586 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004587
4588 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4589 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004590 val = atoi(value);
4591 /* no audio source uses val == 0 */
4592 if ((in->source != val) && (val != 0)) {
4593 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004594 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4595 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4596 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004597 (in->config.rate == 8000 || in->config.rate == 16000 ||
4598 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004599 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004600 err = voice_extn_compress_voip_open_input_stream(in);
4601 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004602 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004603 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004604 }
4605 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606 }
4607 }
4608
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004609 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4610 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004611 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004612 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613 in->device = val;
4614 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004615 if (!in->standby && !in->is_st_session) {
4616 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004617 if (adev->adm_on_routing_change)
4618 adev->adm_on_routing_change(adev->adm_data,
4619 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004620 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004621 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004622 }
4623 }
4624
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304625 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4626 if (err >= 0) {
4627 strlcpy(in->profile, value, sizeof(in->profile));
4628 ALOGV("updating stream profile with value '%s'", in->profile);
4629 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4630 &adev->streams_input_cfg_list,
4631 in->device, in->flags, in->format,
4632 in->sample_rate, in->bit_width,
4633 in->profile, &in->app_type_cfg);
4634 }
4635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004637 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638
4639 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304640error:
Eric Laurent994a6932013-07-17 11:51:42 -07004641 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642 return ret;
4643}
4644
4645static char* in_get_parameters(const struct audio_stream *stream,
4646 const char *keys)
4647{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004648 struct stream_in *in = (struct stream_in *)stream;
4649 struct str_parms *query = str_parms_create_str(keys);
4650 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004651 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004652
4653 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004654 if (reply) {
4655 str_parms_destroy(reply);
4656 }
4657 if (query) {
4658 str_parms_destroy(query);
4659 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004660 ALOGE("in_get_parameters: failed to create query or reply");
4661 return NULL;
4662 }
4663
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004664 ALOGV("%s: enter: keys - %s", __func__, keys);
4665
4666 voice_extn_in_get_parameters(in, query, reply);
4667
4668 str = str_parms_to_str(reply);
4669 str_parms_destroy(query);
4670 str_parms_destroy(reply);
4671
4672 ALOGV("%s: exit: returns - %s", __func__, str);
4673 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674}
4675
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004676static int in_set_gain(struct audio_stream_in *stream __unused,
4677 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678{
4679 return 0;
4680}
4681
4682static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4683 size_t bytes)
4684{
4685 struct stream_in *in = (struct stream_in *)stream;
4686 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304687 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304688 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004690 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304691
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004692 if (in->is_st_session) {
4693 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4694 /* Read from sound trigger HAL */
4695 audio_extn_sound_trigger_read(in, buffer, bytes);
4696 pthread_mutex_unlock(&in->lock);
4697 return bytes;
4698 }
4699
Haynes Mathew George16081042017-05-31 17:16:49 -07004700 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4701 ret = -ENOSYS;
4702 goto exit;
4703 }
4704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004705 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004706 pthread_mutex_lock(&adev->lock);
4707 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4708 ret = voice_extn_compress_voip_start_input_stream(in);
4709 else
4710 ret = start_input_stream(in);
4711 pthread_mutex_unlock(&adev->lock);
4712 if (ret != 0) {
4713 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714 }
4715 in->standby = 0;
4716 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004717
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004718 // what's the duration requested by the client?
4719 long ns = 0;
4720
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304721 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004722 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4723 in->config.rate;
4724
4725 request_in_focus(in, ns);
4726 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004727
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304728 if (audio_extn_cin_attached_usecase(in->usecase)) {
4729 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4730 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304731 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004732 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304733 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004734 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004735 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004736 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304737 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004738 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304739 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4740 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4741 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4742 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304743 ret = -EINVAL;
4744 goto exit;
4745 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304746 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304747 ret = -errno;
4748 }
4749 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304750 /* bytes read is always set to bytes for non compress usecases */
4751 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004752 }
4753
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004754 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004756 /*
4757 * Instead of writing zeroes here, we could trust the hardware
4758 * to always provide zeroes when muted.
4759 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304760 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4761 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004762 memset(buffer, 0, bytes);
4763
4764exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004765 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304766 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004767 pthread_mutex_unlock(&in->lock);
4768
4769 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304770 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304771 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304772 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304773 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304774 in->standby = true;
4775 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304776 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4777 bytes_read = bytes;
4778 memset(buffer, 0, bytes);
4779 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004780 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004781 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304782 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304783 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304785 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004786}
4787
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004788static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004789{
4790 return 0;
4791}
4792
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004793static int add_remove_audio_effect(const struct audio_stream *stream,
4794 effect_handle_t effect,
4795 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004797 struct stream_in *in = (struct stream_in *)stream;
4798 int status = 0;
4799 effect_descriptor_t desc;
4800
4801 status = (*effect)->get_descriptor(effect, &desc);
4802 if (status != 0)
4803 return status;
4804
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004805 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004806 pthread_mutex_lock(&in->dev->lock);
4807 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4808 in->enable_aec != enable &&
4809 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4810 in->enable_aec = enable;
4811 if (!in->standby)
4812 select_devices(in->dev, in->usecase);
4813 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004814 if (in->enable_ns != enable &&
4815 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4816 in->enable_ns = enable;
4817 if (!in->standby)
4818 select_devices(in->dev, in->usecase);
4819 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004820 pthread_mutex_unlock(&in->dev->lock);
4821 pthread_mutex_unlock(&in->lock);
4822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004823 return 0;
4824}
4825
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004826static int in_add_audio_effect(const struct audio_stream *stream,
4827 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828{
Eric Laurent994a6932013-07-17 11:51:42 -07004829 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004830 return add_remove_audio_effect(stream, effect, true);
4831}
4832
4833static int in_remove_audio_effect(const struct audio_stream *stream,
4834 effect_handle_t effect)
4835{
Eric Laurent994a6932013-07-17 11:51:42 -07004836 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004837 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004838}
4839
Haynes Mathew George16081042017-05-31 17:16:49 -07004840static int in_stop(const struct audio_stream_in* stream)
4841{
4842 struct stream_in *in = (struct stream_in *)stream;
4843 struct audio_device *adev = in->dev;
4844
4845 int ret = -ENOSYS;
4846 ALOGV("%s", __func__);
4847 pthread_mutex_lock(&adev->lock);
4848 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4849 in->capture_started && in->pcm != NULL) {
4850 pcm_stop(in->pcm);
4851 ret = stop_input_stream(in);
4852 in->capture_started = false;
4853 }
4854 pthread_mutex_unlock(&adev->lock);
4855 return ret;
4856}
4857
4858static int in_start(const struct audio_stream_in* stream)
4859{
4860 struct stream_in *in = (struct stream_in *)stream;
4861 struct audio_device *adev = in->dev;
4862 int ret = -ENOSYS;
4863
4864 ALOGV("%s in %p", __func__, in);
4865 pthread_mutex_lock(&adev->lock);
4866 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4867 !in->capture_started && in->pcm != NULL) {
4868 if (!in->capture_started) {
4869 ret = start_input_stream(in);
4870 if (ret == 0) {
4871 in->capture_started = true;
4872 }
4873 }
4874 }
4875 pthread_mutex_unlock(&adev->lock);
4876 return ret;
4877}
4878
4879static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4880 int32_t min_size_frames,
4881 struct audio_mmap_buffer_info *info)
4882{
4883 struct stream_in *in = (struct stream_in *)stream;
4884 struct audio_device *adev = in->dev;
4885 int ret = 0;
4886 unsigned int offset1;
4887 unsigned int frames1;
4888 const char *step = "";
4889
4890 pthread_mutex_lock(&adev->lock);
4891 ALOGV("%s in %p", __func__, in);
4892
4893 if (info == NULL || min_size_frames == 0) {
4894 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
4895 ret = -EINVAL;
4896 goto exit;
4897 }
4898 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
4899 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
4900 ALOGV("%s in %p", __func__, in);
4901 ret = -ENOSYS;
4902 goto exit;
4903 }
4904 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4905 if (in->pcm_device_id < 0) {
4906 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4907 __func__, in->pcm_device_id, in->usecase);
4908 ret = -EINVAL;
4909 goto exit;
4910 }
4911
4912 adjust_mmap_period_count(&in->config, min_size_frames);
4913
4914 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4915 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4916 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4917 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4918 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4919 step = "open";
4920 ret = -ENODEV;
4921 goto exit;
4922 }
4923
4924 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4925 if (ret < 0) {
4926 step = "begin";
4927 goto exit;
4928 }
4929 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
4930 info->burst_size_frames = in->config.period_size;
4931 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4932
4933 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
4934 info->buffer_size_frames));
4935
4936 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4937 if (ret < 0) {
4938 step = "commit";
4939 goto exit;
4940 }
4941
4942 in->standby = false;
4943 ret = 0;
4944
4945 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4946 __func__, info->shared_memory_address, info->buffer_size_frames);
4947
4948exit:
4949 if (ret != 0) {
4950 if (in->pcm == NULL) {
4951 ALOGE("%s: %s - %d", __func__, step, ret);
4952 } else {
4953 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
4954 pcm_close(in->pcm);
4955 in->pcm = NULL;
4956 }
4957 }
4958 pthread_mutex_unlock(&adev->lock);
4959 return ret;
4960}
4961
4962static int in_get_mmap_position(const struct audio_stream_in *stream,
4963 struct audio_mmap_position *position)
4964{
4965 struct stream_in *in = (struct stream_in *)stream;
4966 ALOGVV("%s", __func__);
4967 if (position == NULL) {
4968 return -EINVAL;
4969 }
4970 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
4971 return -ENOSYS;
4972 }
4973 if (in->pcm == NULL) {
4974 return -ENOSYS;
4975 }
4976 struct timespec ts = { 0, 0 };
4977 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
4978 if (ret < 0) {
4979 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
4980 return ret;
4981 }
4982 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4983 return 0;
4984}
4985
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304986int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07004987 audio_io_handle_t handle,
4988 audio_devices_t devices,
4989 audio_output_flags_t flags,
4990 struct audio_config *config,
4991 struct audio_stream_out **stream_out,
4992 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004993{
4994 struct audio_device *adev = (struct audio_device *)dev;
4995 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304996 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004997 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004998 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05304999 bool is_direct_passthough = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005001 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305002
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005003 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5004
Mingming Yin3a941d42016-02-17 18:08:05 -08005005 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5006 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305007 devices, flags, &out->stream);
5008
5009
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005010 if (!out) {
5011 return -ENOMEM;
5012 }
5013
Haynes Mathew George204045b2015-02-25 20:32:03 -08005014 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005015 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305016 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005017 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005019 if (devices == AUDIO_DEVICE_NONE)
5020 devices = AUDIO_DEVICE_OUT_SPEAKER;
5021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005022 out->flags = flags;
5023 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005024 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005025 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005026 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305027 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305028 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5029 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5030 else
5031 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005032 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005033 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005034 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305035 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305036 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305037 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08005038 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005039
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305040 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Ben Romberger6c4d3812017-06-13 17:46:45 -07005041 (property_get_bool("audio.matrix.limiter.enable", false)))
5042 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5043
Mingming Yin3a941d42016-02-17 18:08:05 -08005044 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5045 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
5046 pthread_mutex_lock(&adev->lock);
5047 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5048 ret = read_hdmi_sink_caps(out);
5049 pthread_mutex_unlock(&adev->lock);
5050 if (ret != 0) {
5051 if (ret == -ENOSYS) {
5052 /* ignore and go with default */
5053 ret = 0;
5054 } else {
5055 ALOGE("error reading hdmi sink caps");
5056 goto error_open;
5057 }
5058 }
5059 }
5060
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005061 /* Init use case and pcm_config */
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305062#ifndef COMPRES_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005063 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5064 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5065 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5066 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5067 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5068 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5069
5070 out->config = default_pcm_config_voip_copp;
5071 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5072 out->config.rate = out->sample_rate;
5073
5074#else
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305075 } 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 -08005076 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005077 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005078 ret = voice_extn_compress_voip_open_output_stream(out);
5079 if (ret != 0) {
5080 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5081 __func__, ret);
5082 goto error_open;
5083 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005084#endif
vivek mehta0ea887a2015-08-26 14:01:20 -07005085 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305086 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305087 pthread_mutex_lock(&adev->lock);
5088 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5089 pthread_mutex_unlock(&adev->lock);
5090
5091 // reject offload during card offline to allow
5092 // fallback to s/w paths
5093 if (offline) {
5094 ret = -ENODEV;
5095 goto error_open;
5096 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005097
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005098 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5099 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5100 ALOGE("%s: Unsupported Offload information", __func__);
5101 ret = -EINVAL;
5102 goto error_open;
5103 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005104
Mingming Yin3a941d42016-02-17 18:08:05 -08005105 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005106 if(config->offload_info.format == 0)
5107 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08005108 if (config->offload_info.sample_rate == 0)
5109 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005110 }
5111
Mingming Yin90310102013-11-13 16:57:00 -08005112 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305113 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005114 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005115 ret = -EINVAL;
5116 goto error_open;
5117 }
5118
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005119 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5120 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5121 (audio_extn_passthru_is_passthrough_stream(out)) &&
5122 !((config->sample_rate == 48000) ||
5123 (config->sample_rate == 96000) ||
5124 (config->sample_rate == 192000))) {
5125 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5126 __func__, config->sample_rate, config->offload_info.format);
5127 ret = -EINVAL;
5128 goto error_open;
5129 }
5130
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005131 out->compr_config.codec = (struct snd_codec *)
5132 calloc(1, sizeof(struct snd_codec));
5133
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005134 if (!out->compr_config.codec) {
5135 ret = -ENOMEM;
5136 goto error_open;
5137 }
5138
Dhananjay Kumarac341582017-02-23 23:42:25 +05305139 out->stream.pause = out_pause;
5140 out->stream.resume = out_resume;
5141 out->stream.flush = out_flush;
5142 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005143 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07005144 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305145 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005146 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305147 } else {
5148 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5149 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005150 }
vivek mehta446c3962015-09-14 10:57:35 -07005151
5152 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005153 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5154 config->format == 0 && config->sample_rate == 0 &&
5155 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005156 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005157 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5158 } else {
5159 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5160 ret = -EEXIST;
5161 goto error_open;
5162 }
vivek mehta446c3962015-09-14 10:57:35 -07005163 }
5164
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005165 if (config->offload_info.channel_mask)
5166 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005167 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005168 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005169 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005170 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305171 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005172 ret = -EINVAL;
5173 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005174 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005175
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005176 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005177 out->sample_rate = config->offload_info.sample_rate;
5178
Mingming Yin3ee55c62014-08-04 14:23:35 -07005179 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005180
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305181 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
5182 if (audio_extn_is_dolby_format(config->offload_info.format)) {
5183 audio_extn_dolby_send_ddp_endp_params(adev);
5184 audio_extn_dolby_set_dmid(adev);
5185 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005186
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005187 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005188 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005189 out->compr_config.codec->bit_rate =
5190 config->offload_info.bit_rate;
5191 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305192 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005193 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305194 /* Update bit width only for non passthrough usecases.
5195 * For passthrough usecases, the output will always be opened @16 bit
5196 */
5197 if (!audio_extn_passthru_is_passthrough_stream(out))
5198 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305199
5200 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5201 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5202 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5203
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005204 /*TODO: Do we need to change it for passthrough */
5205 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005206
Manish Dewangana6fc5442015-08-24 20:30:31 +05305207 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5208 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305209 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305210 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305211 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5212 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305213
5214 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5215 AUDIO_FORMAT_PCM) {
5216
5217 /*Based on platform support, configure appropriate alsa format for corresponding
5218 *hal input format.
5219 */
5220 out->compr_config.codec->format = hal_format_to_alsa(
5221 config->offload_info.format);
5222
Ashish Jain83a6cc22016-06-28 14:34:17 +05305223 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305224 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305225 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305226
Dhananjay Kumarac341582017-02-23 23:42:25 +05305227 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305228 *hal input format and alsa format might differ based on platform support.
5229 */
5230 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305231 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305232
5233 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5234
5235 /* Check if alsa session is configured with the same format as HAL input format,
5236 * if not then derive correct fragment size needed to accomodate the
5237 * conversion of HAL input format to alsa format.
5238 */
5239 audio_extn_utils_update_direct_pcm_fragment_size(out);
5240
5241 /*if hal input and output fragment size is different this indicates HAL input format is
5242 *not same as the alsa format
5243 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305244 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305245 /*Allocate a buffer to convert input data to the alsa configured format.
5246 *size of convert buffer is equal to the size required to hold one fragment size
5247 *worth of pcm data, this is because flinger does not write more than fragment_size
5248 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305249 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5250 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305251 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5252 ret = -ENOMEM;
5253 goto error_open;
5254 }
5255 }
5256 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5257 out->compr_config.fragment_size =
5258 audio_extn_passthru_get_buffer_size(&config->offload_info);
5259 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5260 } else {
5261 out->compr_config.fragment_size =
5262 platform_get_compress_offload_buffer_size(&config->offload_info);
5263 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5264 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005265
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305266 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5267 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5268 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005269 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305270 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005271
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305272 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5273 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5274 }
5275
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005276 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5277 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005278
Manish Dewangan69426c82017-01-30 17:35:36 +05305279 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5280 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5281 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5282 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5283 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5284 } else {
5285 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5286 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005287
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305288 memset(&out->channel_map_param, 0,
5289 sizeof(struct audio_out_channel_map_param));
5290
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005291 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305292 out->send_next_track_params = false;
5293 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005294 out->offload_state = OFFLOAD_STATE_IDLE;
5295 out->playback_started = 0;
5296
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005297 audio_extn_dts_create_state_notifier_node(out->usecase);
5298
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005299 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5300 __func__, config->offload_info.version,
5301 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305302
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305303 /* Check if DSD audio format is supported in codec
5304 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305305 */
5306
5307 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305308 (!platform_check_codec_dsd_support(adev->platform) ||
5309 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305310 ret = -EINVAL;
5311 goto error_open;
5312 }
5313
Ashish Jain5106d362016-05-11 19:23:33 +05305314 /* Disable gapless if any of the following is true
5315 * passthrough playback
5316 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305317 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305318 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305319 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305320 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005321 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305322 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305323 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305324 check_and_set_gapless_mode(adev, false);
5325 } else
5326 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005327
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305328 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005329 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5330 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305331 if (config->format == AUDIO_FORMAT_DSD) {
5332 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5333 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5334 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005335
5336 create_offload_callback_thread(out);
5337
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005338 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305339 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005340 if (ret != 0) {
5341 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5342 __func__, ret);
5343 goto error_open;
5344 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005345 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5346 if (config->sample_rate == 0)
5347 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5348 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5349 config->sample_rate != 8000) {
5350 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5351 ret = -EINVAL;
5352 goto error_open;
5353 }
5354 out->sample_rate = config->sample_rate;
5355 out->config.rate = config->sample_rate;
5356 if (config->format == AUDIO_FORMAT_DEFAULT)
5357 config->format = AUDIO_FORMAT_PCM_16_BIT;
5358 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5359 config->format = AUDIO_FORMAT_PCM_16_BIT;
5360 ret = -EINVAL;
5361 goto error_open;
5362 }
5363 out->format = config->format;
5364 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5365 out->config = pcm_config_afe_proxy_playback;
5366 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005367 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305368 unsigned int channels = 0;
5369 /*Update config params to default if not set by the caller*/
5370 if (config->sample_rate == 0)
5371 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5372 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5373 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5374 if (config->format == AUDIO_FORMAT_DEFAULT)
5375 config->format = AUDIO_FORMAT_PCM_16_BIT;
5376
5377 channels = audio_channel_count_from_out_mask(out->channel_mask);
5378
Varun Balaraje49253e2017-07-06 19:48:56 +05305379 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
5380 out->usecase = get_interactive_usecase(adev);
5381 out->config = pcm_config_low_latency;
5382 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305383 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005384 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5385 out->flags);
5386 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005387 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5388 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5389 out->config = pcm_config_mmap_playback;
5390 out->stream.start = out_start;
5391 out->stream.stop = out_stop;
5392 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5393 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305394 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5395 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005396 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5397 if (!out->dynamic_pm_qos_enabled) {
5398 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5399 } else {
5400 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5401 //the mixer path will be a string similar to "low-latency-playback resume"
5402 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5403 strlcat(out->pm_qos_mixer_path,
5404 " resume", MAX_MIXER_PATH_LEN);
5405 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5406 out->pm_qos_mixer_path);
5407 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305408 out->config = pcm_config_low_latency;
5409 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5410 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5411 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305412 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5413 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5414 if (out->config.period_size <= 0) {
5415 ALOGE("Invalid configuration period size is not valid");
5416 ret = -EINVAL;
5417 goto error_open;
5418 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305419 } else {
5420 /* primary path is the default path selected if no other outputs are available/suitable */
5421 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5422 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5423 }
5424 out->hal_ip_format = format = out->format;
5425 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5426 out->hal_op_format = pcm_format_to_hal(out->config.format);
5427 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5428 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005429 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305430 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305431 if (out->hal_ip_format != out->hal_op_format) {
5432 uint32_t buffer_size = out->config.period_size *
5433 format_to_bitwidth_table[out->hal_op_format] *
5434 out->config.channels;
5435 out->convert_buffer = calloc(1, buffer_size);
5436 if (out->convert_buffer == NULL){
5437 ALOGE("Allocation failed for convert buffer for size %d",
5438 out->compr_config.fragment_size);
5439 ret = -ENOMEM;
5440 goto error_open;
5441 }
5442 ALOGD("Convert buffer allocated of size %d", buffer_size);
5443 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005444 }
5445
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005446 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5447 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305448
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005449 /* TODO remove this hardcoding and check why width is zero*/
5450 if (out->bit_width == 0)
5451 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305452 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005453 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05305454 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305455 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305456 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005457 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5458 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5459 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005460 if(adev->primary_output == NULL)
5461 adev->primary_output = out;
5462 else {
5463 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005464 ret = -EEXIST;
5465 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005466 }
5467 }
5468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005469 /* Check if this usecase is already existing */
5470 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005471 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5472 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005473 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005474 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005475 ret = -EEXIST;
5476 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005477 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005479 pthread_mutex_unlock(&adev->lock);
5480
5481 out->stream.common.get_sample_rate = out_get_sample_rate;
5482 out->stream.common.set_sample_rate = out_set_sample_rate;
5483 out->stream.common.get_buffer_size = out_get_buffer_size;
5484 out->stream.common.get_channels = out_get_channels;
5485 out->stream.common.get_format = out_get_format;
5486 out->stream.common.set_format = out_set_format;
5487 out->stream.common.standby = out_standby;
5488 out->stream.common.dump = out_dump;
5489 out->stream.common.set_parameters = out_set_parameters;
5490 out->stream.common.get_parameters = out_get_parameters;
5491 out->stream.common.add_audio_effect = out_add_audio_effect;
5492 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5493 out->stream.get_latency = out_get_latency;
5494 out->stream.set_volume = out_set_volume;
5495 out->stream.write = out_write;
5496 out->stream.get_render_position = out_get_render_position;
5497 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005498 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005499
Haynes Mathew George16081042017-05-31 17:16:49 -07005500 if (out->realtime)
5501 out->af_period_multiplier = af_period_multiplier;
5502 else
5503 out->af_period_multiplier = 1;
5504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005505 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005506 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005507 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005508
5509 config->format = out->stream.common.get_format(&out->stream.common);
5510 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5511 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5512
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305513 /*
5514 By locking output stream before registering, we allow the callback
5515 to update stream's state only after stream's initial state is set to
5516 adev state.
5517 */
5518 lock_output_stream(out);
5519 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5520 pthread_mutex_lock(&adev->lock);
5521 out->card_status = adev->card_status;
5522 pthread_mutex_unlock(&adev->lock);
5523 pthread_mutex_unlock(&out->lock);
5524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005525 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305526 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07005527 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005528
5529 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
5530 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5531 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005532 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05305533 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005534 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005535 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05305536 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005537 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5538 out->usecase, PCM_PLAYBACK);
5539 hdlr_stream_cfg.flags = out->flags;
5540 hdlr_stream_cfg.type = PCM_PLAYBACK;
5541 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5542 &hdlr_stream_cfg);
5543 if (ret) {
5544 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5545 out->adsp_hdlr_stream_handle = NULL;
5546 }
5547 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05305548 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07005549 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07005550 if (ret < 0) {
5551 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5552 out->ip_hdlr_handle = NULL;
5553 }
5554 }
Eric Laurent994a6932013-07-17 11:51:42 -07005555 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005556 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005557
5558error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305559 if (out->convert_buffer)
5560 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005561 free(out);
5562 *stream_out = NULL;
5563 ALOGD("%s: exit: ret %d", __func__, ret);
5564 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005565}
5566
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305567void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005568 struct audio_stream_out *stream)
5569{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005570 struct stream_out *out = (struct stream_out *)stream;
5571 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005572 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005573
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305574 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
5575
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305576 // must deregister from sndmonitor first to prevent races
5577 // between the callback and close_stream
5578 audio_extn_snd_mon_unregister_listener(out);
5579
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005580 /* close adsp hdrl session before standby */
5581 if (out->adsp_hdlr_stream_handle) {
5582 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5583 if (ret)
5584 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5585 out->adsp_hdlr_stream_handle = NULL;
5586 }
5587
Manish Dewangan21a850a2017-08-14 12:03:55 +05305588 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07005589 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5590 out->ip_hdlr_handle = NULL;
5591 }
5592
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005593 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305594 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005595 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305596 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305597 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005598 if(ret != 0)
5599 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5600 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005601 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005602 out_standby(&stream->common);
5603
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005604 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005605 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005606 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005607 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005608 if (out->compr_config.codec != NULL)
5609 free(out->compr_config.codec);
5610 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005611
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305612 out->a2dp_compress_mute = false;
5613
Varun Balaraje49253e2017-07-06 19:48:56 +05305614 if (is_interactive_usecase(out->usecase))
5615 free_interactive_usecase(adev, out->usecase);
5616
Ashish Jain83a6cc22016-06-28 14:34:17 +05305617 if (out->convert_buffer != NULL) {
5618 free(out->convert_buffer);
5619 out->convert_buffer = NULL;
5620 }
5621
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005622 if (adev->voice_tx_output == out)
5623 adev->voice_tx_output = NULL;
5624
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305625 if (adev->primary_output == out)
5626 adev->primary_output = NULL;
5627
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005628 pthread_cond_destroy(&out->cond);
5629 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005630 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005631 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005632}
5633
5634static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5635{
5636 struct audio_device *adev = (struct audio_device *)dev;
5637 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005638 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005639 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005640 int ret;
5641 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005642
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005643 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005644 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005645
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305646 if (!parms)
5647 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305648
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305649 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5650 if (ret >= 0) {
5651 /* When set to false, HAL should disable EC and NS */
5652 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5653 adev->bt_sco_on = true;
5654 else
5655 adev->bt_sco_on = false;
5656 }
5657
Naresh Tanniru4c630392014-05-12 01:05:52 +05305658 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005659 status = voice_set_parameters(adev, parms);
5660 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005661 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005662
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005663 status = platform_set_parameters(adev->platform, parms);
5664 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005665 goto done;
5666
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005667 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5668 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005669 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005670 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5671 adev->bluetooth_nrec = true;
5672 else
5673 adev->bluetooth_nrec = false;
5674 }
5675
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005676 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5677 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005678 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5679 adev->screen_off = false;
5680 else
5681 adev->screen_off = true;
5682 }
5683
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005684 ret = str_parms_get_int(parms, "rotation", &val);
5685 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005686 bool reverse_speakers = false;
5687 switch(val) {
5688 // FIXME: note that the code below assumes that the speakers are in the correct placement
5689 // relative to the user when the device is rotated 90deg from its default rotation. This
5690 // assumption is device-specific, not platform-specific like this code.
5691 case 270:
5692 reverse_speakers = true;
5693 break;
5694 case 0:
5695 case 90:
5696 case 180:
5697 break;
5698 default:
5699 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005700 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005701 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005702 if (status == 0) {
5703 if (adev->speaker_lr_swap != reverse_speakers) {
5704 adev->speaker_lr_swap = reverse_speakers;
5705 // only update the selected device if there is active pcm playback
5706 struct audio_usecase *usecase;
5707 struct listnode *node;
5708 list_for_each(node, &adev->usecase_list) {
5709 usecase = node_to_item(node, struct audio_usecase, list);
5710 if (usecase->type == PCM_PLAYBACK) {
5711 select_devices(adev, usecase->id);
5712 break;
5713 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005714 }
5715 }
5716 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005717 }
5718
Mingming Yin514a8bc2014-07-29 15:22:21 -07005719 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5720 if (ret >= 0) {
5721 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5722 adev->bt_wb_speech_enabled = true;
5723 else
5724 adev->bt_wb_speech_enabled = false;
5725 }
5726
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005727 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5728 if (ret >= 0) {
5729 val = atoi(value);
5730 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005731 ALOGV("cache new ext disp type and edid");
5732 ret = platform_get_ext_disp_type(adev->platform);
5733 if (ret < 0) {
5734 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08005735 status = ret;
5736 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005737 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005738 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005739 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005740 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07005741 /*
5742 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
5743 * Per AudioPolicyManager, USB device is higher priority than WFD.
5744 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
5745 * If WFD use case occupies AFE proxy, it may result unintended behavior while
5746 * starting voice call on USB
5747 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005748 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5749 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08005750 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5751 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005752 }
vivek mehta344576a2016-04-12 18:56:03 -07005753 ALOGV("detected USB connect .. disable proxy");
5754 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005755 }
5756 }
5757
5758 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5759 if (ret >= 0) {
5760 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07005761 /*
5762 * The HDMI / Displayport disconnect handling has been moved to
5763 * audio extension to ensure that its parameters are not
5764 * invalidated prior to updating sysfs of the disconnect event
5765 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
5766 */
5767 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005768 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005769 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5770 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05305771 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5772 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005773 }
vivek mehta344576a2016-04-12 18:56:03 -07005774 ALOGV("detected USB disconnect .. enable proxy");
5775 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005776 }
5777 }
5778
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305779 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5780 if (ret >= 0) {
5781 struct audio_usecase *usecase;
5782 struct listnode *node;
5783 list_for_each(node, &adev->usecase_list) {
5784 usecase = node_to_item(node, struct audio_usecase, list);
5785 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005786 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305787 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005788
5789 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305790 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005791 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305792 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305793 //force device switch to re configure encoder
5794 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305795 audio_extn_a2dp_set_handoff_mode(false);
5796 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305797 break;
5798 }
5799 }
5800 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005801
5802 //handle vr audio setparam
5803 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5804 value, sizeof(value));
5805 if (ret >= 0) {
5806 ALOGI("Setting vr mode to be %s", value);
5807 if (!strncmp(value, "true", 4)) {
5808 adev->vr_audio_mode_enabled = true;
5809 ALOGI("Setting vr mode to true");
5810 } else if (!strncmp(value, "false", 5)) {
5811 adev->vr_audio_mode_enabled = false;
5812 ALOGI("Setting vr mode to false");
5813 } else {
5814 ALOGI("wrong vr mode set");
5815 }
5816 }
5817
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305818 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005819done:
5820 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005821 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305822error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005823 ALOGV("%s: exit with code(%d)", __func__, status);
5824 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005825}
5826
5827static char* adev_get_parameters(const struct audio_hw_device *dev,
5828 const char *keys)
5829{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005830 struct audio_device *adev = (struct audio_device *)dev;
5831 struct str_parms *reply = str_parms_create();
5832 struct str_parms *query = str_parms_create_str(keys);
5833 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305834 char value[256] = {0};
5835 int ret = 0;
5836
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005837 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005838 if (reply) {
5839 str_parms_destroy(reply);
5840 }
5841 if (query) {
5842 str_parms_destroy(query);
5843 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005844 ALOGE("adev_get_parameters: failed to create query or reply");
5845 return NULL;
5846 }
5847
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005848 //handle vr audio getparam
5849
5850 ret = str_parms_get_str(query,
5851 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5852 value, sizeof(value));
5853
5854 if (ret >= 0) {
5855 bool vr_audio_enabled = false;
5856 pthread_mutex_lock(&adev->lock);
5857 vr_audio_enabled = adev->vr_audio_mode_enabled;
5858 pthread_mutex_unlock(&adev->lock);
5859
5860 ALOGI("getting vr mode to %d", vr_audio_enabled);
5861
5862 if (vr_audio_enabled) {
5863 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5864 "true");
5865 goto exit;
5866 } else {
5867 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5868 "false");
5869 goto exit;
5870 }
5871 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005872
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005873 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005874 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005875 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005876 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305877 pthread_mutex_unlock(&adev->lock);
5878
Naresh Tannirud7205b62014-06-20 02:54:48 +05305879exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005880 str = str_parms_to_str(reply);
5881 str_parms_destroy(query);
5882 str_parms_destroy(reply);
5883
5884 ALOGV("%s: exit: returns - %s", __func__, str);
5885 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005886}
5887
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005888static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005889{
5890 return 0;
5891}
5892
5893static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5894{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005895 int ret;
5896 struct audio_device *adev = (struct audio_device *)dev;
5897 pthread_mutex_lock(&adev->lock);
5898 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005899 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005900 pthread_mutex_unlock(&adev->lock);
5901 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005902}
5903
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005904static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5905 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005906{
5907 return -ENOSYS;
5908}
5909
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005910static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5911 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005912{
5913 return -ENOSYS;
5914}
5915
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005916static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5917 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005918{
5919 return -ENOSYS;
5920}
5921
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005922static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5923 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005924{
5925 return -ENOSYS;
5926}
5927
5928static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5929{
5930 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005932 pthread_mutex_lock(&adev->lock);
5933 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005934 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005935 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005936 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005937 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005938 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005939 adev->current_call_output = NULL;
5940 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005941 }
5942 pthread_mutex_unlock(&adev->lock);
5943 return 0;
5944}
5945
5946static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5947{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005948 int ret;
5949
5950 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005951 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005952 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5953 pthread_mutex_unlock(&adev->lock);
5954
5955 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005956}
5957
5958static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5959{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005960 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005961 return 0;
5962}
5963
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005964static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005965 const struct audio_config *config)
5966{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005967 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005968
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005969 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5970 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005971}
5972
5973static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005974 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005975 audio_devices_t devices,
5976 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005977 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305978 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005979 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005980 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005981{
5982 struct audio_device *adev = (struct audio_device *)dev;
5983 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005984 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005985 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005986 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305987 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005989 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305990 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5991 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005992 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305993 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005994
5995 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005996
5997 if (!in) {
5998 ALOGE("failed to allocate input stream");
5999 return -ENOMEM;
6000 }
6001
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306002 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306003 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
6004 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006005 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006006 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006008 in->stream.common.get_sample_rate = in_get_sample_rate;
6009 in->stream.common.set_sample_rate = in_set_sample_rate;
6010 in->stream.common.get_buffer_size = in_get_buffer_size;
6011 in->stream.common.get_channels = in_get_channels;
6012 in->stream.common.get_format = in_get_format;
6013 in->stream.common.set_format = in_set_format;
6014 in->stream.common.standby = in_standby;
6015 in->stream.common.dump = in_dump;
6016 in->stream.common.set_parameters = in_set_parameters;
6017 in->stream.common.get_parameters = in_get_parameters;
6018 in->stream.common.add_audio_effect = in_add_audio_effect;
6019 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6020 in->stream.set_gain = in_set_gain;
6021 in->stream.read = in_read;
6022 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6023
6024 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006025 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006026 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006027 in->standby = 1;
6028 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006029 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006030 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006031
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306032 in->usecase = USECASE_AUDIO_RECORD;
6033 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006034 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306035 is_low_latency = true;
6036#if LOW_LATENCY_CAPTURE_USE_CASE
6037 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
6038#endif
6039 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
6040 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006041 in->format = config->format;
Haynes Mathew George16081042017-05-31 17:16:49 -07006042 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6043 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
6044 in->realtime = 0;
6045 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6046 in->config = pcm_config_mmap_capture;
6047 in->stream.start = in_start;
6048 in->stream.stop = in_stop;
6049 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6050 in->stream.get_mmap_position = in_get_mmap_position;
6051 in->af_period_multiplier = 1;
6052 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
6053 } else if (in->realtime) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006054 in->config = pcm_config_audio_capture_rt;
6055 in->sample_rate = in->config.rate;
6056 in->af_period_multiplier = af_period_multiplier;
6057 } else {
6058 in->config = pcm_config_audio_capture;
6059 in->config.rate = config->sample_rate;
6060 in->sample_rate = config->sample_rate;
6061 in->af_period_multiplier = 1;
6062 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306063 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006064
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306065 /* restrict 24 bit capture for unprocessed source only
6066 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
6067 */
6068 if (config->format == AUDIO_FORMAT_DEFAULT) {
6069 config->format = AUDIO_FORMAT_PCM_16_BIT;
6070 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6071 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6072 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6073 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6074 bool ret_error = false;
6075 in->bit_width = 24;
6076 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6077 from HAL is 24_packed and 8_24
6078 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6079 24_packed return error indicating supported format is 24_packed
6080 *> In case of any other source requesting 24 bit or float return error
6081 indicating format supported is 16 bit only.
6082
6083 on error flinger will retry with supported format passed
6084 */
6085 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6086 (source != AUDIO_SOURCE_CAMCORDER)) {
6087 config->format = AUDIO_FORMAT_PCM_16_BIT;
6088 if (config->sample_rate > 48000)
6089 config->sample_rate = 48000;
6090 ret_error = true;
6091 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
6092 in->config.format = PCM_FORMAT_S24_3LE;
6093 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
6094 in->config.format = PCM_FORMAT_S24_LE;
6095 } else {
6096 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
6097 ret_error = true;
6098 }
6099
6100 if (ret_error) {
6101 ret = -EINVAL;
6102 goto err_open;
6103 }
6104 }
6105
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306106 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306107 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6108 (adev->mode != AUDIO_MODE_IN_CALL)) {
6109 ret = -EINVAL;
6110 goto err_open;
6111 }
6112
6113 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
6114 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006115 if (config->sample_rate == 0)
6116 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6117 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6118 config->sample_rate != 8000) {
6119 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6120 ret = -EINVAL;
6121 goto err_open;
6122 }
6123 if (config->format == AUDIO_FORMAT_DEFAULT)
6124 config->format = AUDIO_FORMAT_PCM_16_BIT;
6125 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6126 config->format = AUDIO_FORMAT_PCM_16_BIT;
6127 ret = -EINVAL;
6128 goto err_open;
6129 }
6130
6131 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6132 in->config = pcm_config_afe_proxy_record;
6133 in->config.channels = channel_count;
6134 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306135 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306136 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
6137 in, config, &channel_mask_updated)) {
6138 if (channel_mask_updated == true) {
6139 ALOGD("%s: return error to retry with updated channel mask (%#x)",
6140 __func__, config->channel_mask);
6141 ret = -EINVAL;
6142 goto err_open;
6143 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05306144 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07006145 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006146 audio_extn_compr_cap_format_supported(config->format) &&
6147 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006148 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306149 } else if (audio_extn_cin_applicable_stream(in)) {
6150 ret = audio_extn_cin_configure_input_stream(in);
6151 if (ret)
6152 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006153 } else {
6154 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006155 if (!in->realtime) {
6156 in->format = config->format;
6157 frame_size = audio_stream_in_frame_size(&in->stream);
6158 buffer_size = get_input_buffer_size(config->sample_rate,
6159 config->format,
6160 channel_count,
6161 is_low_latency);
6162 in->config.period_size = buffer_size / frame_size;
6163 }
6164
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006165#ifndef COMPRESS_VOIP_ENABLED
6166 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6167 (in->config.rate == 8000 || in->config.rate == 16000 ||
6168 in->config.rate == 32000 || in->config.rate == 48000) &&
6169 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6170
6171 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6172 in->config = default_pcm_config_voip_copp;
6173 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6174 in->config.rate = in->sample_rate;
6175#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006176 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006177 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6178 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006179 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006180 (in->config.rate == 8000 || in->config.rate == 16000 ||
6181 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006182 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6183 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006184#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006185 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006186 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006187
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306188 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6189 &adev->streams_input_cfg_list,
6190 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306191 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306192
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006193 /* This stream could be for sound trigger lab,
6194 get sound trigger pcm if present */
6195 audio_extn_sound_trigger_check_and_get_session(in);
6196
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306197 lock_input_stream(in);
6198 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6199 pthread_mutex_lock(&adev->lock);
6200 in->card_status = adev->card_status;
6201 pthread_mutex_unlock(&adev->lock);
6202 pthread_mutex_unlock(&in->lock);
6203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006204 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006205 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006206 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006207
6208err_open:
6209 free(in);
6210 *stream_in = NULL;
6211 return ret;
6212}
6213
6214static void adev_close_input_stream(struct audio_hw_device *dev,
6215 struct audio_stream_in *stream)
6216{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006217 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006218 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006219 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306220
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306221 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006222
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306223 // must deregister from sndmonitor first to prevent races
6224 // between the callback and close_stream
6225 audio_extn_snd_mon_unregister_listener(stream);
6226
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306227 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006228 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306229
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006230 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306231 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006232 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306233 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006234 if (ret != 0)
6235 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6236 __func__, ret);
6237 } else
6238 in_standby(&stream->common);
6239
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006240 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006241 audio_extn_ssr_deinit();
6242 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006243
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306244 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006245 audio_extn_compr_cap_format_supported(in->config.format))
6246 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306247
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306248 if (audio_extn_cin_attached_usecase(in->usecase))
6249 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006250
Mingming Yinfd7607b2016-01-22 12:48:44 -08006251 if (in->is_st_session) {
6252 ALOGV("%s: sound trigger pcm stop lab", __func__);
6253 audio_extn_sound_trigger_stop_lab(in);
6254 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006255 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006256 return;
6257}
6258
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306259int adev_create_audio_patch(struct audio_hw_device *dev,
6260 unsigned int num_sources,
6261 const struct audio_port_config *sources,
6262 unsigned int num_sinks,
6263 const struct audio_port_config *sinks,
6264 audio_patch_handle_t *handle)
6265{
6266
6267
6268 return audio_extn_hw_loopback_create_audio_patch(dev,
6269 num_sources,
6270 sources,
6271 num_sinks,
6272 sinks,
6273 handle);
6274
6275}
6276
6277int adev_release_audio_patch(struct audio_hw_device *dev,
6278 audio_patch_handle_t handle)
6279{
6280 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6281}
6282
6283int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6284{
6285 return audio_extn_hw_loopback_get_audio_port(dev, config);
6286}
6287
6288int adev_set_audio_port_config(struct audio_hw_device *dev,
6289 const struct audio_port_config *config)
6290{
6291 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6292}
6293
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006294static int adev_dump(const audio_hw_device_t *device __unused,
6295 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006296{
6297 return 0;
6298}
6299
6300static int adev_close(hw_device_t *device)
6301{
6302 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006303
6304 if (!adev)
6305 return 0;
6306
6307 pthread_mutex_lock(&adev_init_lock);
6308
6309 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306310 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006311 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006312 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306313 audio_extn_utils_release_streams_cfg_lists(
6314 &adev->streams_output_cfg_list,
6315 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306316 if (audio_extn_qaf_is_enabled())
6317 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006318 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006319 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006320 free(adev->snd_dev_ref_cnt);
6321 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006322 if (adev->adm_deinit)
6323 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306324 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006325 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306326 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306327 audio_extn_hw_loopback_deinit(adev);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306328 if (adev->device_cfg_params) {
6329 free(adev->device_cfg_params);
6330 adev->device_cfg_params = NULL;
6331 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006332 free(device);
6333 adev = NULL;
6334 }
6335 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006337 return 0;
6338}
6339
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006340/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6341 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6342 * just that it _might_ work.
6343 */
6344static int period_size_is_plausible_for_low_latency(int period_size)
6345{
6346 switch (period_size) {
6347 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006348 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006349 case 240:
6350 case 320:
6351 case 480:
6352 return 1;
6353 default:
6354 return 0;
6355 }
6356}
6357
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306358static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6359{
6360 bool is_snd_card_status = false;
6361 bool is_ext_device_status = false;
6362 char value[32];
6363 int card = -1;
6364 card_status_t status;
6365
6366 if (cookie != adev || !parms)
6367 return;
6368
6369 if (!parse_snd_card_status(parms, &card, &status)) {
6370 is_snd_card_status = true;
6371 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6372 is_ext_device_status = true;
6373 } else {
6374 // not a valid event
6375 return;
6376 }
6377
6378 pthread_mutex_lock(&adev->lock);
6379 if (card == adev->snd_card || is_ext_device_status) {
6380 if (is_snd_card_status && adev->card_status != status) {
6381 adev->card_status = status;
6382 platform_snd_card_update(adev->platform, status);
6383 audio_extn_fm_set_parameters(adev, parms);
6384 } else if (is_ext_device_status) {
6385 platform_set_parameters(adev->platform, parms);
6386 }
6387 }
6388 pthread_mutex_unlock(&adev->lock);
6389 return;
6390}
6391
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306392/* out and adev lock held */
6393static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6394{
6395 struct audio_usecase *uc_info;
6396 float left_p;
6397 float right_p;
6398 audio_devices_t devices;
6399
6400 uc_info = get_usecase_from_list(adev, out->usecase);
6401 if (uc_info == NULL) {
6402 ALOGE("%s: Could not find the usecase (%d) in the list",
6403 __func__, out->usecase);
6404 return -EINVAL;
6405 }
6406
6407 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6408 out->usecase, use_case_table[out->usecase]);
6409
6410 if (restore) {
6411 // restore A2DP device for active usecases and unmute if required
6412 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6413 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6414 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6415 select_devices(adev, uc_info->id);
6416 pthread_mutex_lock(&out->compr_mute_lock);
6417 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6418 (out->a2dp_compress_mute)) {
6419 out->a2dp_compress_mute = false;
6420 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6421 }
6422 pthread_mutex_unlock(&out->compr_mute_lock);
6423 }
6424 } else {
6425 // mute compress stream if suspended
6426 pthread_mutex_lock(&out->compr_mute_lock);
6427 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6428 (!out->a2dp_compress_mute)) {
6429 if (!out->standby) {
6430 ALOGD("%s: selecting speaker and muting stream", __func__);
6431 devices = out->devices;
6432 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6433 left_p = out->volume_l;
6434 right_p = out->volume_r;
6435 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6436 compress_pause(out->compr);
6437 out_set_compr_volume(&out->stream, (float)0, (float)0);
6438 out->a2dp_compress_mute = true;
6439 select_devices(adev, out->usecase);
6440 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6441 compress_resume(out->compr);
6442 out->devices = devices;
6443 out->volume_l = left_p;
6444 out->volume_r = right_p;
6445 }
6446 }
6447 pthread_mutex_unlock(&out->compr_mute_lock);
6448 }
6449 ALOGV("%s: exit", __func__);
6450 return 0;
6451}
6452
6453int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6454{
6455 int ret = 0;
6456
6457 lock_output_stream(out);
6458 pthread_mutex_lock(&adev->lock);
6459
6460 ret = check_a2dp_restore_l(adev, out, restore);
6461
6462 pthread_mutex_unlock(&adev->lock);
6463 pthread_mutex_unlock(&out->lock);
6464 return ret;
6465}
6466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006467static int adev_open(const hw_module_t *module, const char *name,
6468 hw_device_t **device)
6469{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306470 int ret;
6471
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006472 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006473 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
6474
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006475 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07006476 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006477 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07006478 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006479 ALOGD("%s: returning existing instance of adev", __func__);
6480 ALOGD("%s: exit", __func__);
6481 pthread_mutex_unlock(&adev_init_lock);
6482 return 0;
6483 }
6484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006485 adev = calloc(1, sizeof(struct audio_device));
6486
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006487 if (!adev) {
6488 pthread_mutex_unlock(&adev_init_lock);
6489 return -ENOMEM;
6490 }
6491
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006492 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6493
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05306494#ifdef DYNAMIC_LOG_ENABLED
6495 register_for_dynamic_logging("hal");
6496#endif
6497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006498 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6499 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6500 adev->device.common.module = (struct hw_module_t *)module;
6501 adev->device.common.close = adev_close;
6502
6503 adev->device.init_check = adev_init_check;
6504 adev->device.set_voice_volume = adev_set_voice_volume;
6505 adev->device.set_master_volume = adev_set_master_volume;
6506 adev->device.get_master_volume = adev_get_master_volume;
6507 adev->device.set_master_mute = adev_set_master_mute;
6508 adev->device.get_master_mute = adev_get_master_mute;
6509 adev->device.set_mode = adev_set_mode;
6510 adev->device.set_mic_mute = adev_set_mic_mute;
6511 adev->device.get_mic_mute = adev_get_mic_mute;
6512 adev->device.set_parameters = adev_set_parameters;
6513 adev->device.get_parameters = adev_get_parameters;
6514 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6515 adev->device.open_output_stream = adev_open_output_stream;
6516 adev->device.close_output_stream = adev_close_output_stream;
6517 adev->device.open_input_stream = adev_open_input_stream;
6518 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306519 adev->device.create_audio_patch = adev_create_audio_patch;
6520 adev->device.release_audio_patch = adev_release_audio_patch;
6521 adev->device.get_audio_port = adev_get_audio_port;
6522 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006523 adev->device.dump = adev_dump;
6524
6525 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006526 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08006527 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006528 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006529 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006530 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006531 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07006532 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306533 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006534 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006535 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006536 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006537 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08006538 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006539 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05306540 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306541 adev->perf_lock_opts[0] = 0x101;
6542 adev->perf_lock_opts[1] = 0x20E;
6543 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006544 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006546 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006547 adev->platform = platform_init(adev);
6548 if (!adev->platform) {
6549 free(adev->snd_dev_ref_cnt);
6550 free(adev);
6551 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6552 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006553 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306554 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006555 return -EINVAL;
6556 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006557
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306558 if (audio_extn_qaf_is_enabled()) {
6559 ret = audio_extn_qaf_init(adev);
6560 if (ret < 0) {
6561 free(adev);
6562 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6563 *device = NULL;
6564 pthread_mutex_unlock(&adev_init_lock);
6565 pthread_mutex_destroy(&adev->lock);
6566 return ret;
6567 }
6568
6569 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6570 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6571 }
6572
Eric Laurentc4aef752013-09-12 17:45:53 -07006573 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6574 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6575 if (adev->visualizer_lib == NULL) {
6576 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6577 } else {
6578 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6579 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006580 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006581 "visualizer_hal_start_output");
6582 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006583 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006584 "visualizer_hal_stop_output");
6585 }
6586 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05306587 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08006588 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006589 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306590 audio_extn_hw_loopback_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07006591
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006592 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
6593 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6594 if (adev->offload_effects_lib == NULL) {
6595 ALOGE("%s: DLOPEN failed for %s", __func__,
6596 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6597 } else {
6598 ALOGV("%s: DLOPEN successful for %s", __func__,
6599 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6600 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05306601 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006602 "offload_effects_bundle_hal_start_output");
6603 adev->offload_effects_stop_output =
6604 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6605 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006606 adev->offload_effects_set_hpx_state =
6607 (int (*)(bool))dlsym(adev->offload_effects_lib,
6608 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05306609 adev->offload_effects_get_parameters =
6610 (void (*)(struct str_parms *, struct str_parms *))
6611 dlsym(adev->offload_effects_lib,
6612 "offload_effects_bundle_get_parameters");
6613 adev->offload_effects_set_parameters =
6614 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
6615 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006616 }
6617 }
6618
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006619 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
6620 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6621 if (adev->adm_lib == NULL) {
6622 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6623 } else {
6624 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6625 adev->adm_init = (adm_init_t)
6626 dlsym(adev->adm_lib, "adm_init");
6627 adev->adm_deinit = (adm_deinit_t)
6628 dlsym(adev->adm_lib, "adm_deinit");
6629 adev->adm_register_input_stream = (adm_register_input_stream_t)
6630 dlsym(adev->adm_lib, "adm_register_input_stream");
6631 adev->adm_register_output_stream = (adm_register_output_stream_t)
6632 dlsym(adev->adm_lib, "adm_register_output_stream");
6633 adev->adm_deregister_stream = (adm_deregister_stream_t)
6634 dlsym(adev->adm_lib, "adm_deregister_stream");
6635 adev->adm_request_focus = (adm_request_focus_t)
6636 dlsym(adev->adm_lib, "adm_request_focus");
6637 adev->adm_abandon_focus = (adm_abandon_focus_t)
6638 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006639 adev->adm_set_config = (adm_set_config_t)
6640 dlsym(adev->adm_lib, "adm_set_config");
6641 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6642 dlsym(adev->adm_lib, "adm_request_focus_v2");
6643 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6644 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6645 adev->adm_on_routing_change = (adm_on_routing_change_t)
6646 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006647 }
6648 }
6649
Mingming Yin514a8bc2014-07-29 15:22:21 -07006650 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006651 //initialize this to false for now,
6652 //this will be set to true through set param
6653 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07006654
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07006655 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006656 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006657 adev->dsp_bit_width_enforce_mode =
6658 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006659
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306660 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
6661 &adev->streams_output_cfg_list,
6662 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006663
Kiran Kandi910e1862013-10-29 13:29:42 -07006664 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006665
6666 char value[PROPERTY_VALUE_MAX];
6667 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006668 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006669 trial = atoi(value);
6670 if (period_size_is_plausible_for_low_latency(trial)) {
6671 pcm_config_low_latency.period_size = trial;
6672 pcm_config_low_latency.start_threshold = trial / 4;
6673 pcm_config_low_latency.avail_min = trial / 4;
6674 configured_low_latency_capture_period_size = trial;
6675 }
6676 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006677 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006678 trial = atoi(value);
6679 if (period_size_is_plausible_for_low_latency(trial)) {
6680 configured_low_latency_capture_period_size = trial;
6681 }
6682 }
6683
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006684 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006685 af_period_multiplier = atoi(value);
6686 if (af_period_multiplier < 0)
6687 af_period_multiplier = 2;
6688 else if (af_period_multiplier > 4)
6689 af_period_multiplier = 4;
6690
6691 ALOGV("new period_multiplier = %d", af_period_multiplier);
6692 }
6693
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006694 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006695 pthread_mutex_unlock(&adev_init_lock);
6696
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006697 if (adev->adm_init)
6698 adev->adm_data = adev->adm_init();
6699
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306700 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306701 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006702 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306703
6704 audio_extn_snd_mon_init();
6705 pthread_mutex_lock(&adev->lock);
6706 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
6707 adev->card_status = CARD_STATUS_ONLINE;
6708 pthread_mutex_unlock(&adev->lock);
6709 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306710 /* Allocate memory for Device config params */
6711 adev->device_cfg_params = (struct audio_device_config_param*)
6712 calloc(platform_get_max_codec_backend(),
6713 sizeof(struct audio_device_config_param));
6714 if (adev->device_cfg_params == NULL)
6715 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306716
Eric Laurent994a6932013-07-17 11:51:42 -07006717 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006718 return 0;
6719}
6720
6721static struct hw_module_methods_t hal_module_methods = {
6722 .open = adev_open,
6723};
6724
6725struct audio_module HAL_MODULE_INFO_SYM = {
6726 .common = {
6727 .tag = HARDWARE_MODULE_TAG,
6728 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6729 .hal_api_version = HARDWARE_HAL_API_VERSION,
6730 .id = AUDIO_HARDWARE_MODULE_ID,
6731 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08006732 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006733 .methods = &hal_module_methods,
6734 },
6735};