blob: 70ce0dc3c7bac2f08fcea202b2c5c6aa19acdd8e [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002 * Copyright (C) 2013-2014 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
18/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070019/*#define VERY_VERY_VERBOSE_LOGGING*/
20#ifdef VERY_VERY_VERBOSE_LOGGING
21#define ALOGVV ALOGV
22#else
23#define ALOGVV(a...) do { } while(0)
24#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080025
26#include <errno.h>
27#include <pthread.h>
28#include <stdint.h>
29#include <sys/time.h>
30#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080031#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070032#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070033#include <sys/resource.h>
34#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080035
36#include <cutils/log.h>
37#include <cutils/str_parms.h>
38#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070039#include <cutils/atomic.h>
40#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080041
Eric Laurentb23d5282013-05-14 15:27:20 -070042#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070043#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070044#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <audio_effects/effect_aec.h>
46#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080048#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include "platform_api.h"
50#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070051#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070053#include "sound/compress_params.h"
54
Marco Nelissen32093f52015-04-08 15:14:02 -070055#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070056// 2 buffers causes problems with high bitrate files
57#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058/* ToDo: Check and update a proper value in msec */
59#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
60#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
61
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070062#define PROXY_OPEN_RETRY_COUNT 100
63#define PROXY_OPEN_WAIT_TIME 20
64
vivek mehtadae44712015-07-27 14:13:18 -070065#define MIN_CHANNEL_COUNT 1
66#define DEFAULT_CHANNEL_COUNT 2
67
68#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
69#define XSTR(x) STR(x)
70#define STR(x) #x
71
Glenn Kasten4f993392014-05-14 07:30:48 -070072static unsigned int configured_low_latency_capture_period_size =
73 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
74
Andy Hung31aca912014-03-20 17:14:59 -070075/* This constant enables extended precision handling.
76 * TODO The flag is off until more testing is done.
77 */
78static const bool k_enable_extended_precision = false;
79
Eric Laurentb23d5282013-05-14 15:27:20 -070080struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -070081 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -070082 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
83 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
84 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
85 .format = PCM_FORMAT_S16_LE,
86 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
87 .stop_threshold = INT_MAX,
88 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
89};
90
91struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -070092 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -070093 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
94 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
95 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
96 .format = PCM_FORMAT_S16_LE,
97 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
98 .stop_threshold = INT_MAX,
99 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
100};
101
102struct pcm_config pcm_config_hdmi_multi = {
103 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
104 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
105 .period_size = HDMI_MULTI_PERIOD_SIZE,
106 .period_count = HDMI_MULTI_PERIOD_COUNT,
107 .format = PCM_FORMAT_S16_LE,
108 .start_threshold = 0,
109 .stop_threshold = INT_MAX,
110 .avail_min = 0,
111};
112
113struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700114 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700115 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
116 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700117 .stop_threshold = INT_MAX,
118 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700119};
120
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700121#define AFE_PROXY_CHANNEL_COUNT 2
122#define AFE_PROXY_SAMPLING_RATE 48000
123
124#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
125#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
126
127struct pcm_config pcm_config_afe_proxy_playback = {
128 .channels = AFE_PROXY_CHANNEL_COUNT,
129 .rate = AFE_PROXY_SAMPLING_RATE,
130 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
131 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
132 .format = PCM_FORMAT_S16_LE,
133 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
134 .stop_threshold = INT_MAX,
135 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
136};
137
138#define AFE_PROXY_RECORD_PERIOD_SIZE 768
139#define AFE_PROXY_RECORD_PERIOD_COUNT 4
140
141struct pcm_config pcm_config_afe_proxy_record = {
142 .channels = AFE_PROXY_CHANNEL_COUNT,
143 .rate = AFE_PROXY_SAMPLING_RATE,
144 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
145 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
146 .format = PCM_FORMAT_S16_LE,
147 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
148 .stop_threshold = INT_MAX,
149 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
150};
151
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700152const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700153 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
154 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
155 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700156 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700157 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700158 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700159
Eric Laurentb23d5282013-05-14 15:27:20 -0700160 [USECASE_AUDIO_RECORD] = "audio-record",
161 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700162
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800163 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
164 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700165
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700167 [USECASE_VOICE2_CALL] = "voice2-call",
168 [USECASE_VOLTE_CALL] = "volte-call",
169 [USECASE_QCHAT_CALL] = "qchat-call",
170 [USECASE_VOWLAN_CALL] = "vowlan-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700171
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700172 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
173 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
174
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700175 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
176 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700177};
178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800179
180#define STRING_TO_ENUM(string) { #string, string }
181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800182struct string_to_enum {
183 const char *name;
184 uint32_t value;
185};
186
187static const struct string_to_enum out_channels_name_to_enum_table[] = {
188 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
189 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
190 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
191};
192
Haynes Mathew George5191a852013-09-11 14:19:36 -0700193static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700194static struct audio_device *adev = NULL;
195static pthread_mutex_t adev_init_lock;
196static unsigned int audio_device_ref_count;
197
198__attribute__ ((visibility ("default")))
199bool audio_hw_send_gain_dep_calibration(int level) {
200 bool ret_val = false;
201 ALOGV("%s: enter ... ", __func__);
202
203 pthread_mutex_lock(&adev_init_lock);
204
205 if (adev != NULL && adev->platform != NULL) {
206 pthread_mutex_lock(&adev->lock);
207 ret_val = platform_send_gain_dep_cal(adev->platform, level);
208 pthread_mutex_unlock(&adev->lock);
209 } else {
210 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
211 }
212
213 pthread_mutex_unlock(&adev_init_lock);
214
215 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
216 return ret_val;
217}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700218
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700219static bool is_supported_format(audio_format_t format)
220{
Eric Laurent8251ac82014-07-23 11:00:25 -0700221 switch (format) {
222 case AUDIO_FORMAT_MP3:
223 case AUDIO_FORMAT_AAC_LC:
224 case AUDIO_FORMAT_AAC_HE_V1:
225 case AUDIO_FORMAT_AAC_HE_V2:
226 return true;
227 default:
228 break;
229 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700230 return false;
231}
232
233static int get_snd_codec_id(audio_format_t format)
234{
235 int id = 0;
236
Eric Laurent8251ac82014-07-23 11:00:25 -0700237 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700238 case AUDIO_FORMAT_MP3:
239 id = SND_AUDIOCODEC_MP3;
240 break;
241 case AUDIO_FORMAT_AAC:
242 id = SND_AUDIOCODEC_AAC;
243 break;
244 default:
245 ALOGE("%s: Unsupported audio format", __func__);
246 }
247
248 return id;
249}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800250
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800251int enable_audio_route(struct audio_device *adev,
252 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800253{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700254 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800255 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800256
257 if (usecase == NULL)
258 return -EINVAL;
259
260 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
261
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800262 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700263 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800264 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700265 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800266
267 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500268 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Ravi Kumar Alamanda64026462014-09-15 00:08:58 -0700269 ALOGD("%s: apply and update mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700270 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800272 ALOGV("%s: exit", __func__);
273 return 0;
274}
275
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800276int disable_audio_route(struct audio_device *adev,
277 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700279 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800280 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800281
282 if (usecase == NULL)
283 return -EINVAL;
284
285 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700286 if (usecase->type == PCM_CAPTURE)
287 snd_device = usecase->in_snd_device;
288 else
289 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800290 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500291 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Ravi Kumar Alamanda64026462014-09-15 00:08:58 -0700292 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700293 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800295 ALOGV("%s: exit", __func__);
296 return 0;
297}
298
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800299int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700300 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800301{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700302 int i, num_devices = 0;
303 snd_device_t new_snd_devices[2];
304
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800305 if (snd_device < SND_DEVICE_MIN ||
306 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800307 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800308 return -EINVAL;
309 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700310
311 adev->snd_dev_ref_cnt[snd_device]++;
312 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700313 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700314 __func__, snd_device, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700315 return 0;
316 }
317
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700318 /* due to the possibility of calibration overwrite between listen
319 and audio, notify sound trigger hal before audio calibration is sent */
320 audio_extn_sound_trigger_update_device_status(snd_device,
321 ST_EVENT_SND_DEVICE_BUSY);
322
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700323 if (audio_extn_spkr_prot_is_enabled())
324 audio_extn_spkr_prot_calib_cancel(adev);
325
Eric Laurentb23d5282013-05-14 15:27:20 -0700326 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700327 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700328 audio_extn_sound_trigger_update_device_status(snd_device,
329 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800330 return -EINVAL;
331 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800332
zhaoyang yin4211fad2015-06-04 21:13:25 +0800333 audio_extn_dsm_feedback_enable(adev, snd_device, true);
334
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700335 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
336 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
337 audio_extn_spkr_prot_is_enabled()) {
338 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
339 adev->snd_dev_ref_cnt[snd_device]--;
340 return -EINVAL;
341 }
342 if (audio_extn_spkr_prot_start_processing(snd_device)) {
343 ALOGE("%s: spkr_start_processing failed", __func__);
344 return -EINVAL;
345 }
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700346 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
347 for (i = 0; i < num_devices; i++) {
348 enable_snd_device(adev, new_snd_devices[i]);
349 }
vivek mehtab6506412015-08-07 16:55:17 -0700350 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700351 } else {
352 const char * dev_path = platform_get_snd_device_name(snd_device);
353 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, dev_path);
354 audio_route_apply_and_update_path(adev->audio_route, dev_path);
355 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800357 return 0;
358}
359
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800360int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700361 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800362{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700363 int i, num_devices = 0;
364 snd_device_t new_snd_devices[2];
365
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800366 if (snd_device < SND_DEVICE_MIN ||
367 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800368 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800369 return -EINVAL;
370 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700371 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
372 ALOGE("%s: device ref cnt is already 0", __func__);
373 return -EINVAL;
374 }
375 adev->snd_dev_ref_cnt[snd_device]--;
376 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700377 const char * dev_path = platform_get_snd_device_name(snd_device);
Ravi Kumar Alamanda64026462014-09-15 00:08:58 -0700378 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, dev_path);
zhaoyang yin4211fad2015-06-04 21:13:25 +0800379
380 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700381 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
382 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
383 audio_extn_spkr_prot_is_enabled()) {
384 audio_extn_spkr_prot_stop_processing(snd_device);
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700385 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
386 for (i = 0; i < num_devices; i++) {
387 disable_snd_device(adev, new_snd_devices[i]);
388 }
vivek mehtab6506412015-08-07 16:55:17 -0700389 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700390 } else {
391 audio_route_reset_and_update_path(adev->audio_route, dev_path);
392 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700393 audio_extn_sound_trigger_update_device_status(snd_device,
394 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700395 }
vivek mehtab6506412015-08-07 16:55:17 -0700396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800397 return 0;
398}
399
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700400static void check_and_route_playback_usecases(struct audio_device *adev,
401 struct audio_usecase *uc_info,
402 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700403{
404 struct listnode *node;
405 struct audio_usecase *usecase;
406 bool switch_device[AUDIO_USECASE_MAX];
407 int i, num_uc_to_switch = 0;
408
409 /*
410 * This function is to make sure that all the usecases that are active on
411 * the hardware codec backend are always routed to any one device that is
412 * handled by the hardware codec.
413 * For example, if low-latency and deep-buffer usecases are currently active
414 * on speaker and out_set_parameters(headset) is received on low-latency
415 * output, then we have to make sure deep-buffer is also switched to headset,
416 * because of the limitation that both the devices cannot be enabled
417 * at the same time as they share the same backend.
418 */
419 /* Disable all the usecases on the shared backend other than the
420 specified usecase */
421 for (i = 0; i < AUDIO_USECASE_MAX; i++)
422 switch_device[i] = false;
423
424 list_for_each(node, &adev->usecase_list) {
425 usecase = node_to_item(node, struct audio_usecase, list);
426 if (usecase->type != PCM_CAPTURE &&
427 usecase != uc_info &&
428 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700429 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
430 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700431 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
432 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700433 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700434 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700435 switch_device[usecase->id] = true;
436 num_uc_to_switch++;
437 }
438 }
439
440 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 list_for_each(node, &adev->usecase_list) {
442 usecase = node_to_item(node, struct audio_usecase, list);
443 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700444 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900445 }
446 }
447
448 list_for_each(node, &adev->usecase_list) {
449 usecase = node_to_item(node, struct audio_usecase, list);
450 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700451 enable_snd_device(adev, snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700452 }
453 }
454
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700455 /* Re-route all the usecases on the shared backend other than the
456 specified usecase to new snd devices */
457 list_for_each(node, &adev->usecase_list) {
458 usecase = node_to_item(node, struct audio_usecase, list);
459 /* Update the out_snd_device only before enabling the audio route */
460 if (switch_device[usecase->id] ) {
461 usecase->out_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700462 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700463 }
464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700465 }
466}
467
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700468static void check_and_route_capture_usecases(struct audio_device *adev,
469 struct audio_usecase *uc_info,
470 snd_device_t snd_device)
471{
472 struct listnode *node;
473 struct audio_usecase *usecase;
474 bool switch_device[AUDIO_USECASE_MAX];
475 int i, num_uc_to_switch = 0;
476
477 /*
478 * This function is to make sure that all the active capture usecases
479 * are always routed to the same input sound device.
480 * For example, if audio-record and voice-call usecases are currently
481 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
482 * is received for voice call then we have to make sure that audio-record
483 * usecase is also switched to earpiece i.e. voice-dmic-ef,
484 * because of the limitation that two devices cannot be enabled
485 * at the same time if they share the same backend.
486 */
487 for (i = 0; i < AUDIO_USECASE_MAX; i++)
488 switch_device[i] = false;
489
490 list_for_each(node, &adev->usecase_list) {
491 usecase = node_to_item(node, struct audio_usecase, list);
492 if (usecase->type != PCM_PLAYBACK &&
493 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700494 usecase->in_snd_device != snd_device &&
495 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700496 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
497 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700498 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700499 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700500 switch_device[usecase->id] = true;
501 num_uc_to_switch++;
502 }
503 }
504
505 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700506 list_for_each(node, &adev->usecase_list) {
507 usecase = node_to_item(node, struct audio_usecase, list);
508 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700509 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700510 }
511 }
512
513 list_for_each(node, &adev->usecase_list) {
514 usecase = node_to_item(node, struct audio_usecase, list);
515 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700516 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700517 }
518 }
519
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700520 /* Re-route all the usecases on the shared backend other than the
521 specified usecase to new snd devices */
522 list_for_each(node, &adev->usecase_list) {
523 usecase = node_to_item(node, struct audio_usecase, list);
524 /* Update the in_snd_device only before enabling the audio route */
525 if (switch_device[usecase->id] ) {
526 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700527 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700528 }
529 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700530 }
531}
532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800533/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700534static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800535{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700536 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700537 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800538
539 switch (channels) {
540 /*
541 * Do not handle stereo output in Multi-channel cases
542 * Stereo case is handled in normal playback path
543 */
544 case 6:
545 ALOGV("%s: HDMI supports 5.1", __func__);
546 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
547 break;
548 case 8:
549 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
550 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
551 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
552 break;
553 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700554 ALOGE("HDMI does not support multi channel playback");
555 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800556 break;
557 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700558 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800559}
560
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700561static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
562{
563 struct audio_usecase *usecase;
564 struct listnode *node;
565
566 list_for_each(node, &adev->usecase_list) {
567 usecase = node_to_item(node, struct audio_usecase, list);
568 if (usecase->type == VOICE_CALL) {
569 ALOGV("%s: usecase id %d", __func__, usecase->id);
570 return usecase->id;
571 }
572 }
573 return USECASE_INVALID;
574}
575
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800576struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
577 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700578{
579 struct audio_usecase *usecase;
580 struct listnode *node;
581
582 list_for_each(node, &adev->usecase_list) {
583 usecase = node_to_item(node, struct audio_usecase, list);
584 if (usecase->id == uc_id)
585 return usecase;
586 }
587 return NULL;
588}
589
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800590int select_devices(struct audio_device *adev,
591 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800592{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800593 snd_device_t out_snd_device = SND_DEVICE_NONE;
594 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 struct audio_usecase *usecase = NULL;
596 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800597 struct audio_usecase *hfp_usecase = NULL;
598 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800599 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800601
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700602 usecase = get_usecase_from_list(adev, uc_id);
603 if (usecase == NULL) {
604 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
605 return -EINVAL;
606 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800607
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800608 if ((usecase->type == VOICE_CALL) ||
609 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700610 out_snd_device = platform_get_output_snd_device(adev->platform,
611 usecase->stream.out->devices);
612 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613 usecase->devices = usecase->stream.out->devices;
614 } else {
615 /*
616 * If the voice call is active, use the sound devices of voice call usecase
617 * so that it would not result any device switch. All the usecases will
618 * be switched to new device when select_devices() is called for voice call
619 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700620 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700621 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700622 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700623 vc_usecase = get_usecase_from_list(adev,
624 get_voice_usecase_id_from_list(adev));
625 if ((vc_usecase != NULL) &&
626 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
627 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700628 in_snd_device = vc_usecase->in_snd_device;
629 out_snd_device = vc_usecase->out_snd_device;
630 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800631 } else if (audio_extn_hfp_is_active(adev)) {
632 hfp_ucid = audio_extn_hfp_get_usecase();
633 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
634 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
635 in_snd_device = hfp_usecase->in_snd_device;
636 out_snd_device = hfp_usecase->out_snd_device;
637 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700638 }
639 if (usecase->type == PCM_PLAYBACK) {
640 usecase->devices = usecase->stream.out->devices;
641 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700642 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700643 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700644 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700645 if (usecase->stream.out == adev->primary_output &&
646 adev->active_input &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800647 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
648 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700649 select_devices(adev, adev->active_input->usecase);
650 }
651 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700652 } else if (usecase->type == PCM_CAPTURE) {
653 usecase->devices = usecase->stream.in->device;
654 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700655 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700656 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700657 if (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
658 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700659 out_device = adev->primary_output->devices;
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800660 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700661 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
662 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700663 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700664 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700665 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700666 }
667 }
668
669 if (out_snd_device == usecase->out_snd_device &&
670 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671 return 0;
672 }
673
sangwoobc677242013-08-08 16:53:43 +0900674 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700675 out_snd_device, platform_get_snd_device_name(out_snd_device),
676 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800678 /*
679 * Limitation: While in call, to do a device switch we need to disable
680 * and enable both RX and TX devices though one of them is same as current
681 * device.
682 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700683 if ((usecase->type == VOICE_CALL) &&
684 (usecase->in_snd_device != SND_DEVICE_NONE) &&
685 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700686 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -0700687 /* Disable sidetone only if voice call already exists */
688 if (voice_is_call_state_active(adev))
689 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800690 }
691
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700692 /* Disable current sound devices */
693 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700694 disable_audio_route(adev, usecase);
695 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800696 }
697
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700698 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700699 disable_audio_route(adev, usecase);
700 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800701 }
702
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700703 /* Applicable only on the targets that has external modem.
704 * New device information should be sent to modem before enabling
705 * the devices to reduce in-call device switch time.
706 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700707 if ((usecase->type == VOICE_CALL) &&
708 (usecase->in_snd_device != SND_DEVICE_NONE) &&
709 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700710 status = platform_switch_voice_call_enable_device_config(adev->platform,
711 out_snd_device,
712 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700713 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700714
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 /* Enable new sound devices */
716 if (out_snd_device != SND_DEVICE_NONE) {
717 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700718 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700719 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800720 }
721
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700722 if (in_snd_device != SND_DEVICE_NONE) {
723 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700724 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700725 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700726
Eric Laurentb23d5282013-05-14 15:27:20 -0700727 if (usecase->type == VOICE_CALL)
728 status = platform_switch_voice_call_device_post(adev->platform,
729 out_snd_device,
730 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800731
sangwoo170731f2013-06-08 15:36:36 +0900732 usecase->in_snd_device = in_snd_device;
733 usecase->out_snd_device = out_snd_device;
734
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700735 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900736
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700737 /* Applicable only on the targets that has external modem.
738 * Enable device command should be sent to modem only after
739 * enabling voice call mixer controls
740 */
vivek mehta765eb642015-08-07 19:46:06 -0700741 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700742 status = platform_switch_voice_call_usecase_route_post(adev->platform,
743 out_snd_device,
744 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -0700745 /* Enable sidetone only if voice call already exists */
746 if (voice_is_call_state_active(adev))
747 voice_set_sidetone(adev, out_snd_device, true);
748 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800750 return status;
751}
752
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800753static int stop_input_stream(struct stream_in *in)
754{
755 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800756 struct audio_usecase *uc_info;
757 struct audio_device *adev = in->dev;
758
Eric Laurentc8400632013-02-14 19:04:54 -0800759 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760
Eric Laurent994a6932013-07-17 11:51:42 -0700761 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700762 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800763 uc_info = get_usecase_from_list(adev, in->usecase);
764 if (uc_info == NULL) {
765 ALOGE("%s: Could not find the usecase (%d) in the list",
766 __func__, in->usecase);
767 return -EINVAL;
768 }
769
Eric Laurent150dbfe2013-02-27 14:31:02 -0800770 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700771 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700772
773 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700774 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800776 list_remove(&uc_info->list);
777 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800778
Eric Laurent994a6932013-07-17 11:51:42 -0700779 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800780 return ret;
781}
782
783int start_input_stream(struct stream_in *in)
784{
785 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800786 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800787 struct audio_usecase *uc_info;
788 struct audio_device *adev = in->dev;
789
Eric Laurent994a6932013-07-17 11:51:42 -0700790 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Eric Laurentb23d5282013-05-14 15:27:20 -0700791 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800792 if (in->pcm_device_id < 0) {
793 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
794 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800795 ret = -EINVAL;
796 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800797 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700798
799 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800800 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
801 uc_info->id = in->usecase;
802 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800803 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700804 uc_info->devices = in->device;
805 uc_info->in_snd_device = SND_DEVICE_NONE;
806 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800808 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700809 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810
Eric Laurentc8400632013-02-14 19:04:54 -0800811 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700812 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700813
814 unsigned int flags = PCM_IN;
815 unsigned int pcm_open_retry_count = 0;
816
817 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
818 flags |= PCM_MMAP | PCM_NOIRQ;
819 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800820 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700821
822 while (1) {
823 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
824 flags, &in->config);
825 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
826 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
827 if (in->pcm != NULL) {
828 pcm_close(in->pcm);
829 in->pcm = NULL;
830 }
831 if (pcm_open_retry_count-- == 0) {
832 ret = -EIO;
833 goto error_open;
834 }
835 usleep(PROXY_OPEN_WAIT_TIME * 1000);
836 continue;
837 }
838 break;
839 }
840
Haynes Mathew George88e6fb22015-08-19 11:51:34 -0700841 ALOGV("%s: pcm_prepare start", __func__);
842 pcm_prepare(in->pcm);
Eric Laurent994a6932013-07-17 11:51:42 -0700843 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -0700844
Eric Laurentc8400632013-02-14 19:04:54 -0800845 return ret;
846
847error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800848 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -0800849
850error_config:
851 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700852 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -0800853
854 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800855}
856
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700857/* must be called with out->lock locked */
858static int send_offload_cmd_l(struct stream_out* out, int command)
859{
860 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
861
862 ALOGVV("%s %d", __func__, command);
863
864 cmd->cmd = command;
865 list_add_tail(&out->offload_cmd_list, &cmd->node);
866 pthread_cond_signal(&out->offload_cond);
867 return 0;
868}
869
870/* must be called iwth out->lock locked */
871static void stop_compressed_output_l(struct stream_out *out)
872{
873 out->offload_state = OFFLOAD_STATE_IDLE;
874 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -0700875 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700876 if (out->compr != NULL) {
877 compress_stop(out->compr);
878 while (out->offload_thread_blocked) {
879 pthread_cond_wait(&out->cond, &out->lock);
880 }
881 }
882}
883
884static void *offload_thread_loop(void *context)
885{
886 struct stream_out *out = (struct stream_out *) context;
887 struct listnode *item;
888
889 out->offload_state = OFFLOAD_STATE_IDLE;
890 out->playback_started = 0;
891
892 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
893 set_sched_policy(0, SP_FOREGROUND);
894 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
895
896 ALOGV("%s", __func__);
Eric Laurent6010f702015-06-25 23:39:33 +0000897 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700898 for (;;) {
899 struct offload_cmd *cmd = NULL;
900 stream_callback_event_t event;
901 bool send_callback = false;
902
903 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
904 __func__, list_empty(&out->offload_cmd_list),
905 out->offload_state);
906 if (list_empty(&out->offload_cmd_list)) {
907 ALOGV("%s SLEEPING", __func__);
908 pthread_cond_wait(&out->offload_cond, &out->lock);
909 ALOGV("%s RUNNING", __func__);
910 continue;
911 }
912
913 item = list_head(&out->offload_cmd_list);
914 cmd = node_to_item(item, struct offload_cmd, node);
915 list_remove(item);
916
917 ALOGVV("%s STATE %d CMD %d out->compr %p",
918 __func__, out->offload_state, cmd->cmd, out->compr);
919
920 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
921 free(cmd);
922 break;
923 }
924
925 if (out->compr == NULL) {
926 ALOGE("%s: Compress handle is NULL", __func__);
927 pthread_cond_signal(&out->cond);
928 continue;
929 }
930 out->offload_thread_blocked = true;
931 pthread_mutex_unlock(&out->lock);
932 send_callback = false;
933 switch(cmd->cmd) {
934 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
935 compress_wait(out->compr, -1);
936 send_callback = true;
937 event = STREAM_CBK_EVENT_WRITE_READY;
938 break;
939 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -0700940 compress_next_track(out->compr);
941 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700942 send_callback = true;
943 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -0800944 /* Resend the metadata for next iteration */
945 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700946 break;
947 case OFFLOAD_CMD_DRAIN:
948 compress_drain(out->compr);
949 send_callback = true;
950 event = STREAM_CBK_EVENT_DRAIN_READY;
951 break;
952 default:
953 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
954 break;
955 }
Eric Laurent6010f702015-06-25 23:39:33 +0000956 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700957 out->offload_thread_blocked = false;
958 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -0700959 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -0800960 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700961 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -0700962 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700963 free(cmd);
964 }
965
966 pthread_cond_signal(&out->cond);
967 while (!list_empty(&out->offload_cmd_list)) {
968 item = list_head(&out->offload_cmd_list);
969 list_remove(item);
970 free(node_to_item(item, struct offload_cmd, node));
971 }
972 pthread_mutex_unlock(&out->lock);
973
974 return NULL;
975}
976
977static int create_offload_callback_thread(struct stream_out *out)
978{
979 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
980 list_init(&out->offload_cmd_list);
981 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
982 offload_thread_loop, out);
983 return 0;
984}
985
986static int destroy_offload_callback_thread(struct stream_out *out)
987{
Eric Laurent6010f702015-06-25 23:39:33 +0000988 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700989 stop_compressed_output_l(out);
990 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
991
992 pthread_mutex_unlock(&out->lock);
993 pthread_join(out->offload_thread, (void **) NULL);
994 pthread_cond_destroy(&out->offload_cond);
995
996 return 0;
997}
998
Eric Laurent07eeafd2013-10-06 12:52:49 -0700999static bool allow_hdmi_channel_config(struct audio_device *adev)
1000{
1001 struct listnode *node;
1002 struct audio_usecase *usecase;
1003 bool ret = true;
1004
1005 list_for_each(node, &adev->usecase_list) {
1006 usecase = node_to_item(node, struct audio_usecase, list);
1007 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1008 /*
1009 * If voice call is already existing, do not proceed further to avoid
1010 * disabling/enabling both RX and TX devices, CSD calls, etc.
1011 * Once the voice call done, the HDMI channels can be configured to
1012 * max channels of remaining use cases.
1013 */
1014 if (usecase->id == USECASE_VOICE_CALL) {
1015 ALOGD("%s: voice call is active, no change in HDMI channels",
1016 __func__);
1017 ret = false;
1018 break;
1019 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1020 ALOGD("%s: multi channel playback is active, "
1021 "no change in HDMI channels", __func__);
1022 ret = false;
1023 break;
1024 }
1025 }
1026 }
1027 return ret;
1028}
1029
1030static int check_and_set_hdmi_channels(struct audio_device *adev,
1031 unsigned int channels)
1032{
1033 struct listnode *node;
1034 struct audio_usecase *usecase;
1035
1036 /* Check if change in HDMI channel config is allowed */
1037 if (!allow_hdmi_channel_config(adev))
1038 return 0;
1039
1040 if (channels == adev->cur_hdmi_channels) {
1041 ALOGD("%s: Requested channels are same as current", __func__);
1042 return 0;
1043 }
1044
1045 platform_set_hdmi_channels(adev->platform, channels);
1046 adev->cur_hdmi_channels = channels;
1047
1048 /*
1049 * Deroute all the playback streams routed to HDMI so that
1050 * the back end is deactivated. Note that backend will not
1051 * be deactivated if any one stream is connected to it.
1052 */
1053 list_for_each(node, &adev->usecase_list) {
1054 usecase = node_to_item(node, struct audio_usecase, list);
1055 if (usecase->type == PCM_PLAYBACK &&
1056 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001057 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001058 }
1059 }
1060
1061 /*
1062 * Enable all the streams disabled above. Now the HDMI backend
1063 * will be activated with new channel configuration
1064 */
1065 list_for_each(node, &adev->usecase_list) {
1066 usecase = node_to_item(node, struct audio_usecase, list);
1067 if (usecase->type == PCM_PLAYBACK &&
1068 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001069 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001070 }
1071 }
1072
1073 return 0;
1074}
1075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001076static int stop_output_stream(struct stream_out *out)
1077{
1078 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001079 struct audio_usecase *uc_info;
1080 struct audio_device *adev = out->dev;
1081
Eric Laurent994a6932013-07-17 11:51:42 -07001082 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001083 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084 uc_info = get_usecase_from_list(adev, out->usecase);
1085 if (uc_info == NULL) {
1086 ALOGE("%s: Could not find the usecase (%d) in the list",
1087 __func__, out->usecase);
1088 return -EINVAL;
1089 }
1090
Haynes Mathew George41f86652014-06-17 14:22:15 -07001091 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1092 if (adev->visualizer_stop_output != NULL)
1093 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1094 if (adev->offload_effects_stop_output != NULL)
1095 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1096 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001097
Eric Laurent150dbfe2013-02-27 14:31:02 -08001098 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001099 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100
1101 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001102 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001103
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001104 list_remove(&uc_info->list);
1105 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001106
Eric Laurent0499d4f2014-08-25 22:39:29 -05001107 audio_extn_extspk_update(adev->extspk);
1108
Eric Laurent07eeafd2013-10-06 12:52:49 -07001109 /* Must be called after removing the usecase from list */
1110 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1111 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1112
Eric Laurent994a6932013-07-17 11:51:42 -07001113 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114 return ret;
1115}
1116
1117int start_output_stream(struct stream_out *out)
1118{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001119 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120 struct audio_usecase *uc_info;
1121 struct audio_device *adev = out->dev;
1122
Eric Laurent994a6932013-07-17 11:51:42 -07001123 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001125 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126 if (out->pcm_device_id < 0) {
1127 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1128 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001129 ret = -EINVAL;
1130 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131 }
1132
1133 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1134 uc_info->id = out->usecase;
1135 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001136 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 uc_info->devices = out->devices;
1138 uc_info->in_snd_device = SND_DEVICE_NONE;
1139 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140
Eric Laurent07eeafd2013-10-06 12:52:49 -07001141 /* This must be called before adding this usecase to the list */
1142 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1143 check_and_set_hdmi_channels(adev, out->config.channels);
1144
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001145 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001147 select_devices(adev, out->usecase);
1148
Eric Laurent0499d4f2014-08-25 22:39:29 -05001149 audio_extn_extspk_update(adev->extspk);
1150
Andy Hung31aca912014-03-20 17:14:59 -07001151 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001152 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001153 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001154 unsigned int flags = PCM_OUT;
1155 unsigned int pcm_open_retry_count = 0;
1156 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1157 flags |= PCM_MMAP | PCM_NOIRQ;
1158 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1159 } else
1160 flags |= PCM_MONOTONIC;
1161
1162 while (1) {
1163 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1164 flags, &out->config);
1165 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1166 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1167 if (out->pcm != NULL) {
1168 pcm_close(out->pcm);
1169 out->pcm = NULL;
1170 }
1171 if (pcm_open_retry_count-- == 0) {
1172 ret = -EIO;
1173 goto error_open;
1174 }
1175 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1176 continue;
1177 }
1178 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001179 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001180 ALOGV("%s: pcm_prepare start", __func__);
1181 if (pcm_is_ready(out->pcm))
1182 pcm_prepare(out->pcm);
1183
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001184 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001185 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001186 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001187 COMPRESS_IN, &out->compr_config);
1188 if (out->compr && !is_compress_ready(out->compr)) {
1189 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1190 compress_close(out->compr);
1191 out->compr = NULL;
1192 ret = -EIO;
1193 goto error_open;
1194 }
1195 if (out->offload_callback)
1196 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001197
1198 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001199 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1200 if (adev->offload_effects_start_output != NULL)
1201 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001202 }
Eric Laurent994a6932013-07-17 11:51:42 -07001203 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001205error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001206 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001207error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001208 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209}
1210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001211static int check_input_parameters(uint32_t sample_rate,
1212 audio_format_t format,
1213 int channel_count)
1214{
vivek mehtadae44712015-07-27 14:13:18 -07001215 if (format != AUDIO_FORMAT_PCM_16_BIT) {
1216 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1217 return -EINVAL;
1218 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001219
vivek mehtadae44712015-07-27 14:13:18 -07001220 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
1221 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d\%d)", __func__,
1222 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1223 return -EINVAL;
1224 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225
1226 switch (sample_rate) {
1227 case 8000:
1228 case 11025:
1229 case 12000:
1230 case 16000:
1231 case 22050:
1232 case 24000:
1233 case 32000:
1234 case 44100:
1235 case 48000:
1236 break;
1237 default:
vivek mehtadae44712015-07-27 14:13:18 -07001238 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001239 return -EINVAL;
1240 }
1241
1242 return 0;
1243}
1244
1245static size_t get_input_buffer_size(uint32_t sample_rate,
1246 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001247 int channel_count,
1248 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249{
1250 size_t size = 0;
1251
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001252 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1253 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001254
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001255 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001256 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001257 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001258 /* ToDo: should use frame_size computed based on the format and
1259 channel_count here. */
1260 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261
Glenn Kasten4f993392014-05-14 07:30:48 -07001262 /* make sure the size is multiple of 32 bytes
1263 * At 48 kHz mono 16-bit PCM:
1264 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1265 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1266 */
1267 size += 0x1f;
1268 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001269
1270 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271}
1272
1273static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1274{
1275 struct stream_out *out = (struct stream_out *)stream;
1276
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001277 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278}
1279
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001280static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281{
1282 return -ENOSYS;
1283}
1284
1285static size_t out_get_buffer_size(const struct audio_stream *stream)
1286{
1287 struct stream_out *out = (struct stream_out *)stream;
1288
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001289 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1290 return out->compr_config.fragment_size;
1291 }
Eric Laurentfdf296a2014-07-03 16:41:51 -07001292 return out->config.period_size *
1293 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001294}
1295
1296static uint32_t out_get_channels(const struct audio_stream *stream)
1297{
1298 struct stream_out *out = (struct stream_out *)stream;
1299
1300 return out->channel_mask;
1301}
1302
1303static audio_format_t out_get_format(const struct audio_stream *stream)
1304{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001305 struct stream_out *out = (struct stream_out *)stream;
1306
1307 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001308}
1309
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001310static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001311{
1312 return -ENOSYS;
1313}
1314
1315static int out_standby(struct audio_stream *stream)
1316{
1317 struct stream_out *out = (struct stream_out *)stream;
1318 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001319
Eric Laurent994a6932013-07-17 11:51:42 -07001320 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001321 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001322
Eric Laurent6010f702015-06-25 23:39:33 +00001323 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001324 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001325 if (adev->adm_deregister_stream)
1326 adev->adm_deregister_stream(adev->adm_data, out->handle);
1327
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001328 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001329 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001330 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1331 if (out->pcm) {
1332 pcm_close(out->pcm);
1333 out->pcm = NULL;
1334 }
1335 } else {
1336 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001337 out->gapless_mdata.encoder_delay = 0;
1338 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001339 if (out->compr != NULL) {
1340 compress_close(out->compr);
1341 out->compr = NULL;
1342 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001343 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001345 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001346 }
1347 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001348 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001349 return 0;
1350}
1351
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001352static int out_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001353{
1354 return 0;
1355}
1356
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001357static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1358{
1359 int ret = 0;
1360 char value[32];
1361 struct compr_gapless_mdata tmp_mdata;
1362
1363 if (!out || !parms) {
1364 return -EINVAL;
1365 }
1366
1367 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1368 if (ret >= 0) {
1369 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1370 } else {
1371 return -EINVAL;
1372 }
1373
1374 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1375 if (ret >= 0) {
1376 tmp_mdata.encoder_padding = atoi(value);
1377 } else {
1378 return -EINVAL;
1379 }
1380
1381 out->gapless_mdata = tmp_mdata;
1382 out->send_new_metadata = 1;
1383 ALOGV("%s new encoder delay %u and padding %u", __func__,
1384 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1385
1386 return 0;
1387}
1388
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001389static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1390{
1391 return out == adev->primary_output || out == adev->voice_tx_output;
1392}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001394static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1395{
1396 struct stream_out *out = (struct stream_out *)stream;
1397 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001398 struct audio_usecase *usecase;
1399 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001400 struct str_parms *parms;
1401 char value[32];
1402 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001403 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001404 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001405
sangwoobc677242013-08-08 16:53:43 +09001406 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001407 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001408 parms = str_parms_create_str(kvpairs);
1409 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1410 if (ret >= 0) {
1411 val = atoi(value);
Eric Laurent6010f702015-06-25 23:39:33 +00001412 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001413 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001414
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001415 /*
1416 * When HDMI cable is unplugged the music playback is paused and
1417 * the policy manager sends routing=0. But the audioflinger
1418 * continues to write data until standby time (3sec).
1419 * As the HDMI core is turned off, the write gets blocked.
1420 * Avoid this by routing audio to speaker until standby.
1421 */
1422 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1423 val == AUDIO_DEVICE_NONE) {
1424 val = AUDIO_DEVICE_OUT_SPEAKER;
1425 }
1426
1427 /*
1428 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001429 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001430 * the select_devices(). But how do we undo this?
1431 *
1432 * For example, music playback is active on headset (deep-buffer usecase)
1433 * and if we go to ringtones and select a ringtone, low-latency usecase
1434 * will be started on headset+speaker. As we can't enable headset+speaker
1435 * and headset devices at the same time, select_devices() switches the music
1436 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1437 * So when the ringtone playback is completed, how do we undo the same?
1438 *
1439 * We are relying on the out_set_parameters() call on deep-buffer output,
1440 * once the ringtone playback is ended.
1441 * NOTE: We should not check if the current devices are same as new devices.
1442 * Because select_devices() must be called to switch back the music
1443 * playback to headset.
1444 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001445 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001446 out->devices = val;
1447
1448 if (!out->standby)
1449 select_devices(adev, out->usecase);
1450
Eric Laurenta7657192014-10-09 21:09:33 -07001451 if (output_drives_call(adev, out)) {
1452 if (!voice_is_in_call(adev)) {
1453 if (adev->mode == AUDIO_MODE_IN_CALL) {
1454 adev->current_call_output = out;
1455 ret = voice_start_call(adev);
1456 }
1457 } else {
1458 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001459 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07001460 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001461 }
1462 }
1463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001465 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05001466
1467 /*handles device and call state changes*/
1468 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001470
1471 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1472 parse_compress_metadata(out, parms);
1473 }
1474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07001476 ALOGV("%s: exit: code(%d)", __func__, status);
1477 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478}
1479
1480static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1481{
1482 struct stream_out *out = (struct stream_out *)stream;
1483 struct str_parms *query = str_parms_create_str(keys);
1484 char *str;
1485 char value[256];
1486 struct str_parms *reply = str_parms_create();
1487 size_t i, j;
1488 int ret;
1489 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07001490 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1492 if (ret >= 0) {
1493 value[0] = '\0';
1494 i = 0;
1495 while (out->supported_channel_masks[i] != 0) {
1496 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1497 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1498 if (!first) {
1499 strcat(value, "|");
1500 }
1501 strcat(value, out_channels_name_to_enum_table[j].name);
1502 first = false;
1503 break;
1504 }
1505 }
1506 i++;
1507 }
1508 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1509 str = str_parms_to_str(reply);
1510 } else {
1511 str = strdup(keys);
1512 }
1513 str_parms_destroy(query);
1514 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001515 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001516 return str;
1517}
1518
1519static uint32_t out_get_latency(const struct audio_stream_out *stream)
1520{
1521 struct stream_out *out = (struct stream_out *)stream;
1522
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001523 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
1524 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
1525
1526 return (out->config.period_count * out->config.period_size * 1000) /
1527 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528}
1529
1530static int out_set_volume(struct audio_stream_out *stream, float left,
1531 float right)
1532{
Eric Laurenta9024de2013-04-04 09:19:12 -07001533 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001534 int volume[2];
1535
Eric Laurenta9024de2013-04-04 09:19:12 -07001536 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1537 /* only take left channel into account: the API is for stereo anyway */
1538 out->muted = (left == 0.0f);
1539 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001540 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1541 const char *mixer_ctl_name = "Compress Playback Volume";
1542 struct audio_device *adev = out->dev;
1543 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001544 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1545 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07001546 /* try with the control based on device id */
1547 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
1548 PCM_PLAYBACK);
1549 char ctl_name[128] = {0};
1550 snprintf(ctl_name, sizeof(ctl_name),
1551 "Compress Playback %d Volume", pcm_device_id);
1552 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
1553 if (!ctl) {
1554 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
1555 return -EINVAL;
1556 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001557 }
1558 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
1559 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
1560 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
1561 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07001562 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001564 return -ENOSYS;
1565}
1566
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001567#ifdef NO_AUDIO_OUT
1568static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
1569 const void *buffer, size_t bytes)
1570{
1571 struct stream_out *out = (struct stream_out *)stream;
1572
1573 /* No Output device supported other than BT for playback.
1574 * Sleep for the amount of buffer duration
1575 */
Eric Laurent6010f702015-06-25 23:39:33 +00001576 pthread_mutex_lock(&out->lock);
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001577 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
1578 out_get_sample_rate(&out->stream.common));
1579 pthread_mutex_unlock(&out->lock);
1580 return bytes;
1581}
1582#endif
1583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1585 size_t bytes)
1586{
1587 struct stream_out *out = (struct stream_out *)stream;
1588 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07001589 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590
Eric Laurent6010f702015-06-25 23:39:33 +00001591 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001593 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001594 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001595 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001596 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001597 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001599 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600 goto exit;
1601 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001602 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
1603 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001606 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001607 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
1608 if (out->send_new_metadata) {
1609 ALOGVV("send new gapless metadata");
1610 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
1611 out->send_new_metadata = 0;
1612 }
1613
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001614 ret = compress_write(out->compr, buffer, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001615 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07001616 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001617 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
1618 }
1619 if (!out->playback_started) {
1620 compress_start(out->compr);
1621 out->playback_started = 1;
1622 out->offload_state = OFFLOAD_STATE_PLAYING;
1623 }
1624 pthread_mutex_unlock(&out->lock);
1625 return ret;
1626 } else {
1627 if (out->pcm) {
1628 if (out->muted)
1629 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001630
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001631 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001632 if (adev->adm_request_focus)
1633 adev->adm_request_focus(adev->adm_data, out->handle);
1634
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001635 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1636 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
1637 }
1638 else
1639 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001640
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001641 if (ret == 0)
1642 out->written += bytes / (out->config.channels * sizeof(short));
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001643
1644 if (adev->adm_abandon_focus)
1645 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647 }
1648
1649exit:
1650 pthread_mutex_unlock(&out->lock);
1651
1652 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001653 if (out->pcm)
vivek mehta1a9b7c02015-06-25 11:49:38 -07001654 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655 out_standby(&out->stream.common);
Eric Laurentfdf296a2014-07-03 16:41:51 -07001656 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657 out_get_sample_rate(&out->stream.common));
1658 }
1659 return bytes;
1660}
1661
1662static int out_get_render_position(const struct audio_stream_out *stream,
1663 uint32_t *dsp_frames)
1664{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001665 struct stream_out *out = (struct stream_out *)stream;
1666 *dsp_frames = 0;
1667 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurent6010f702015-06-25 23:39:33 +00001668 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001669 if (out->compr != NULL) {
1670 compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
1671 &out->sample_rate);
1672 ALOGVV("%s rendered frames %d sample_rate %d",
1673 __func__, *dsp_frames, out->sample_rate);
1674 }
1675 pthread_mutex_unlock(&out->lock);
1676 return 0;
1677 } else
1678 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679}
1680
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001681static int out_add_audio_effect(const struct audio_stream *stream __unused,
1682 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683{
1684 return 0;
1685}
1686
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001687static int out_remove_audio_effect(const struct audio_stream *stream __unused,
1688 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689{
1690 return 0;
1691}
1692
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001693static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
1694 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695{
1696 return -EINVAL;
1697}
1698
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001699static int out_get_presentation_position(const struct audio_stream_out *stream,
1700 uint64_t *frames, struct timespec *timestamp)
1701{
1702 struct stream_out *out = (struct stream_out *)stream;
1703 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07001704 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001705
Eric Laurent6010f702015-06-25 23:39:33 +00001706 pthread_mutex_lock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001707
Eric Laurent949a0892013-09-20 09:20:13 -07001708 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1709 if (out->compr != NULL) {
1710 compress_get_tstamp(out->compr, &dsp_frames,
1711 &out->sample_rate);
1712 ALOGVV("%s rendered frames %ld sample_rate %d",
1713 __func__, dsp_frames, out->sample_rate);
1714 *frames = dsp_frames;
1715 ret = 0;
1716 /* this is the best we can do */
1717 clock_gettime(CLOCK_MONOTONIC, timestamp);
1718 }
1719 } else {
1720 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07001721 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07001722 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
1723 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07001724 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07001725 // This adjustment accounts for buffering after app processor.
1726 // It is based on estimated DSP latency per use case, rather than exact.
1727 signed_frames -=
1728 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
1729
Eric Laurent949a0892013-09-20 09:20:13 -07001730 // It would be unusual for this value to be negative, but check just in case ...
1731 if (signed_frames >= 0) {
1732 *frames = signed_frames;
1733 ret = 0;
1734 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001735 }
1736 }
1737 }
1738
1739 pthread_mutex_unlock(&out->lock);
1740
1741 return ret;
1742}
1743
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001744static int out_set_callback(struct audio_stream_out *stream,
1745 stream_callback_t callback, void *cookie)
1746{
1747 struct stream_out *out = (struct stream_out *)stream;
1748
1749 ALOGV("%s", __func__);
Eric Laurent6010f702015-06-25 23:39:33 +00001750 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001751 out->offload_callback = callback;
1752 out->offload_cookie = cookie;
1753 pthread_mutex_unlock(&out->lock);
1754 return 0;
1755}
1756
1757static int out_pause(struct audio_stream_out* stream)
1758{
1759 struct stream_out *out = (struct stream_out *)stream;
1760 int status = -ENOSYS;
1761 ALOGV("%s", __func__);
1762 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent6010f702015-06-25 23:39:33 +00001763 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001764 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
1765 status = compress_pause(out->compr);
1766 out->offload_state = OFFLOAD_STATE_PAUSED;
1767 }
1768 pthread_mutex_unlock(&out->lock);
1769 }
1770 return status;
1771}
1772
1773static int out_resume(struct audio_stream_out* stream)
1774{
1775 struct stream_out *out = (struct stream_out *)stream;
1776 int status = -ENOSYS;
1777 ALOGV("%s", __func__);
1778 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1779 status = 0;
Eric Laurent6010f702015-06-25 23:39:33 +00001780 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001781 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
1782 status = compress_resume(out->compr);
1783 out->offload_state = OFFLOAD_STATE_PLAYING;
1784 }
1785 pthread_mutex_unlock(&out->lock);
1786 }
1787 return status;
1788}
1789
1790static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
1791{
1792 struct stream_out *out = (struct stream_out *)stream;
1793 int status = -ENOSYS;
1794 ALOGV("%s", __func__);
1795 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent6010f702015-06-25 23:39:33 +00001796 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001797 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
1798 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
1799 else
1800 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
1801 pthread_mutex_unlock(&out->lock);
1802 }
1803 return status;
1804}
1805
1806static int out_flush(struct audio_stream_out* stream)
1807{
1808 struct stream_out *out = (struct stream_out *)stream;
1809 ALOGV("%s", __func__);
1810 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent6010f702015-06-25 23:39:33 +00001811 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001812 stop_compressed_output_l(out);
1813 pthread_mutex_unlock(&out->lock);
1814 return 0;
1815 }
1816 return -ENOSYS;
1817}
1818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819/** audio_stream_in implementation **/
1820static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1821{
1822 struct stream_in *in = (struct stream_in *)stream;
1823
1824 return in->config.rate;
1825}
1826
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001827static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828{
1829 return -ENOSYS;
1830}
1831
1832static size_t in_get_buffer_size(const struct audio_stream *stream)
1833{
1834 struct stream_in *in = (struct stream_in *)stream;
1835
Eric Laurentfdf296a2014-07-03 16:41:51 -07001836 return in->config.period_size *
1837 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838}
1839
1840static uint32_t in_get_channels(const struct audio_stream *stream)
1841{
1842 struct stream_in *in = (struct stream_in *)stream;
1843
1844 return in->channel_mask;
1845}
1846
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001847static audio_format_t in_get_format(const struct audio_stream *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848{
1849 return AUDIO_FORMAT_PCM_16_BIT;
1850}
1851
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001852static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853{
1854 return -ENOSYS;
1855}
1856
1857static int in_standby(struct audio_stream *stream)
1858{
1859 struct stream_in *in = (struct stream_in *)stream;
1860 struct audio_device *adev = in->dev;
1861 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07001862 ALOGV("%s: enter", __func__);
Eric Laurent6010f702015-06-25 23:39:33 +00001863 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07001864
1865 if (!in->standby && in->is_st_session) {
1866 ALOGD("%s: sound trigger pcm stop lab", __func__);
1867 audio_extn_sound_trigger_stop_lab(in);
1868 in->standby = true;
1869 }
1870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001872 if (adev->adm_deregister_stream)
1873 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
1874
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001875 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001877 if (in->pcm) {
1878 pcm_close(in->pcm);
1879 in->pcm = NULL;
1880 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05001881 adev->enable_voicerx = false;
1882 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001884 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885 }
1886 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001887 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888 return status;
1889}
1890
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001891static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892{
1893 return 0;
1894}
1895
1896static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1897{
1898 struct stream_in *in = (struct stream_in *)stream;
1899 struct audio_device *adev = in->dev;
1900 struct str_parms *parms;
1901 char *str;
1902 char value[32];
1903 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07001904 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905
Eric Laurent994a6932013-07-17 11:51:42 -07001906 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001907 parms = str_parms_create_str(kvpairs);
1908
1909 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
1910
Eric Laurent6010f702015-06-25 23:39:33 +00001911 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001912 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913 if (ret >= 0) {
1914 val = atoi(value);
1915 /* no audio source uses val == 0 */
1916 if ((in->source != val) && (val != 0)) {
1917 in->source = val;
1918 }
1919 }
1920
1921 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07001922
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 if (ret >= 0) {
1924 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001925 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 in->device = val;
1927 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001928 if (!in->standby)
Eric Laurent03f09432014-03-25 18:09:11 -07001929 status = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930 }
1931 }
1932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001934 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001935
1936 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07001937 ALOGV("%s: exit: status(%d)", __func__, status);
1938 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001939}
1940
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001941static char* in_get_parameters(const struct audio_stream *stream __unused,
1942 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001943{
1944 return strdup("");
1945}
1946
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001947static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948{
1949 return 0;
1950}
1951
1952static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
1953 size_t bytes)
1954{
1955 struct stream_in *in = (struct stream_in *)stream;
1956 struct audio_device *adev = in->dev;
1957 int i, ret = -1;
1958
Eric Laurent6010f702015-06-25 23:39:33 +00001959 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07001960 if (in->is_st_session) {
1961 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
1962 /* Read from sound trigger HAL */
1963 audio_extn_sound_trigger_read(in, buffer, bytes);
1964 pthread_mutex_unlock(&in->lock);
1965 return bytes;
1966 }
1967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001969 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001971 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 goto exit;
1974 }
1975 in->standby = 0;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001976 if (adev->adm_register_input_stream)
1977 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001980 if (adev->adm_request_focus)
1981 adev->adm_request_focus(adev->adm_data, in->capture_handle);
1982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 if (in->pcm) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001984 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1985 ret = pcm_mmap_read(in->pcm, buffer, bytes);
1986 } else
1987 ret = pcm_read(in->pcm, buffer, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988 }
1989
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001990 if (adev->adm_abandon_focus)
1991 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
1992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993 /*
1994 * Instead of writing zeroes here, we could trust the hardware
1995 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07001996 * No need to acquire adev->lock to read mic_muted here as we don't change its state.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07001998 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 memset(buffer, 0, bytes);
2000
2001exit:
2002 pthread_mutex_unlock(&in->lock);
2003
2004 if (ret != 0) {
2005 in_standby(&in->stream.common);
2006 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002007 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008 in_get_sample_rate(&in->stream.common));
2009 }
2010 return bytes;
2011}
2012
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002013static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014{
2015 return 0;
2016}
2017
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002018static int add_remove_audio_effect(const struct audio_stream *stream,
2019 effect_handle_t effect,
2020 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002022 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002023 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002024 int status = 0;
2025 effect_descriptor_t desc;
2026
2027 status = (*effect)->get_descriptor(effect, &desc);
2028 if (status != 0)
2029 return status;
2030
Eric Laurent6010f702015-06-25 23:39:33 +00002031 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002032 pthread_mutex_lock(&in->dev->lock);
2033 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2034 in->enable_aec != enable &&
2035 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2036 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002037 if (!enable)
2038 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
2039 adev->enable_voicerx = enable;
2040 struct audio_usecase *usecase;
2041 struct listnode *node;
2042 list_for_each(node, &adev->usecase_list) {
2043 usecase = node_to_item(node, struct audio_usecase, list);
2044 if (usecase->type == PCM_PLAYBACK) {
2045 select_devices(adev, usecase->id);
2046 break;
2047 }
2048 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002049 if (!in->standby)
2050 select_devices(in->dev, in->usecase);
2051 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002052 if (in->enable_ns != enable &&
2053 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2054 in->enable_ns = enable;
2055 if (!in->standby)
2056 select_devices(in->dev, in->usecase);
2057 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002058 pthread_mutex_unlock(&in->dev->lock);
2059 pthread_mutex_unlock(&in->lock);
2060
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 return 0;
2062}
2063
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002064static int in_add_audio_effect(const struct audio_stream *stream,
2065 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066{
Eric Laurent994a6932013-07-17 11:51:42 -07002067 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002068 return add_remove_audio_effect(stream, effect, true);
2069}
2070
2071static int in_remove_audio_effect(const struct audio_stream *stream,
2072 effect_handle_t effect)
2073{
Eric Laurent994a6932013-07-17 11:51:42 -07002074 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002075 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076}
2077
2078static int adev_open_output_stream(struct audio_hw_device *dev,
2079 audio_io_handle_t handle,
2080 audio_devices_t devices,
2081 audio_output_flags_t flags,
2082 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002083 struct audio_stream_out **stream_out,
2084 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002085{
2086 struct audio_device *adev = (struct audio_device *)dev;
2087 struct stream_out *out;
2088 int i, ret;
2089
Eric Laurent994a6932013-07-17 11:51:42 -07002090 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091 __func__, config->sample_rate, config->channel_mask, devices, flags);
2092 *stream_out = NULL;
2093 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2094
2095 if (devices == AUDIO_DEVICE_NONE)
2096 devices = AUDIO_DEVICE_OUT_SPEAKER;
2097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098 out->flags = flags;
2099 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002100 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002101 out->format = config->format;
2102 out->sample_rate = config->sample_rate;
2103 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2104 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002105 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106
2107 /* Init use case and pcm_config */
2108 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002109 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002111 pthread_mutex_lock(&adev->lock);
2112 ret = read_hdmi_channel_masks(out);
2113 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002114 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002115 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002116
2117 if (config->sample_rate == 0)
2118 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2119 if (config->channel_mask == 0)
2120 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2121
2122 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002123 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2125 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002127 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002129 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2130 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2131 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2132 ALOGE("%s: Unsupported Offload information", __func__);
2133 ret = -EINVAL;
2134 goto error_open;
2135 }
2136 if (!is_supported_format(config->offload_info.format)) {
2137 ALOGE("%s: Unsupported audio format", __func__);
2138 ret = -EINVAL;
2139 goto error_open;
2140 }
2141
2142 out->compr_config.codec = (struct snd_codec *)
2143 calloc(1, sizeof(struct snd_codec));
2144
2145 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2146 if (config->offload_info.channel_mask)
2147 out->channel_mask = config->offload_info.channel_mask;
2148 else if (config->channel_mask)
2149 out->channel_mask = config->channel_mask;
2150 out->format = config->offload_info.format;
2151 out->sample_rate = config->offload_info.sample_rate;
2152
2153 out->stream.set_callback = out_set_callback;
2154 out->stream.pause = out_pause;
2155 out->stream.resume = out_resume;
2156 out->stream.drain = out_drain;
2157 out->stream.flush = out_flush;
2158
2159 out->compr_config.codec->id =
2160 get_snd_codec_id(config->offload_info.format);
2161 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2162 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002163 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002164 out->compr_config.codec->bit_rate =
2165 config->offload_info.bit_rate;
2166 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002167 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002168 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2169
2170 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2171 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002172
2173 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 create_offload_callback_thread(out);
2175 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2176 __func__, config->offload_info.version,
2177 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002178 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2179 if (config->sample_rate == 0)
2180 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2181 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2182 config->sample_rate != 8000) {
2183 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2184 ret = -EINVAL;
2185 goto error_open;
2186 }
2187 out->sample_rate = config->sample_rate;
2188 out->config.rate = config->sample_rate;
2189 if (config->format == AUDIO_FORMAT_DEFAULT)
2190 config->format = AUDIO_FORMAT_PCM_16_BIT;
2191 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2192 config->format = AUDIO_FORMAT_PCM_16_BIT;
2193 ret = -EINVAL;
2194 goto error_open;
2195 }
2196 out->format = config->format;
2197 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2198 out->config = pcm_config_afe_proxy_playback;
2199 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002201 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2202 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2203 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002204 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2205 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2206 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002207 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2208 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2209 out->config = pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002210 } else {
2211 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2212 out->config = pcm_config_low_latency;
2213 }
2214 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2215 if (k_enable_extended_precision
2216 && pcm_params_format_test(adev->use_case_table[out->usecase],
2217 pcm_format_from_audio_format(config->format))) {
2218 out->config.format = pcm_format_from_audio_format(config->format);
2219 /* out->format already set to config->format */
2220 } else {
2221 /* deny the externally proposed config format
2222 * and use the one specified in audio_hw layer configuration.
2223 * Note: out->format is returned by out->stream.common.get_format()
2224 * and is used to set config->format in the code several lines below.
2225 */
2226 out->format = audio_format_from_pcm_format(out->config.format);
2227 }
2228 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002229 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07002231 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
2232 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002234 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002235 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002236 adev->primary_output = out;
2237 else {
2238 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002239 ret = -EEXIST;
2240 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002241 }
2242 }
2243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 /* Check if this usecase is already existing */
2245 pthread_mutex_lock(&adev->lock);
2246 if (get_usecase_from_list(adev, out->usecase) != NULL) {
2247 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002249 ret = -EEXIST;
2250 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251 }
2252 pthread_mutex_unlock(&adev->lock);
2253
2254 out->stream.common.get_sample_rate = out_get_sample_rate;
2255 out->stream.common.set_sample_rate = out_set_sample_rate;
2256 out->stream.common.get_buffer_size = out_get_buffer_size;
2257 out->stream.common.get_channels = out_get_channels;
2258 out->stream.common.get_format = out_get_format;
2259 out->stream.common.set_format = out_set_format;
2260 out->stream.common.standby = out_standby;
2261 out->stream.common.dump = out_dump;
2262 out->stream.common.set_parameters = out_set_parameters;
2263 out->stream.common.get_parameters = out_get_parameters;
2264 out->stream.common.add_audio_effect = out_add_audio_effect;
2265 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2266 out->stream.get_latency = out_get_latency;
2267 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002268#ifdef NO_AUDIO_OUT
2269 out->stream.write = out_write_for_no_output;
2270#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002272#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273 out->stream.get_render_position = out_get_render_position;
2274 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002275 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002278 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002279 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002281 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2282 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284 config->format = out->stream.common.get_format(&out->stream.common);
2285 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
2286 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
2287
2288 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002289 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002291
2292error_open:
2293 free(out);
2294 *stream_out = NULL;
2295 ALOGD("%s: exit: ret %d", __func__, ret);
2296 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297}
2298
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002299static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 struct audio_stream_out *stream)
2301{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002302 struct stream_out *out = (struct stream_out *)stream;
2303 struct audio_device *adev = out->dev;
2304
Eric Laurent994a6932013-07-17 11:51:42 -07002305 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002307 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2308 destroy_offload_callback_thread(out);
2309
2310 if (out->compr_config.codec != NULL)
2311 free(out->compr_config.codec);
2312 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07002313
2314 if (adev->voice_tx_output == out)
2315 adev->voice_tx_output = NULL;
2316
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002317 pthread_cond_destroy(&out->cond);
2318 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002320 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321}
2322
2323static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2324{
2325 struct audio_device *adev = (struct audio_device *)dev;
2326 struct str_parms *parms;
2327 char *str;
2328 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002329 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07002331 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002333 ALOGD("%s: enter: %s", __func__, kvpairs);
2334
2335 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336
2337 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002338 status = voice_set_parameters(adev, parms);
2339 if (status != 0) {
2340 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 }
2342
2343 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
2344 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07002345 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2347 adev->bluetooth_nrec = true;
2348 else
2349 adev->bluetooth_nrec = false;
2350 }
2351
2352 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
2353 if (ret >= 0) {
2354 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2355 adev->screen_off = false;
2356 else
2357 adev->screen_off = true;
2358 }
2359
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002360 ret = str_parms_get_int(parms, "rotation", &val);
2361 if (ret >= 0) {
2362 bool reverse_speakers = false;
2363 switch(val) {
2364 // FIXME: note that the code below assumes that the speakers are in the correct placement
2365 // relative to the user when the device is rotated 90deg from its default rotation. This
2366 // assumption is device-specific, not platform-specific like this code.
2367 case 270:
2368 reverse_speakers = true;
2369 break;
2370 case 0:
2371 case 90:
2372 case 180:
2373 break;
2374 default:
2375 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07002376 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002377 }
Eric Laurent03f09432014-03-25 18:09:11 -07002378 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07002379 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002380 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002381 }
2382
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002383 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
2384 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002385 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002386 }
2387
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08002388 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002389done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002391 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07002392 ALOGV("%s: exit with code(%d)", __func__, status);
2393 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394}
2395
2396static char* adev_get_parameters(const struct audio_hw_device *dev,
2397 const char *keys)
2398{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002399 struct audio_device *adev = (struct audio_device *)dev;
2400 struct str_parms *reply = str_parms_create();
2401 struct str_parms *query = str_parms_create_str(keys);
2402 char *str;
2403
2404 pthread_mutex_lock(&adev->lock);
2405
2406 voice_get_parameters(adev, query, reply);
2407 str = str_parms_to_str(reply);
2408 str_parms_destroy(query);
2409 str_parms_destroy(reply);
2410
2411 pthread_mutex_unlock(&adev->lock);
2412 ALOGV("%s: exit: returns - %s", __func__, str);
2413 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414}
2415
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002416static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417{
2418 return 0;
2419}
2420
Haynes Mathew George5191a852013-09-11 14:19:36 -07002421static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
2422{
2423 int ret;
2424 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002425
Eric Laurent4cc4ce12014-09-10 13:21:01 -05002426 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
2427
Haynes Mathew George5191a852013-09-11 14:19:36 -07002428 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002429 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07002430 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002431
Haynes Mathew George5191a852013-09-11 14:19:36 -07002432 return ret;
2433}
2434
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002435static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436{
2437 return -ENOSYS;
2438}
2439
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002440static int adev_get_master_volume(struct audio_hw_device *dev __unused,
2441 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442{
2443 return -ENOSYS;
2444}
2445
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002446static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447{
2448 return -ENOSYS;
2449}
2450
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002451static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452{
2453 return -ENOSYS;
2454}
2455
2456static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
2457{
2458 struct audio_device *adev = (struct audio_device *)dev;
2459
2460 pthread_mutex_lock(&adev->lock);
2461 if (adev->mode != mode) {
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002462 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002463 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07002464 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
2465 voice_is_in_call(adev)) {
2466 voice_stop_call(adev);
2467 adev->current_call_output = NULL;
2468 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 }
2470 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002471
2472 audio_extn_extspk_set_mode(adev->extspk, mode);
2473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474 return 0;
2475}
2476
2477static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
2478{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002479 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002482 ALOGD("%s: state %d\n", __func__, state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002483 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002484 ret = voice_set_mic_mute(adev, state);
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002485 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00002486 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002487
2488 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489}
2490
2491static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
2492{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002493 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 return 0;
2495}
2496
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002497static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 const struct audio_config *config)
2499{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002500 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002502 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
2503 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504}
2505
2506static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002507 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508 audio_devices_t devices,
2509 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002510 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07002511 audio_input_flags_t flags,
2512 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05002513 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514{
2515 struct audio_device *adev = (struct audio_device *)dev;
2516 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002517 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002518 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002519 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520
Eric Laurent994a6932013-07-17 11:51:42 -07002521 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 *stream_in = NULL;
2523 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
2524 return -EINVAL;
2525
2526 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
2527
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002528 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
2529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530 in->stream.common.get_sample_rate = in_get_sample_rate;
2531 in->stream.common.set_sample_rate = in_set_sample_rate;
2532 in->stream.common.get_buffer_size = in_get_buffer_size;
2533 in->stream.common.get_channels = in_get_channels;
2534 in->stream.common.get_format = in_get_format;
2535 in->stream.common.set_format = in_set_format;
2536 in->stream.common.standby = in_standby;
2537 in->stream.common.dump = in_dump;
2538 in->stream.common.set_parameters = in_set_parameters;
2539 in->stream.common.get_parameters = in_get_parameters;
2540 in->stream.common.add_audio_effect = in_add_audio_effect;
2541 in->stream.common.remove_audio_effect = in_remove_audio_effect;
2542 in->stream.set_gain = in_set_gain;
2543 in->stream.read = in_read;
2544 in->stream.get_input_frames_lost = in_get_input_frames_lost;
2545
2546 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002547 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 in->standby = 1;
2550 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002551 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002552 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553
2554 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002555 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
2556 if (config->sample_rate == 0)
2557 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2558 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2559 config->sample_rate != 8000) {
2560 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2561 ret = -EINVAL;
2562 goto err_open;
2563 }
2564 if (config->format == AUDIO_FORMAT_DEFAULT)
2565 config->format = AUDIO_FORMAT_PCM_16_BIT;
2566 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2567 config->format = AUDIO_FORMAT_PCM_16_BIT;
2568 ret = -EINVAL;
2569 goto err_open;
2570 }
2571
2572 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
2573 in->config = pcm_config_afe_proxy_record;
2574 } else {
2575 in->usecase = USECASE_AUDIO_RECORD;
2576 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
2577 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
2578 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07002579#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002580 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07002581#endif
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002582 }
2583 in->config = pcm_config_audio_capture;
2584
2585 frame_size = audio_stream_in_frame_size(&in->stream);
2586 buffer_size = get_input_buffer_size(config->sample_rate,
2587 config->format,
2588 channel_count,
2589 is_low_latency);
2590 in->config.period_size = buffer_size / frame_size;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002591 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 in->config.channels = channel_count;
2593 in->config.rate = config->sample_rate;
2594
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002595 /* This stream could be for sound trigger lab,
2596 get sound trigger pcm if present */
2597 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598
2599 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002600 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 return 0;
2602
2603err_open:
2604 free(in);
2605 *stream_in = NULL;
2606 return ret;
2607}
2608
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002609static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610 struct audio_stream_in *stream)
2611{
Eric Laurent994a6932013-07-17 11:51:42 -07002612 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614 in_standby(&stream->common);
2615 free(stream);
2616
2617 return;
2618}
2619
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002620static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621{
2622 return 0;
2623}
2624
Andy Hung31aca912014-03-20 17:14:59 -07002625/* verifies input and output devices and their capabilities.
2626 *
2627 * This verification is required when enabling extended bit-depth or
2628 * sampling rates, as not all qcom products support it.
2629 *
2630 * Suitable for calling only on initialization such as adev_open().
2631 * It fills the audio_device use_case_table[] array.
2632 *
2633 * Has a side-effect that it needs to configure audio routing / devices
2634 * in order to power up the devices and read the device parameters.
2635 * It does not acquire any hw device lock. Should restore the devices
2636 * back to "normal state" upon completion.
2637 */
2638static int adev_verify_devices(struct audio_device *adev)
2639{
2640 /* enumeration is a bit difficult because one really wants to pull
2641 * the use_case, device id, etc from the hidden pcm_device_table[].
2642 * In this case there are the following use cases and device ids.
2643 *
2644 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
2645 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
2646 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
2647 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
2648 * [USECASE_AUDIO_RECORD] = {0, 0},
2649 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
2650 * [USECASE_VOICE_CALL] = {2, 2},
2651 *
2652 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
2653 * USECASE_VOICE_CALL omitted, but possible for either input or output.
2654 */
2655
2656 /* should be the usecases enabled in adev_open_input_stream() */
2657 static const int test_in_usecases[] = {
2658 USECASE_AUDIO_RECORD,
2659 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
2660 };
2661 /* should be the usecases enabled in adev_open_output_stream()*/
2662 static const int test_out_usecases[] = {
2663 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
2664 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
2665 };
2666 static const usecase_type_t usecase_type_by_dir[] = {
2667 PCM_PLAYBACK,
2668 PCM_CAPTURE,
2669 };
2670 static const unsigned flags_by_dir[] = {
2671 PCM_OUT,
2672 PCM_IN,
2673 };
2674
2675 size_t i;
2676 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002677 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07002678 char info[512]; /* for possible debug info */
2679
2680 for (dir = 0; dir < 2; ++dir) {
2681 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
2682 const unsigned flags_dir = flags_by_dir[dir];
2683 const size_t testsize =
2684 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
2685 const int *testcases =
2686 dir ? test_in_usecases : test_out_usecases;
2687 const audio_devices_t audio_device =
2688 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
2689
2690 for (i = 0; i < testsize; ++i) {
2691 const audio_usecase_t audio_usecase = testcases[i];
2692 int device_id;
2693 snd_device_t snd_device;
2694 struct pcm_params **pparams;
2695 struct stream_out out;
2696 struct stream_in in;
2697 struct audio_usecase uc_info;
2698 int retval;
2699
2700 pparams = &adev->use_case_table[audio_usecase];
2701 pcm_params_free(*pparams); /* can accept null input */
2702 *pparams = NULL;
2703
2704 /* find the device ID for the use case (signed, for error) */
2705 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
2706 if (device_id < 0)
2707 continue;
2708
2709 /* prepare structures for device probing */
2710 memset(&uc_info, 0, sizeof(uc_info));
2711 uc_info.id = audio_usecase;
2712 uc_info.type = usecase_type;
2713 if (dir) {
2714 adev->active_input = &in;
2715 memset(&in, 0, sizeof(in));
2716 in.device = audio_device;
2717 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
2718 uc_info.stream.in = &in;
2719 } else {
2720 adev->active_input = NULL;
2721 }
2722 memset(&out, 0, sizeof(out));
2723 out.devices = audio_device; /* only field needed in select_devices */
2724 uc_info.stream.out = &out;
2725 uc_info.devices = audio_device;
2726 uc_info.in_snd_device = SND_DEVICE_NONE;
2727 uc_info.out_snd_device = SND_DEVICE_NONE;
2728 list_add_tail(&adev->usecase_list, &uc_info.list);
2729
2730 /* select device - similar to start_(in/out)put_stream() */
2731 retval = select_devices(adev, audio_usecase);
2732 if (retval >= 0) {
2733 *pparams = pcm_params_get(card_id, device_id, flags_dir);
2734#if LOG_NDEBUG == 0
2735 if (*pparams) {
2736 ALOGV("%s: (%s) card %d device %d", __func__,
2737 dir ? "input" : "output", card_id, device_id);
2738 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
2739 ALOGV(info); /* print parameters */
2740 } else {
2741 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
2742 }
2743#endif
2744 }
2745
2746 /* deselect device - similar to stop_(in/out)put_stream() */
2747 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07002748 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07002749 /* 2. Disable the rx device */
2750 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07002751 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07002752 list_remove(&uc_info.list);
2753 }
2754 }
2755 adev->active_input = NULL; /* restore adev state */
2756 return 0;
2757}
2758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759static int adev_close(hw_device_t *device)
2760{
Andy Hung31aca912014-03-20 17:14:59 -07002761 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07002763
2764 if (!adev)
2765 return 0;
2766
2767 pthread_mutex_lock(&adev_init_lock);
2768
2769 if ((--audio_device_ref_count) == 0) {
2770 audio_route_free(adev->audio_route);
2771 free(adev->snd_dev_ref_cnt);
2772 platform_deinit(adev->platform);
2773 audio_extn_extspk_deinit(adev->extspk);
2774 audio_extn_sound_trigger_deinit(adev);
2775 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
2776 pcm_params_free(adev->use_case_table[i]);
2777 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002778 if (adev->adm_deinit)
2779 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07002780 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07002781 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07002782
2783 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785 return 0;
2786}
2787
Glenn Kasten4f993392014-05-14 07:30:48 -07002788/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
2789 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
2790 * just that it _might_ work.
2791 */
2792static int period_size_is_plausible_for_low_latency(int period_size)
2793{
2794 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07002795 case 48:
2796 case 96:
2797 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07002798 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07002799 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07002800 case 240:
2801 case 320:
2802 case 480:
2803 return 1;
2804 default:
2805 return 0;
2806 }
2807}
2808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809static int adev_open(const hw_module_t *module, const char *name,
2810 hw_device_t **device)
2811{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002812 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002814 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07002816 pthread_mutex_lock(&adev_init_lock);
2817 if (audio_device_ref_count != 0) {
2818 *device = &adev->device.common;
2819 audio_device_ref_count++;
2820 ALOGV("%s: returning existing instance of adev", __func__);
2821 ALOGV("%s: exit", __func__);
2822 pthread_mutex_unlock(&adev_init_lock);
2823 return 0;
2824 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825 adev = calloc(1, sizeof(struct audio_device));
2826
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002827 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
2828
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 adev->device.common.tag = HARDWARE_DEVICE_TAG;
2830 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
2831 adev->device.common.module = (struct hw_module_t *)module;
2832 adev->device.common.close = adev_close;
2833
2834 adev->device.init_check = adev_init_check;
2835 adev->device.set_voice_volume = adev_set_voice_volume;
2836 adev->device.set_master_volume = adev_set_master_volume;
2837 adev->device.get_master_volume = adev_get_master_volume;
2838 adev->device.set_master_mute = adev_set_master_mute;
2839 adev->device.get_master_mute = adev_get_master_mute;
2840 adev->device.set_mode = adev_set_mode;
2841 adev->device.set_mic_mute = adev_set_mic_mute;
2842 adev->device.get_mic_mute = adev_get_mic_mute;
2843 adev->device.set_parameters = adev_set_parameters;
2844 adev->device.get_parameters = adev_get_parameters;
2845 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
2846 adev->device.open_output_stream = adev_open_output_stream;
2847 adev->device.close_output_stream = adev_close_output_stream;
2848 adev->device.open_input_stream = adev_open_input_stream;
2849 adev->device.close_input_stream = adev_close_input_stream;
2850 adev->device.dump = adev_dump;
2851
2852 /* Set the default route before the PCM stream is opened */
2853 pthread_mutex_lock(&adev->lock);
2854 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08002855 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002856 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08002858 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07002859 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07002860 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002861 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002862 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 pthread_mutex_unlock(&adev->lock);
2864
2865 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07002866 adev->platform = platform_init(adev);
2867 if (!adev->platform) {
2868 free(adev->snd_dev_ref_cnt);
2869 free(adev);
2870 ALOGE("%s: Failed to init platform data, aborting.", __func__);
2871 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07002872 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07002873 return -EINVAL;
2874 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002875
Eric Laurent0499d4f2014-08-25 22:39:29 -05002876 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002877 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002878
Eric Laurentc4aef752013-09-12 17:45:53 -07002879 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
2880 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
2881 if (adev->visualizer_lib == NULL) {
2882 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
2883 } else {
2884 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
2885 adev->visualizer_start_output =
Haynes Mathew George41f86652014-06-17 14:22:15 -07002886 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07002887 "visualizer_hal_start_output");
2888 adev->visualizer_stop_output =
Haynes Mathew George41f86652014-06-17 14:22:15 -07002889 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07002890 "visualizer_hal_stop_output");
2891 }
2892 }
2893
Haynes Mathew George41f86652014-06-17 14:22:15 -07002894 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
2895 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
2896 if (adev->offload_effects_lib == NULL) {
2897 ALOGE("%s: DLOPEN failed for %s", __func__,
2898 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
2899 } else {
2900 ALOGV("%s: DLOPEN successful for %s", __func__,
2901 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
2902 adev->offload_effects_start_output =
2903 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
2904 "offload_effects_bundle_hal_start_output");
2905 adev->offload_effects_stop_output =
2906 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
2907 "offload_effects_bundle_hal_stop_output");
2908 }
2909 }
2910
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002911 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
2912 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
2913 if (adev->adm_lib == NULL) {
2914 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
2915 } else {
2916 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
2917 adev->adm_init = (adm_init_t)
2918 dlsym(adev->adm_lib, "adm_init");
2919 adev->adm_deinit = (adm_deinit_t)
2920 dlsym(adev->adm_lib, "adm_deinit");
2921 adev->adm_register_input_stream = (adm_register_input_stream_t)
2922 dlsym(adev->adm_lib, "adm_register_input_stream");
2923 adev->adm_register_output_stream = (adm_register_output_stream_t)
2924 dlsym(adev->adm_lib, "adm_register_output_stream");
2925 adev->adm_deregister_stream = (adm_deregister_stream_t)
2926 dlsym(adev->adm_lib, "adm_deregister_stream");
2927 adev->adm_request_focus = (adm_request_focus_t)
2928 dlsym(adev->adm_lib, "adm_request_focus");
2929 adev->adm_abandon_focus = (adm_abandon_focus_t)
2930 dlsym(adev->adm_lib, "adm_abandon_focus");
2931 }
2932 }
2933
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002934 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002935 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07002938
Andy Hung31aca912014-03-20 17:14:59 -07002939 if (k_enable_extended_precision)
2940 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941
Glenn Kasten4f993392014-05-14 07:30:48 -07002942 char value[PROPERTY_VALUE_MAX];
2943 int trial;
2944 if (property_get("audio_hal.period_size", value, NULL) > 0) {
2945 trial = atoi(value);
2946 if (period_size_is_plausible_for_low_latency(trial)) {
2947 pcm_config_low_latency.period_size = trial;
2948 pcm_config_low_latency.start_threshold = trial / 4;
2949 pcm_config_low_latency.avail_min = trial / 4;
2950 configured_low_latency_capture_period_size = trial;
2951 }
2952 }
2953 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
2954 trial = atoi(value);
2955 if (period_size_is_plausible_for_low_latency(trial)) {
2956 configured_low_latency_capture_period_size = trial;
2957 }
2958 }
2959
vivek mehta1a9b7c02015-06-25 11:49:38 -07002960 audio_device_ref_count++;
2961 pthread_mutex_unlock(&adev_init_lock);
2962
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002963 if (adev->adm_init)
2964 adev->adm_data = adev->adm_init();
2965
Eric Laurent994a6932013-07-17 11:51:42 -07002966 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967 return 0;
2968}
2969
2970static struct hw_module_methods_t hal_module_methods = {
2971 .open = adev_open,
2972};
2973
2974struct audio_module HAL_MODULE_INFO_SYM = {
2975 .common = {
2976 .tag = HARDWARE_MODULE_TAG,
2977 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
2978 .hal_api_version = HARDWARE_HAL_API_VERSION,
2979 .id = AUDIO_HARDWARE_MODULE_ID,
2980 .name = "QCOM Audio HAL",
2981 .author = "Code Aurora Forum",
2982 .methods = &hal_module_methods,
2983 },
2984};