blob: c01ba776bd8364a83d712d0eb31c3eb6d77d5828 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "audio_hw_primary"
21/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070022/*#define VERY_VERY_VERBOSE_LOGGING*/
23#ifdef VERY_VERY_VERBOSE_LOGGING
24#define ALOGVV ALOGV
25#else
26#define ALOGVV(a...) do { } while(0)
27#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080028
29#include <errno.h>
30#include <pthread.h>
31#include <stdint.h>
32#include <sys/time.h>
33#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080034#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070035#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070036#include <sys/resource.h>
37#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080038
39#include <cutils/log.h>
40#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070047#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080049#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070050#include "platform_api.h"
51#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070052#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080053#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080056#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
59/* ToDo: Check and update a proper value in msec */
60#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
61#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
62
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080063
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080064#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
65
Eric Laurentb23d5282013-05-14 15:27:20 -070066struct pcm_config pcm_config_deep_buffer = {
67 .channels = 2,
68 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
69 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
70 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
71 .format = PCM_FORMAT_S16_LE,
72 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
73 .stop_threshold = INT_MAX,
74 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
75};
76
77struct pcm_config pcm_config_low_latency = {
78 .channels = 2,
79 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
80 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
81 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
82 .format = PCM_FORMAT_S16_LE,
83 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
84 .stop_threshold = INT_MAX,
85 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
86};
87
88struct pcm_config pcm_config_hdmi_multi = {
89 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
90 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
91 .period_size = HDMI_MULTI_PERIOD_SIZE,
92 .period_count = HDMI_MULTI_PERIOD_COUNT,
93 .format = PCM_FORMAT_S16_LE,
94 .start_threshold = 0,
95 .stop_threshold = INT_MAX,
96 .avail_min = 0,
97};
98
99struct pcm_config pcm_config_audio_capture = {
100 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700101 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
102 .format = PCM_FORMAT_S16_LE,
103};
104
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800105const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700106 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
107 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
108 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700109 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700110#ifdef MULTIPLE_OFFLOAD_ENABLED
111 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
112 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
113 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
114 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
115 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
116 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
117 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
118 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
119#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700120 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700121 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700122 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700123 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700124 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800125 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800126 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700127 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700128
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700129 [USECASE_VOICE2_CALL] = "voice2-call",
130 [USECASE_VOLTE_CALL] = "volte-call",
131 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800132 [USECASE_VOWLAN_CALL] = "vowlan-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800133 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700134 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
135 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
136 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800137 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
138 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
139 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
140
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700141 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
142 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700143 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
144 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700145};
146
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700147static const audio_usecase_t offload_usecases[] = {
148 USECASE_AUDIO_PLAYBACK_OFFLOAD,
149#ifdef MULTIPLE_OFFLOAD_ENABLED
150 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
151 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
152 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
153 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
154 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
155 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
156 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
157 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
158#endif
159};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800160
161#define STRING_TO_ENUM(string) { #string, string }
162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800163struct string_to_enum {
164 const char *name;
165 uint32_t value;
166};
167
168static const struct string_to_enum out_channels_name_to_enum_table[] = {
169 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
170 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
171 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
172};
173
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700174static struct audio_device *adev = NULL;
175static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700176static unsigned int audio_device_ref_count;
177
Haynes Mathew George5191a852013-09-11 14:19:36 -0700178static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800179
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800180static int check_and_set_gapless_mode(struct audio_device *adev) {
181
182
183 char value[PROPERTY_VALUE_MAX] = {0};
184 bool gapless_enabled = false;
185 const char *mixer_ctl_name = "Compress Gapless Playback";
186 struct mixer_ctl *ctl;
187
188 ALOGV("%s:", __func__);
189 property_get("audio.offload.gapless.enabled", value, NULL);
190 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
191
192 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
193 if (!ctl) {
194 ALOGE("%s: Could not get ctl for mixer cmd - %s",
195 __func__, mixer_ctl_name);
196 return -EINVAL;
197 }
198
199 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
200 ALOGE("%s: Could not set gapless mode %d",
201 __func__, gapless_enabled);
202 return -EINVAL;
203 }
204 return 0;
205}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700206
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700207static bool is_supported_format(audio_format_t format)
208{
Eric Laurent86e17132013-09-12 17:49:30 -0700209 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530210 format == AUDIO_FORMAT_AAC_LC ||
211 format == AUDIO_FORMAT_AAC_HE_V1 ||
212 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800213 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700214 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
215 format == AUDIO_FORMAT_FLAC)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800216 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700217
218 return false;
219}
220
221static int get_snd_codec_id(audio_format_t format)
222{
223 int id = 0;
224
Ashish Jainf9b78162014-08-25 20:36:25 +0530225 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700226 case AUDIO_FORMAT_MP3:
227 id = SND_AUDIOCODEC_MP3;
228 break;
229 case AUDIO_FORMAT_AAC:
230 id = SND_AUDIOCODEC_AAC;
231 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530232 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800233 id = SND_AUDIOCODEC_PCM;
234 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700235 case AUDIO_FORMAT_FLAC:
236 id = SND_AUDIOCODEC_FLAC;
237 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700238 default:
Mingming Yin90310102013-11-13 16:57:00 -0800239 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700240 }
241
242 return id;
243}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800244
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530245int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530246{
247 int snd_scard_state;
248
249 if (!adev)
250 return SND_CARD_STATE_OFFLINE;
251
252 pthread_mutex_lock(&adev->snd_card_status.lock);
253 snd_scard_state = adev->snd_card_status.state;
254 pthread_mutex_unlock(&adev->snd_card_status.lock);
255
256 return snd_scard_state;
257}
258
259static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
260{
261 if (!adev)
262 return -ENOSYS;
263
264 pthread_mutex_lock(&adev->snd_card_status.lock);
265 adev->snd_card_status.state = snd_scard_state;
266 pthread_mutex_unlock(&adev->snd_card_status.lock);
267
268 return 0;
269}
270
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700271int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700272 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800273{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700274 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700275 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800276
277 if (usecase == NULL)
278 return -EINVAL;
279
280 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
281
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800282 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700283 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800284 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700285 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800286
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800287#ifdef DS1_DOLBY_DAP_ENABLED
288 audio_extn_dolby_set_dmid(adev);
289 audio_extn_dolby_set_endpoint(adev);
290#endif
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530291 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700292 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700293 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800294 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700295 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700296 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
297 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800298 ALOGV("%s: exit", __func__);
299 return 0;
300}
301
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700302int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700303 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800304{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700305 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700306 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800307
308 if (usecase == NULL)
309 return -EINVAL;
310
311 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700312 if (usecase->type == PCM_CAPTURE)
313 snd_device = usecase->in_snd_device;
314 else
315 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800316 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700317 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700318 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
319 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530320 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800321 ALOGV("%s: exit", __func__);
322 return 0;
323}
324
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700325int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700326 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800327{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700328 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
329
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800330 if (snd_device < SND_DEVICE_MIN ||
331 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800332 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800333 return -EINVAL;
334 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700335
336 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700337
338 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
339 ALOGE("%s: Invalid sound device returned", __func__);
340 return -EINVAL;
341 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700342 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700343 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700344 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700345 return 0;
346 }
347
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700348 if (audio_extn_spkr_prot_is_enabled())
349 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700350 /* start usb playback thread */
351 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
352 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
353 audio_extn_usb_start_playback(adev);
354
355 /* start usb capture thread */
356 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
357 audio_extn_usb_start_capture(adev);
358
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800359 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
360 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700361 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700362 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
363 adev->snd_dev_ref_cnt[snd_device]--;
364 return -EINVAL;
365 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800366 if (audio_extn_spkr_prot_start_processing(snd_device)) {
367 ALOGE("%s: spkr_start_processing failed", __func__);
368 return -EINVAL;
369 }
370 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700371 ALOGV("%s: snd_device(%d: %s)", __func__,
372 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700373 /* due to the possibility of calibration overwrite between listen
374 and audio, notify listen hal before audio calibration is sent */
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530375 audio_extn_listen_update_device_status(snd_device,
376 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700377 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700378 adev->snd_dev_ref_cnt[snd_device]--;
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530379 audio_extn_listen_update_device_status(snd_device,
380 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700381 return -EINVAL;
382 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300383 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700384 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800385 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800386 return 0;
387}
388
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700389int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700390 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800391{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700392 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
393
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800394 if (snd_device < SND_DEVICE_MIN ||
395 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800396 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800397 return -EINVAL;
398 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700399 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
400 ALOGE("%s: device ref cnt is already 0", __func__);
401 return -EINVAL;
402 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700403
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700404 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700405
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700406 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
407 ALOGE("%s: Invalid sound device returned", __func__);
408 return -EINVAL;
409 }
410
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700411 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700412 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700413 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800414 /* exit usb play back thread */
415 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
416 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
417 audio_extn_usb_stop_playback();
418
419 /* exit usb capture thread */
420 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700421 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800422
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800423 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
424 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700425 audio_extn_spkr_prot_is_enabled()) {
426 audio_extn_spkr_prot_stop_processing();
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300427 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700428 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300429 audio_extn_dev_arbi_release(snd_device);
430 }
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530431 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800432 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700433 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800435 return 0;
436}
437
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700438static void check_usecases_codec_backend(struct audio_device *adev,
439 struct audio_usecase *uc_info,
440 snd_device_t snd_device)
441{
442 struct listnode *node;
443 struct audio_usecase *usecase;
444 bool switch_device[AUDIO_USECASE_MAX];
445 int i, num_uc_to_switch = 0;
446
447 /*
448 * This function is to make sure that all the usecases that are active on
449 * the hardware codec backend are always routed to any one device that is
450 * handled by the hardware codec.
451 * For example, if low-latency and deep-buffer usecases are currently active
452 * on speaker and out_set_parameters(headset) is received on low-latency
453 * output, then we have to make sure deep-buffer is also switched to headset,
454 * because of the limitation that both the devices cannot be enabled
455 * at the same time as they share the same backend.
456 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700457 /*
458 * This call is to check if we need to force routing for a particular stream
459 * If there is a backend configuration change for the device when a
460 * new stream starts, then ADM needs to be closed and re-opened with the new
461 * configuraion. This call check if we need to re-route all the streams
462 * associated with the backend. Touch tone + 24 bit playback.
463 */
464 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
465
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700466 /* Disable all the usecases on the shared backend other than the
467 specified usecase */
468 for (i = 0; i < AUDIO_USECASE_MAX; i++)
469 switch_device[i] = false;
470
471 list_for_each(node, &adev->usecase_list) {
472 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800473 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700474 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700475 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700476 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
477 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
478 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700479 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700480 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700481 switch_device[usecase->id] = true;
482 num_uc_to_switch++;
483 }
484 }
485
486 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700487 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700488
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530489 /* Make sure the previous devices to be disabled first and then enable the
490 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700491 list_for_each(node, &adev->usecase_list) {
492 usecase = node_to_item(node, struct audio_usecase, list);
493 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700494 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495 }
496 }
497
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700498 list_for_each(node, &adev->usecase_list) {
499 usecase = node_to_item(node, struct audio_usecase, list);
500 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700501 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700502 }
503 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700504
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 /* Re-route all the usecases on the shared backend other than the
506 specified usecase to new snd devices */
507 list_for_each(node, &adev->usecase_list) {
508 usecase = node_to_item(node, struct audio_usecase, list);
509 /* Update the out_snd_device only before enabling the audio route */
510 if (switch_device[usecase->id] ) {
511 usecase->out_snd_device = snd_device;
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700512 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700513 }
514 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700515 }
516}
517
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700518static void check_and_route_capture_usecases(struct audio_device *adev,
519 struct audio_usecase *uc_info,
520 snd_device_t snd_device)
521{
522 struct listnode *node;
523 struct audio_usecase *usecase;
524 bool switch_device[AUDIO_USECASE_MAX];
525 int i, num_uc_to_switch = 0;
526
527 /*
528 * This function is to make sure that all the active capture usecases
529 * are always routed to the same input sound device.
530 * For example, if audio-record and voice-call usecases are currently
531 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
532 * is received for voice call then we have to make sure that audio-record
533 * usecase is also switched to earpiece i.e. voice-dmic-ef,
534 * because of the limitation that two devices cannot be enabled
535 * at the same time if they share the same backend.
536 */
537 for (i = 0; i < AUDIO_USECASE_MAX; i++)
538 switch_device[i] = false;
539
540 list_for_each(node, &adev->usecase_list) {
541 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800542 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700543 usecase != uc_info &&
544 usecase->in_snd_device != snd_device) {
545 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
546 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700547 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700548 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700549 switch_device[usecase->id] = true;
550 num_uc_to_switch++;
551 }
552 }
553
554 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700555 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700556
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530557 /* Make sure the previous devices to be disabled first and then enable the
558 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700559 list_for_each(node, &adev->usecase_list) {
560 usecase = node_to_item(node, struct audio_usecase, list);
561 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700562 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800563 }
564 }
565
566 list_for_each(node, &adev->usecase_list) {
567 usecase = node_to_item(node, struct audio_usecase, list);
568 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700569 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700570 }
571 }
572
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700573 /* Re-route all the usecases on the shared backend other than the
574 specified usecase to new snd devices */
575 list_for_each(node, &adev->usecase_list) {
576 usecase = node_to_item(node, struct audio_usecase, list);
577 /* Update the in_snd_device only before enabling the audio route */
578 if (switch_device[usecase->id] ) {
579 usecase->in_snd_device = snd_device;
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700580 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700581 }
582 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700583 }
584}
585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800586/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700587static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800588{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700589 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700590 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800591
592 switch (channels) {
593 /*
594 * Do not handle stereo output in Multi-channel cases
595 * Stereo case is handled in normal playback path
596 */
597 case 6:
598 ALOGV("%s: HDMI supports 5.1", __func__);
599 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
600 break;
601 case 8:
602 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
603 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
604 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
605 break;
606 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700607 ALOGE("HDMI does not support multi channel playback");
608 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800609 break;
610 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700611 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800612}
613
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700614static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
615{
616 struct audio_usecase *usecase;
617 struct listnode *node;
618
619 list_for_each(node, &adev->usecase_list) {
620 usecase = node_to_item(node, struct audio_usecase, list);
621 if (usecase->type == VOICE_CALL) {
622 ALOGV("%s: usecase id %d", __func__, usecase->id);
623 return usecase->id;
624 }
625 }
626 return USECASE_INVALID;
627}
628
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700629struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700630 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700631{
632 struct audio_usecase *usecase;
633 struct listnode *node;
634
635 list_for_each(node, &adev->usecase_list) {
636 usecase = node_to_item(node, struct audio_usecase, list);
637 if (usecase->id == uc_id)
638 return usecase;
639 }
640 return NULL;
641}
642
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700643int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800644{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800645 snd_device_t out_snd_device = SND_DEVICE_NONE;
646 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700647 struct audio_usecase *usecase = NULL;
648 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800649 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800650 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800651 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800652 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700653 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800654
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655 usecase = get_usecase_from_list(adev, uc_id);
656 if (usecase == NULL) {
657 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
658 return -EINVAL;
659 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800660
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800661 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800662 (usecase->type == VOIP_CALL) ||
663 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700664 out_snd_device = platform_get_output_snd_device(adev->platform,
665 usecase->stream.out->devices);
666 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700667 usecase->devices = usecase->stream.out->devices;
668 } else {
669 /*
670 * If the voice call is active, use the sound devices of voice call usecase
671 * so that it would not result any device switch. All the usecases will
672 * be switched to new device when select_devices() is called for voice call
673 * usecase. This is to avoid switching devices for voice call when
674 * check_usecases_codec_backend() is called below.
675 */
Vidyakumar Athotaad34d572014-08-05 18:20:42 -0700676 if (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700677 vc_usecase = get_usecase_from_list(adev,
678 get_voice_usecase_id_from_list(adev));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700679 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
680 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 in_snd_device = vc_usecase->in_snd_device;
682 out_snd_device = vc_usecase->out_snd_device;
683 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800684 } else if (voice_extn_compress_voip_is_active(adev)) {
685 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700686 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530687 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700688 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800689 in_snd_device = voip_usecase->in_snd_device;
690 out_snd_device = voip_usecase->out_snd_device;
691 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800692 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800693 hfp_ucid = audio_extn_hfp_get_usecase();
694 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700695 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800696 in_snd_device = hfp_usecase->in_snd_device;
697 out_snd_device = hfp_usecase->out_snd_device;
698 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 }
700 if (usecase->type == PCM_PLAYBACK) {
701 usecase->devices = usecase->stream.out->devices;
702 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700703 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700704 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700706 if (usecase->stream.out == adev->primary_output &&
707 adev->active_input &&
708 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
709 select_devices(adev, adev->active_input->usecase);
710 }
711 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712 } else if (usecase->type == PCM_CAPTURE) {
713 usecase->devices = usecase->stream.in->device;
714 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700715 if (in_snd_device == SND_DEVICE_NONE) {
716 if (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
717 adev->primary_output && !adev->primary_output->standby) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700718 in_snd_device = platform_get_input_snd_device(adev->platform,
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700719 adev->primary_output->devices);
720 } else {
Eric Laurentb23d5282013-05-14 15:27:20 -0700721 in_snd_device = platform_get_input_snd_device(adev->platform,
722 AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700723 }
724 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700725 }
726 }
727
728 if (out_snd_device == usecase->out_snd_device &&
729 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800730 return 0;
731 }
732
sangwoobc677242013-08-08 16:53:43 +0900733 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700734 out_snd_device, platform_get_snd_device_name(out_snd_device),
735 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800737 /*
738 * Limitation: While in call, to do a device switch we need to disable
739 * and enable both RX and TX devices though one of them is same as current
740 * device.
741 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700742 if ((usecase->type == VOICE_CALL) &&
743 (usecase->in_snd_device != SND_DEVICE_NONE) &&
744 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700745 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800746 }
747
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700748 /* Disable current sound devices */
749 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700750 disable_audio_route(adev, usecase);
751 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752 }
753
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700754 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700755 disable_audio_route(adev, usecase);
756 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800757 }
758
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800759 /* Applicable only on the targets that has external modem.
760 * New device information should be sent to modem before enabling
761 * the devices to reduce in-call device switch time.
762 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700763 if ((usecase->type == VOICE_CALL) &&
764 (usecase->in_snd_device != SND_DEVICE_NONE) &&
765 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800766 status = platform_switch_voice_call_enable_device_config(adev->platform,
767 out_snd_device,
768 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700769 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800770
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700771 /* Enable new sound devices */
772 if (out_snd_device != SND_DEVICE_NONE) {
773 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
774 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700775 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776 }
777
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700778 if (in_snd_device != SND_DEVICE_NONE) {
779 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700780 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700781 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700782
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800783 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)
Eric Laurentb23d5282013-05-14 15:27:20 -0700784 status = platform_switch_voice_call_device_post(adev->platform,
785 out_snd_device,
786 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800787
sangwoo170731f2013-06-08 15:36:36 +0900788 usecase->in_snd_device = in_snd_device;
789 usecase->out_snd_device = out_snd_device;
790
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700791 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900792
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800793 /* Applicable only on the targets that has external modem.
794 * Enable device command should be sent to modem only after
795 * enabling voice call mixer controls
796 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700797 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800798 status = platform_switch_voice_call_usecase_route_post(adev->platform,
799 out_snd_device,
800 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530801 ALOGD("%s: done",__func__);
802
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800803 return status;
804}
805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806static int stop_input_stream(struct stream_in *in)
807{
808 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800809 struct audio_usecase *uc_info;
810 struct audio_device *adev = in->dev;
811
Eric Laurentc8400632013-02-14 19:04:54 -0800812 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800813
Eric Laurent994a6932013-07-17 11:51:42 -0700814 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700815 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800816 uc_info = get_usecase_from_list(adev, in->usecase);
817 if (uc_info == NULL) {
818 ALOGE("%s: Could not find the usecase (%d) in the list",
819 __func__, in->usecase);
820 return -EINVAL;
821 }
822
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800823 /* Close in-call recording streams */
824 voice_check_and_stop_incall_rec_usecase(adev, in);
825
Eric Laurent150dbfe2013-02-27 14:31:02 -0800826 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700827 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828
829 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700830 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800831
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800832 list_remove(&uc_info->list);
833 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800834
Eric Laurent994a6932013-07-17 11:51:42 -0700835 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836 return ret;
837}
838
839int start_input_stream(struct stream_in *in)
840{
841 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800842 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800843 struct audio_usecase *uc_info;
844 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +0530845 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800846
Mingming Yine62d7842013-10-25 16:26:03 -0700847 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530848 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
849 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700850
Naresh Tanniru80659832014-06-04 18:17:56 +0530851
852 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +0530853 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +0530854 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +0530855 goto error_config;
856 }
Naresh Tanniru4c630392014-05-12 01:05:52 +0530857
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700858 /* Check if source matches incall recording usecase criteria */
859 ret = voice_check_and_set_incall_rec_usecase(adev, in);
860 if (ret)
861 goto error_config;
862 else
863 ALOGV("%s: usecase(%d)", __func__, in->usecase);
864
Eric Laurentb23d5282013-05-14 15:27:20 -0700865 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800866 if (in->pcm_device_id < 0) {
867 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
868 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800869 ret = -EINVAL;
870 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800871 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872
873 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800874 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700875
876 if (!uc_info) {
877 ret = -ENOMEM;
878 goto error_config;
879 }
880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800881 uc_info->id = in->usecase;
882 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800883 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 uc_info->devices = in->device;
885 uc_info->in_snd_device = SND_DEVICE_NONE;
886 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800887
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800888 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700889 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800890
Eric Laurentc8400632013-02-14 19:04:54 -0800891 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800892 __func__, adev->snd_card,
893 in->pcm_device_id, in->config.channels);
894 in->pcm = pcm_open(adev->snd_card,
895 in->pcm_device_id, PCM_IN, &in->config);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800896 if (in->pcm && !pcm_is_ready(in->pcm)) {
897 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
898 pcm_close(in->pcm);
899 in->pcm = NULL;
Eric Laurentc8400632013-02-14 19:04:54 -0800900 ret = -EIO;
901 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800902 }
Naresh Tanniru4c630392014-05-12 01:05:52 +0530903
Eric Laurent994a6932013-07-17 11:51:42 -0700904 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -0800905 return ret;
906
907error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800908 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -0800909
910error_config:
911 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700912 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -0800913
914 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800915}
916
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700917/* must be called with out->lock locked */
918static int send_offload_cmd_l(struct stream_out* out, int command)
919{
920 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
921
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700922 if (!cmd) {
923 ALOGE("failed to allocate mem for command 0x%x", command);
924 return -ENOMEM;
925 }
926
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700927 ALOGVV("%s %d", __func__, command);
928
929 cmd->cmd = command;
930 list_add_tail(&out->offload_cmd_list, &cmd->node);
931 pthread_cond_signal(&out->offload_cond);
932 return 0;
933}
934
935/* must be called iwth out->lock locked */
936static void stop_compressed_output_l(struct stream_out *out)
937{
938 out->offload_state = OFFLOAD_STATE_IDLE;
939 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -0700940 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700941 if (out->compr != NULL) {
942 compress_stop(out->compr);
943 while (out->offload_thread_blocked) {
944 pthread_cond_wait(&out->cond, &out->lock);
945 }
946 }
947}
948
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700949bool is_offload_usecase(audio_usecase_t uc_id)
950{
951 unsigned int i;
952 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
953 if (uc_id == offload_usecases[i])
954 return true;
955 }
956 return false;
957}
958
959static audio_usecase_t get_offload_usecase(struct audio_device *adev)
960{
961 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
962 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
963 char value[PROPERTY_VALUE_MAX] = {0};
964
965 property_get("audio.offload.multiple.enabled", value, NULL);
966 if (!(atoi(value) || !strncmp("true", value, 4)))
967 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
968
969 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
970 for (i = 0; i < num_usecase; i++) {
971 if (!(adev->offload_usecases_state & (0x1<<i))) {
972 adev->offload_usecases_state |= 0x1 << i;
973 ret = offload_usecases[i];
974 break;
975 }
976 }
977 ALOGV("%s: offload usecase is %d", __func__, ret);
978 return ret;
979}
980
981static void free_offload_usecase(struct audio_device *adev,
982 audio_usecase_t uc_id)
983{
984 unsigned int i;
985 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
986 if (offload_usecases[i] == uc_id) {
987 adev->offload_usecases_state &= ~(0x1<<i);
988 break;
989 }
990 }
991 ALOGV("%s: free offload usecase %d", __func__, uc_id);
992}
993
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700994static void *offload_thread_loop(void *context)
995{
996 struct stream_out *out = (struct stream_out *) context;
997 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -0800998 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700999
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001000 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1001 set_sched_policy(0, SP_FOREGROUND);
1002 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1003
1004 ALOGV("%s", __func__);
1005 pthread_mutex_lock(&out->lock);
1006 for (;;) {
1007 struct offload_cmd *cmd = NULL;
1008 stream_callback_event_t event;
1009 bool send_callback = false;
1010
1011 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1012 __func__, list_empty(&out->offload_cmd_list),
1013 out->offload_state);
1014 if (list_empty(&out->offload_cmd_list)) {
1015 ALOGV("%s SLEEPING", __func__);
1016 pthread_cond_wait(&out->offload_cond, &out->lock);
1017 ALOGV("%s RUNNING", __func__);
1018 continue;
1019 }
1020
1021 item = list_head(&out->offload_cmd_list);
1022 cmd = node_to_item(item, struct offload_cmd, node);
1023 list_remove(item);
1024
1025 ALOGVV("%s STATE %d CMD %d out->compr %p",
1026 __func__, out->offload_state, cmd->cmd, out->compr);
1027
1028 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1029 free(cmd);
1030 break;
1031 }
1032
1033 if (out->compr == NULL) {
1034 ALOGE("%s: Compress handle is NULL", __func__);
1035 pthread_cond_signal(&out->cond);
1036 continue;
1037 }
1038 out->offload_thread_blocked = true;
1039 pthread_mutex_unlock(&out->lock);
1040 send_callback = false;
1041 switch(cmd->cmd) {
1042 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001043 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001044 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001045 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001046 send_callback = true;
1047 event = STREAM_CBK_EVENT_WRITE_READY;
1048 break;
1049 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001050 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301051 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001052 ALOGD("copl(%p):calling compress_partial_drain", out);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001053 compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001054 ALOGD("copl(%p):out of compress_partial_drain", out);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301055 }
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001056 else if(ret == -ETIMEDOUT)
1057 compress_drain(out->compr);
1058 else
1059 ALOGE("%s: Next track returned error %d",__func__, ret);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001060 send_callback = true;
1061 event = STREAM_CBK_EVENT_DRAIN_READY;
1062 break;
1063 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001064 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001065 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001066 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001067 send_callback = true;
1068 event = STREAM_CBK_EVENT_DRAIN_READY;
1069 break;
1070 default:
1071 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1072 break;
1073 }
1074 pthread_mutex_lock(&out->lock);
1075 out->offload_thread_blocked = false;
1076 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001077 if (send_callback) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001078 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001079 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001080 free(cmd);
1081 }
1082
1083 pthread_cond_signal(&out->cond);
1084 while (!list_empty(&out->offload_cmd_list)) {
1085 item = list_head(&out->offload_cmd_list);
1086 list_remove(item);
1087 free(node_to_item(item, struct offload_cmd, node));
1088 }
1089 pthread_mutex_unlock(&out->lock);
1090
1091 return NULL;
1092}
1093
1094static int create_offload_callback_thread(struct stream_out *out)
1095{
1096 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1097 list_init(&out->offload_cmd_list);
1098 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1099 offload_thread_loop, out);
1100 return 0;
1101}
1102
1103static int destroy_offload_callback_thread(struct stream_out *out)
1104{
1105 pthread_mutex_lock(&out->lock);
1106 stop_compressed_output_l(out);
1107 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1108
1109 pthread_mutex_unlock(&out->lock);
1110 pthread_join(out->offload_thread, (void **) NULL);
1111 pthread_cond_destroy(&out->offload_cond);
1112
1113 return 0;
1114}
1115
Eric Laurent07eeafd2013-10-06 12:52:49 -07001116static bool allow_hdmi_channel_config(struct audio_device *adev)
1117{
1118 struct listnode *node;
1119 struct audio_usecase *usecase;
1120 bool ret = true;
1121
1122 list_for_each(node, &adev->usecase_list) {
1123 usecase = node_to_item(node, struct audio_usecase, list);
1124 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1125 /*
1126 * If voice call is already existing, do not proceed further to avoid
1127 * disabling/enabling both RX and TX devices, CSD calls, etc.
1128 * Once the voice call done, the HDMI channels can be configured to
1129 * max channels of remaining use cases.
1130 */
1131 if (usecase->id == USECASE_VOICE_CALL) {
1132 ALOGD("%s: voice call is active, no change in HDMI channels",
1133 __func__);
1134 ret = false;
1135 break;
1136 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1137 ALOGD("%s: multi channel playback is active, "
1138 "no change in HDMI channels", __func__);
1139 ret = false;
1140 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001141 } else if (is_offload_usecase(usecase->id) &&
Mingming Yin139f1072014-02-24 17:56:01 -08001142 popcount(usecase->stream.out->channel_mask) > 2) {
1143 ALOGD("%s: multi-channel(%x) compress offload playback is active, "
1144 "no change in HDMI channels", __func__, usecase->stream.out->channel_mask);
1145 ret = false;
1146 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001147 }
1148 }
1149 }
1150 return ret;
1151}
1152
1153static int check_and_set_hdmi_channels(struct audio_device *adev,
1154 unsigned int channels)
1155{
1156 struct listnode *node;
1157 struct audio_usecase *usecase;
1158
1159 /* Check if change in HDMI channel config is allowed */
1160 if (!allow_hdmi_channel_config(adev))
1161 return 0;
1162
1163 if (channels == adev->cur_hdmi_channels) {
Mingming Yin10fef6a2013-11-26 17:17:01 -08001164 ALOGD("%s: Requested channels are same as current channels(%d)", __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001165 return 0;
1166 }
1167
1168 platform_set_hdmi_channels(adev->platform, channels);
1169 adev->cur_hdmi_channels = channels;
1170
1171 /*
1172 * Deroute all the playback streams routed to HDMI so that
1173 * the back end is deactivated. Note that backend will not
1174 * be deactivated if any one stream is connected to it.
1175 */
1176 list_for_each(node, &adev->usecase_list) {
1177 usecase = node_to_item(node, struct audio_usecase, list);
1178 if (usecase->type == PCM_PLAYBACK &&
1179 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001180 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001181 }
1182 }
1183
1184 /*
1185 * Enable all the streams disabled above. Now the HDMI backend
1186 * will be activated with new channel configuration
1187 */
1188 list_for_each(node, &adev->usecase_list) {
1189 usecase = node_to_item(node, struct audio_usecase, list);
1190 if (usecase->type == PCM_PLAYBACK &&
1191 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001192 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001193 }
1194 }
1195
1196 return 0;
1197}
1198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001199static int stop_output_stream(struct stream_out *out)
1200{
1201 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001202 struct audio_usecase *uc_info;
1203 struct audio_device *adev = out->dev;
1204
Eric Laurent994a6932013-07-17 11:51:42 -07001205 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001206 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207 uc_info = get_usecase_from_list(adev, out->usecase);
1208 if (uc_info == NULL) {
1209 ALOGE("%s: Could not find the usecase (%d) in the list",
1210 __func__, out->usecase);
1211 return -EINVAL;
1212 }
1213
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001214 if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001215 if (adev->visualizer_stop_output != NULL)
1216 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1217 if (adev->offload_effects_stop_output != NULL)
1218 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1219 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001220
Eric Laurent150dbfe2013-02-27 14:31:02 -08001221 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001222 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001223
1224 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001225 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001226
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001227 list_remove(&uc_info->list);
1228 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229
Eric Laurent07eeafd2013-10-06 12:52:49 -07001230 /* Must be called after removing the usecase from list */
1231 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1232 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1233
Eric Laurent994a6932013-07-17 11:51:42 -07001234 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235 return ret;
1236}
1237
1238int start_output_stream(struct stream_out *out)
1239{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001241 int sink_channels = 0;
1242 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001243 struct audio_usecase *uc_info;
1244 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301245 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001246
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001247 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1248 ret = -EINVAL;
1249 goto error_config;
1250 }
1251
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301252 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1253 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1254 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301255
Naresh Tanniru80659832014-06-04 18:17:56 +05301256 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301257 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301258 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301259 goto error_config;
1260 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301261
Eric Laurentb23d5282013-05-14 15:27:20 -07001262 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263 if (out->pcm_device_id < 0) {
1264 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1265 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001266 ret = -EINVAL;
1267 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001268 }
1269
1270 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001271
1272 if (!uc_info) {
1273 ret = -ENOMEM;
1274 goto error_config;
1275 }
1276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277 uc_info->id = out->usecase;
1278 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001279 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001280 uc_info->devices = out->devices;
1281 uc_info->in_snd_device = SND_DEVICE_NONE;
1282 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001283
Eric Laurent07eeafd2013-10-06 12:52:49 -07001284 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001285 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Mingming Yin9c041392014-05-01 15:37:31 -07001286 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1287 if (!strncmp("true", prop_value, 4)) {
1288 sink_channels = platform_edid_get_max_channels(out->dev->platform);
1289 ALOGD("%s: set HDMI channel count[%d] based on sink capability", __func__, sink_channels);
1290 check_and_set_hdmi_channels(adev, sink_channels);
1291 } else {
1292 if (is_offload_usecase(out->usecase))
1293 check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in);
1294 else
1295 check_and_set_hdmi_channels(adev, out->config.channels);
1296 }
Mingming Yin10fef6a2013-11-26 17:17:01 -08001297 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001298
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001299 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001300
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001301 select_devices(adev, out->usecase);
1302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001303 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
1304 __func__, 0, out->pcm_device_id);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001305 if (!is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001306 out->pcm = pcm_open(adev->snd_card,
1307 out->pcm_device_id,
1308 PCM_OUT | PCM_MONOTONIC, &out->config);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001309 if (out->pcm && !pcm_is_ready(out->pcm)) {
1310 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1311 pcm_close(out->pcm);
1312 out->pcm = NULL;
1313 ret = -EIO;
1314 goto error_open;
1315 }
1316 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001317 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001318 out->compr = compress_open(adev->snd_card,
1319 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001320 COMPRESS_IN, &out->compr_config);
1321 if (out->compr && !is_compress_ready(out->compr)) {
1322 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1323 compress_close(out->compr);
1324 out->compr = NULL;
1325 ret = -EIO;
1326 goto error_open;
1327 }
1328 if (out->offload_callback)
1329 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001330
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001331#ifdef DS1_DOLBY_DDP_ENABLED
1332 if (audio_extn_is_dolby_format(out->format))
1333 audio_extn_dolby_send_ddp_endp_params(adev);
1334#endif
1335
Eric Laurentc4aef752013-09-12 17:45:53 -07001336 if (adev->visualizer_start_output != NULL)
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001337 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1338 if (adev->offload_effects_start_output != NULL)
1339 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001340 }
Eric Laurent994a6932013-07-17 11:51:42 -07001341 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001342 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001343error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001345error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001346 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001347}
1348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001349static int check_input_parameters(uint32_t sample_rate,
1350 audio_format_t format,
1351 int channel_count)
1352{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001353 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001354
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001355 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001356 !voice_extn_compress_voip_is_format_supported(format) &&
1357 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001358
1359 switch (channel_count) {
1360 case 1:
1361 case 2:
1362 case 6:
1363 break;
1364 default:
1365 ret = -EINVAL;
1366 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367
1368 switch (sample_rate) {
1369 case 8000:
1370 case 11025:
1371 case 12000:
1372 case 16000:
1373 case 22050:
1374 case 24000:
1375 case 32000:
1376 case 44100:
1377 case 48000:
1378 break;
1379 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001380 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001381 }
1382
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001383 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384}
1385
1386static size_t get_input_buffer_size(uint32_t sample_rate,
1387 audio_format_t format,
1388 int channel_count)
1389{
1390 size_t size = 0;
1391
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001392 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1393 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001394
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001395 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
1396 /* ToDo: should use frame_size computed based on the format and
1397 channel_count here. */
1398 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001399
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001400 /* make sure the size is multiple of 64 */
1401 size += 0x3f;
1402 size &= ~0x3f;
1403
1404 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001405}
1406
1407static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1408{
1409 struct stream_out *out = (struct stream_out *)stream;
1410
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001411 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001412}
1413
1414static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1415{
1416 return -ENOSYS;
1417}
1418
1419static size_t out_get_buffer_size(const struct audio_stream *stream)
1420{
1421 struct stream_out *out = (struct stream_out *)stream;
1422
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001423 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001424 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001425 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1426 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428 return out->config.period_size * audio_stream_frame_size(stream);
1429}
1430
1431static uint32_t out_get_channels(const struct audio_stream *stream)
1432{
1433 struct stream_out *out = (struct stream_out *)stream;
1434
1435 return out->channel_mask;
1436}
1437
1438static audio_format_t out_get_format(const struct audio_stream *stream)
1439{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001440 struct stream_out *out = (struct stream_out *)stream;
1441
1442 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443}
1444
1445static int out_set_format(struct audio_stream *stream, audio_format_t format)
1446{
1447 return -ENOSYS;
1448}
1449
1450static int out_standby(struct audio_stream *stream)
1451{
1452 struct stream_out *out = (struct stream_out *)stream;
1453 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001454
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301455 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1456 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001457 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1458 /* Ignore standby in case of voip call because the voip output
1459 * stream is closed in adev_close_output_stream()
1460 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301461 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001462 return 0;
1463 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001465 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001466 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001467 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001469 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001470 if (out->pcm) {
1471 pcm_close(out->pcm);
1472 out->pcm = NULL;
1473 }
1474 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001475 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001476 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001477 out->gapless_mdata.encoder_delay = 0;
1478 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001479 if (out->compr != NULL) {
1480 compress_close(out->compr);
1481 out->compr = NULL;
1482 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001483 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001485 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 }
1487 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001488 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489 return 0;
1490}
1491
1492static int out_dump(const struct audio_stream *stream, int fd)
1493{
1494 return 0;
1495}
1496
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001497static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1498{
1499 int ret = 0;
1500 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001501 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001502 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001503 tmp_mdata.encoder_delay = 0;
1504 tmp_mdata.encoder_padding = 0;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001505
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001506 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001507 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001508 return -EINVAL;
1509 }
1510
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001511 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1512 if (ret >= 0) {
1513 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1514 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1515 ALOGV("ADTS format is set in offload mode");
1516 }
1517 out->send_new_metadata = 1;
1518 }
1519
Mingming Yin3ee55c62014-08-04 14:23:35 -07001520 if (out->format == AUDIO_FORMAT_FLAC) {
1521 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1522 if (ret >= 0) {
1523 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1524 out->send_new_metadata = 1;
1525 }
1526 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1527 if (ret >= 0) {
1528 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1529 out->send_new_metadata = 1;
1530 }
1531 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1532 if (ret >= 0) {
1533 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1534 out->send_new_metadata = 1;
1535 }
1536 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1537 if (ret >= 0) {
1538 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1539 out->send_new_metadata = 1;
1540 }
1541 }
1542
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001543 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1544 if(ret >= 0)
1545 is_meta_data_params = true;
1546 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1547 if(ret >= 0 )
1548 is_meta_data_params = true;
1549 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1550 if(ret >= 0 )
1551 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001552 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1553 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001554 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001555 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001556 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001557 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1558 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001559 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001560 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001561 }
1562
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001563 if(!is_meta_data_params) {
1564 ALOGV("%s: Not gapless meta data params", __func__);
1565 return 0;
1566 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001567 out->gapless_mdata = tmp_mdata;
1568 out->send_new_metadata = 1;
1569 ALOGV("%s new encoder delay %u and padding %u", __func__,
1570 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1571
1572 return 0;
1573}
1574
1575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001576static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1577{
1578 struct stream_out *out = (struct stream_out *)stream;
1579 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001580 struct audio_usecase *usecase;
1581 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 struct str_parms *parms;
1583 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001584 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001585 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586
sangwoobc677242013-08-08 16:53:43 +09001587 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001588 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001589 parms = str_parms_create_str(kvpairs);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001590 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1591 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001594 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001595
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001596 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301597 * When HDMI cable is unplugged/usb hs is disconnected the
1598 * music playback is paused and the policy manager sends routing=0
1599 * But the audioflingercontinues to write data until standby time
1600 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001601 * Avoid this by routing audio to speaker until standby.
1602 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301603 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1604 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001605 val == AUDIO_DEVICE_NONE) {
1606 val = AUDIO_DEVICE_OUT_SPEAKER;
1607 }
1608
1609 /*
1610 * select_devices() call below switches all the usecases on the same
1611 * backend to the new device. Refer to check_usecases_codec_backend() in
1612 * the select_devices(). But how do we undo this?
1613 *
1614 * For example, music playback is active on headset (deep-buffer usecase)
1615 * and if we go to ringtones and select a ringtone, low-latency usecase
1616 * will be started on headset+speaker. As we can't enable headset+speaker
1617 * and headset devices at the same time, select_devices() switches the music
1618 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1619 * So when the ringtone playback is completed, how do we undo the same?
1620 *
1621 * We are relying on the out_set_parameters() call on deep-buffer output,
1622 * once the ringtone playback is ended.
1623 * NOTE: We should not check if the current devices are same as new devices.
1624 * Because select_devices() must be called to switch back the music
1625 * playback to headset.
1626 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001627 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001628 out->devices = val;
1629
1630 if (!out->standby)
1631 select_devices(adev, out->usecase);
1632
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001633 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
Vidyakumar Athotaad34d572014-08-05 18:20:42 -07001634 !adev->voice.in_call &&
1635 (out == adev->primary_output)) {
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001636 ret = voice_start_call(adev);
Vidyakumar Athotaad34d572014-08-05 18:20:42 -07001637 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
1638 adev->voice.in_call &&
1639 (out == adev->primary_output)) {
Narsinga Rao Chella22d8d7a2014-02-06 14:05:14 -08001640 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001641 }
1642 }
1643
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001644 if ((adev->mode == AUDIO_MODE_NORMAL) &&
Vidyakumar Athotaad34d572014-08-05 18:20:42 -07001645 adev->voice.in_call &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001646 (out == adev->primary_output)) {
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001647 ret = voice_stop_call(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001651 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001653
1654 if (out == adev->primary_output) {
1655 pthread_mutex_lock(&adev->lock);
1656 audio_extn_set_parameters(adev, parms);
1657 pthread_mutex_unlock(&adev->lock);
1658 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001659 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001660 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001661 parse_compress_metadata(out, parms);
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001662 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001663 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -07001666 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667 return ret;
1668}
1669
1670static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1671{
1672 struct stream_out *out = (struct stream_out *)stream;
1673 struct str_parms *query = str_parms_create_str(keys);
1674 char *str;
1675 char value[256];
1676 struct str_parms *reply = str_parms_create();
1677 size_t i, j;
1678 int ret;
1679 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001680
1681 if (!query || !reply) {
1682 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1683 return NULL;
1684 }
1685
Eric Laurent994a6932013-07-17 11:51:42 -07001686 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001687 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1688 if (ret >= 0) {
1689 value[0] = '\0';
1690 i = 0;
1691 while (out->supported_channel_masks[i] != 0) {
1692 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1693 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1694 if (!first) {
1695 strcat(value, "|");
1696 }
1697 strcat(value, out_channels_name_to_enum_table[j].name);
1698 first = false;
1699 break;
1700 }
1701 }
1702 i++;
1703 }
1704 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1705 str = str_parms_to_str(reply);
1706 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001707 voice_extn_out_get_parameters(out, query, reply);
1708 str = str_parms_to_str(reply);
1709 if (!strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001710 free(str);
1711 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001712 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713 }
1714 str_parms_destroy(query);
1715 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001716 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717 return str;
1718}
1719
1720static uint32_t out_get_latency(const struct audio_stream_out *stream)
1721{
1722 struct stream_out *out = (struct stream_out *)stream;
1723
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001724 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
1726
1727 return (out->config.period_count * out->config.period_size * 1000) /
1728 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729}
1730
1731static int out_set_volume(struct audio_stream_out *stream, float left,
1732 float right)
1733{
Eric Laurenta9024de2013-04-04 09:19:12 -07001734 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001735 int volume[2];
1736
Eric Laurenta9024de2013-04-04 09:19:12 -07001737 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1738 /* only take left channel into account: the API is for stereo anyway */
1739 out->muted = (left == 0.0f);
1740 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001741 } else if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001742 char mixer_ctl_name[128];
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001743 struct audio_device *adev = out->dev;
1744 struct mixer_ctl *ctl;
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001745 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
1746 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001747
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001748 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
1749 "Compress Playback %d Volume", pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001750 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1751 if (!ctl) {
1752 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1753 __func__, mixer_ctl_name);
1754 return -EINVAL;
1755 }
1756 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
1757 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
1758 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
1759 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07001760 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762 return -ENOSYS;
1763}
1764
1765static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1766 size_t bytes)
1767{
1768 struct stream_out *out = (struct stream_out *)stream;
1769 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301770 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07001771 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301774
Naresh Tanniru80659832014-06-04 18:17:56 +05301775 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
1776 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301777 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301778 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301779 goto exit;
Naresh Tanniru80659832014-06-04 18:17:56 +05301780 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1781 //during SSR for compress usecase we should return error to flinger
1782 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
1783 pthread_mutex_unlock(&out->lock);
1784 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301785 }
1786 }
1787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001789 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001790 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001791 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
1792 ret = voice_extn_compress_voip_start_output_stream(out);
1793 else
1794 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001795 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001796 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001798 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799 goto exit;
1800 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001803 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001804 ALOGD("copl(%p): writing buffer (%d bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001805 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001806 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001807 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
1808 out->send_new_metadata = 0;
1809 }
1810
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001811 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05301812 if (ret < 0)
1813 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001814 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07001815 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05301816 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05301818 } else if (-ENETRESET == ret) {
1819 ALOGE("copl %s: received sound card offline state on compress write", __func__);
1820 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
1821 pthread_mutex_unlock(&out->lock);
1822 out_standby(&out->stream.common);
1823 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001824 }
Naresh Tanniru80659832014-06-04 18:17:56 +05301825 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001826 compress_start(out->compr);
1827 out->playback_started = 1;
1828 out->offload_state = OFFLOAD_STATE_PLAYING;
1829 }
1830 pthread_mutex_unlock(&out->lock);
1831 return ret;
1832 } else {
1833 if (out->pcm) {
1834 if (out->muted)
1835 memset((void *)buffer, 0, bytes);
1836 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
1837 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05301838 if (ret < 0)
1839 ret = -errno;
1840 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001841 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001842 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843 }
1844
1845exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05301846 /* ToDo: There may be a corner case when SSR happens back to back during
1847 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05301848 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05301849 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301850 }
1851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 pthread_mutex_unlock(&out->lock);
1853
1854 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001855 if (out->pcm)
1856 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05301857 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05301858 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05301859 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05301860 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05301861 out->standby = true;
1862 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 out_standby(&out->stream.common);
1864 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05301865 out_get_sample_rate(&out->stream.common));
1866
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 }
1868 return bytes;
1869}
1870
1871static int out_get_render_position(const struct audio_stream_out *stream,
1872 uint32_t *dsp_frames)
1873{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001874 struct stream_out *out = (struct stream_out *)stream;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001875 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05301876 ssize_t ret = -EINVAL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001877 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001878 pthread_mutex_lock(&out->lock);
1879 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05301880 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001881 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05301882 if (ret < 0)
1883 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001884 ALOGVV("%s rendered frames %d sample_rate %d",
1885 __func__, *dsp_frames, out->sample_rate);
1886 }
1887 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05301888 if (-ENETRESET == ret) {
1889 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
1890 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
1891 return -EINVAL;
1892 } else if(ret < 0) {
1893 ALOGE(" ERROR: Unable to get time stamp from compress driver");
1894 return -EINVAL;
1895 } else {
1896 return 0;
1897 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001898 } else
1899 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900}
1901
1902static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1903{
1904 return 0;
1905}
1906
1907static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1908{
1909 return 0;
1910}
1911
1912static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1913 int64_t *timestamp)
1914{
1915 return -EINVAL;
1916}
1917
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001918static int out_get_presentation_position(const struct audio_stream_out *stream,
1919 uint64_t *frames, struct timespec *timestamp)
1920{
1921 struct stream_out *out = (struct stream_out *)stream;
1922 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07001923 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001924
1925 pthread_mutex_lock(&out->lock);
1926
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001927 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07001928 if (out->compr != NULL) {
1929 compress_get_tstamp(out->compr, &dsp_frames,
1930 &out->sample_rate);
1931 ALOGVV("%s rendered frames %ld sample_rate %d",
1932 __func__, dsp_frames, out->sample_rate);
1933 *frames = dsp_frames;
1934 ret = 0;
1935 /* this is the best we can do */
1936 clock_gettime(CLOCK_MONOTONIC, timestamp);
1937 }
1938 } else {
1939 if (out->pcm) {
1940 size_t avail;
1941 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
1942 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07001943 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07001944 // This adjustment accounts for buffering after app processor.
1945 // It is based on estimated DSP latency per use case, rather than exact.
1946 signed_frames -=
1947 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
1948
Eric Laurent949a0892013-09-20 09:20:13 -07001949 // It would be unusual for this value to be negative, but check just in case ...
1950 if (signed_frames >= 0) {
1951 *frames = signed_frames;
1952 ret = 0;
1953 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001954 }
1955 }
1956 }
1957
1958 pthread_mutex_unlock(&out->lock);
1959
1960 return ret;
1961}
1962
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001963static int out_set_callback(struct audio_stream_out *stream,
1964 stream_callback_t callback, void *cookie)
1965{
1966 struct stream_out *out = (struct stream_out *)stream;
1967
1968 ALOGV("%s", __func__);
1969 pthread_mutex_lock(&out->lock);
1970 out->offload_callback = callback;
1971 out->offload_cookie = cookie;
1972 pthread_mutex_unlock(&out->lock);
1973 return 0;
1974}
1975
1976static int out_pause(struct audio_stream_out* stream)
1977{
1978 struct stream_out *out = (struct stream_out *)stream;
1979 int status = -ENOSYS;
1980 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001981 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001982 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001983 pthread_mutex_lock(&out->lock);
1984 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05301985 struct audio_device *adev = out->dev;
1986 int snd_scard_state = get_snd_card_state(adev);
1987
1988 if (SND_CARD_STATE_ONLINE == snd_scard_state)
1989 status = compress_pause(out->compr);
1990
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001991 out->offload_state = OFFLOAD_STATE_PAUSED;
1992 }
1993 pthread_mutex_unlock(&out->lock);
1994 }
1995 return status;
1996}
1997
1998static int out_resume(struct audio_stream_out* stream)
1999{
2000 struct stream_out *out = (struct stream_out *)stream;
2001 int status = -ENOSYS;
2002 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002003 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002004 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002005 status = 0;
2006 pthread_mutex_lock(&out->lock);
2007 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302008 struct audio_device *adev = out->dev;
2009 int snd_scard_state = get_snd_card_state(adev);
2010
2011 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2012 status = compress_resume(out->compr);
2013
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002014 out->offload_state = OFFLOAD_STATE_PLAYING;
2015 }
2016 pthread_mutex_unlock(&out->lock);
2017 }
2018 return status;
2019}
2020
2021static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2022{
2023 struct stream_out *out = (struct stream_out *)stream;
2024 int status = -ENOSYS;
2025 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002026 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002027 pthread_mutex_lock(&out->lock);
2028 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2029 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2030 else
2031 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2032 pthread_mutex_unlock(&out->lock);
2033 }
2034 return status;
2035}
2036
2037static int out_flush(struct audio_stream_out* stream)
2038{
2039 struct stream_out *out = (struct stream_out *)stream;
2040 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002041 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002042 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002043 pthread_mutex_lock(&out->lock);
2044 stop_compressed_output_l(out);
2045 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002046 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002047 return 0;
2048 }
2049 return -ENOSYS;
2050}
2051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052/** audio_stream_in implementation **/
2053static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2054{
2055 struct stream_in *in = (struct stream_in *)stream;
2056
2057 return in->config.rate;
2058}
2059
2060static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
2061{
2062 return -ENOSYS;
2063}
2064
2065static size_t in_get_buffer_size(const struct audio_stream *stream)
2066{
2067 struct stream_in *in = (struct stream_in *)stream;
2068
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002069 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2070 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002071 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2072 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002073
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074 return in->config.period_size * audio_stream_frame_size(stream);
2075}
2076
2077static uint32_t in_get_channels(const struct audio_stream *stream)
2078{
2079 struct stream_in *in = (struct stream_in *)stream;
2080
2081 return in->channel_mask;
2082}
2083
2084static audio_format_t in_get_format(const struct audio_stream *stream)
2085{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002086 struct stream_in *in = (struct stream_in *)stream;
2087
2088 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089}
2090
2091static int in_set_format(struct audio_stream *stream, audio_format_t format)
2092{
2093 return -ENOSYS;
2094}
2095
2096static int in_standby(struct audio_stream *stream)
2097{
2098 struct stream_in *in = (struct stream_in *)stream;
2099 struct audio_device *adev = in->dev;
2100 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302101 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2102 stream, in->usecase, use_case_table[in->usecase]);
2103
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002104
2105 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2106 /* Ignore standby in case of voip call because the voip input
2107 * stream is closed in adev_close_input_stream()
2108 */
2109 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2110 return status;
2111 }
2112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 pthread_mutex_lock(&in->lock);
2114 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002115 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002117 if (in->pcm) {
2118 pcm_close(in->pcm);
2119 in->pcm = NULL;
2120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002122 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123 }
2124 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002125 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 return status;
2127}
2128
2129static int in_dump(const struct audio_stream *stream, int fd)
2130{
2131 return 0;
2132}
2133
2134static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2135{
2136 struct stream_in *in = (struct stream_in *)stream;
2137 struct audio_device *adev = in->dev;
2138 struct str_parms *parms;
2139 char *str;
2140 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002141 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302143 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 parms = str_parms_create_str(kvpairs);
2145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002147 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002148
2149 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2150 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 val = atoi(value);
2152 /* no audio source uses val == 0 */
2153 if ((in->source != val) && (val != 0)) {
2154 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002155 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2156 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2157 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2158 (in->config.rate == 8000 || in->config.rate == 16000) &&
2159 (popcount(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002160 err = voice_extn_compress_voip_open_input_stream(in);
2161 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002162 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002163 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002164 }
2165 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 }
2167 }
2168
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002169 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2170 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171 val = atoi(value);
2172 if ((in->device != val) && (val != 0)) {
2173 in->device = val;
2174 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002175 if (!in->standby)
2176 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 }
2178 }
2179
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002180done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002182 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183
2184 str_parms_destroy(parms);
Eric Laurent994a6932013-07-17 11:51:42 -07002185 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 return ret;
2187}
2188
2189static char* in_get_parameters(const struct audio_stream *stream,
2190 const char *keys)
2191{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002192 struct stream_in *in = (struct stream_in *)stream;
2193 struct str_parms *query = str_parms_create_str(keys);
2194 char *str;
2195 char value[256];
2196 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002197
2198 if (!query || !reply) {
2199 ALOGE("in_get_parameters: failed to create query or reply");
2200 return NULL;
2201 }
2202
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002203 ALOGV("%s: enter: keys - %s", __func__, keys);
2204
2205 voice_extn_in_get_parameters(in, query, reply);
2206
2207 str = str_parms_to_str(reply);
2208 str_parms_destroy(query);
2209 str_parms_destroy(reply);
2210
2211 ALOGV("%s: exit: returns - %s", __func__, str);
2212 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213}
2214
2215static int in_set_gain(struct audio_stream_in *stream, float gain)
2216{
2217 return 0;
2218}
2219
2220static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2221 size_t bytes)
2222{
2223 struct stream_in *in = (struct stream_in *)stream;
2224 struct audio_device *adev = in->dev;
2225 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302226 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302229
2230 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302231 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302232 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302233 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302234 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302235 }
2236 }
2237
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002239 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002240 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2241 ret = voice_extn_compress_voip_start_input_stream(in);
2242 else
2243 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002244 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246 goto exit;
2247 }
2248 in->standby = 0;
2249 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250
2251 if (in->pcm) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002252 if (audio_extn_ssr_get_enabled() && popcount(in->channel_mask) == 6)
2253 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002254 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2255 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002256 else
2257 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302258 if (ret < 0)
2259 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 }
2261
2262 /*
2263 * Instead of writing zeroes here, we could trust the hardware
2264 * to always provide zeroes when muted.
2265 */
kunleizc5a639b2014-04-24 18:46:22 +08002266 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267 memset(buffer, 0, bytes);
2268
2269exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302270 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302271 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302272 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302273 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302274 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275 pthread_mutex_unlock(&in->lock);
2276
2277 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302278 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302279 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302280 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302281 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302282 in->standby = true;
2283 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302284 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285 in_standby(&in->stream.common);
2286 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
2287 usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302288 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289 }
2290 return bytes;
2291}
2292
2293static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
2294{
2295 return 0;
2296}
2297
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002298static int add_remove_audio_effect(const struct audio_stream *stream,
2299 effect_handle_t effect,
2300 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002301{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002302 struct stream_in *in = (struct stream_in *)stream;
2303 int status = 0;
2304 effect_descriptor_t desc;
2305
2306 status = (*effect)->get_descriptor(effect, &desc);
2307 if (status != 0)
2308 return status;
2309
2310 pthread_mutex_lock(&in->lock);
2311 pthread_mutex_lock(&in->dev->lock);
2312 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2313 in->enable_aec != enable &&
2314 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2315 in->enable_aec = enable;
2316 if (!in->standby)
2317 select_devices(in->dev, in->usecase);
2318 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002319 if (in->enable_ns != enable &&
2320 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2321 in->enable_ns = enable;
2322 if (!in->standby)
2323 select_devices(in->dev, in->usecase);
2324 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002325 pthread_mutex_unlock(&in->dev->lock);
2326 pthread_mutex_unlock(&in->lock);
2327
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328 return 0;
2329}
2330
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002331static int in_add_audio_effect(const struct audio_stream *stream,
2332 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333{
Eric Laurent994a6932013-07-17 11:51:42 -07002334 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002335 return add_remove_audio_effect(stream, effect, true);
2336}
2337
2338static int in_remove_audio_effect(const struct audio_stream *stream,
2339 effect_handle_t effect)
2340{
Eric Laurent994a6932013-07-17 11:51:42 -07002341 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002342 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343}
2344
2345static int adev_open_output_stream(struct audio_hw_device *dev,
2346 audio_io_handle_t handle,
2347 audio_devices_t devices,
2348 audio_output_flags_t flags,
2349 struct audio_config *config,
2350 struct audio_stream_out **stream_out)
2351{
2352 struct audio_device *adev = (struct audio_device *)dev;
2353 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002354 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002355 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302358
2359 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2360 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2361 ALOGE(" sound card is not active rejecting compress output open request");
2362 return -EINVAL;
2363 }
2364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2366
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302367 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2368 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2369 devices, flags, &out->stream);
2370
2371
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002372 if (!out) {
2373 return -ENOMEM;
2374 }
2375
2376 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2377 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379 if (devices == AUDIO_DEVICE_NONE)
2380 devices = AUDIO_DEVICE_OUT_SPEAKER;
2381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 out->flags = flags;
2383 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002384 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002385 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 out->sample_rate = config->sample_rate;
2387 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2388 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002389 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002390 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391
2392 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002393 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2394 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2395 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2396
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002397 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002398 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2399 ret = read_hdmi_channel_masks(out);
2400
2401 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2402 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002403 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002404 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002405 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002406
2407 if (config->sample_rate == 0)
2408 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2409 if (config->channel_mask == 0)
2410 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2411
2412 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2415 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416 out->config.rate = config->sample_rate;
2417 out->config.channels = popcount(out->channel_mask);
2418 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002419 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2420 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002421 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002422 ret = voice_extn_compress_voip_open_output_stream(out);
2423 if (ret != 0) {
2424 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2425 __func__, ret);
2426 goto error_open;
2427 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002428 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2429 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2430 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2431 ALOGE("%s: Unsupported Offload information", __func__);
2432 ret = -EINVAL;
2433 goto error_open;
2434 }
Mingming Yin90310102013-11-13 16:57:00 -08002435 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002436 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 ALOGE("%s: Unsupported audio format", __func__);
2438 ret = -EINVAL;
2439 goto error_open;
2440 }
2441
2442 out->compr_config.codec = (struct snd_codec *)
2443 calloc(1, sizeof(struct snd_codec));
2444
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002445 if (!out->compr_config.codec) {
2446 ret = -ENOMEM;
2447 goto error_open;
2448 }
2449
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002450 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002451 if (config->offload_info.channel_mask)
2452 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002453 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002454 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002455 config->offload_info.channel_mask = config->channel_mask;
2456 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002457 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002458 out->sample_rate = config->offload_info.sample_rate;
2459
2460 out->stream.set_callback = out_set_callback;
2461 out->stream.pause = out_pause;
2462 out->stream.resume = out_resume;
2463 out->stream.drain = out_drain;
2464 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002465 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002467 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002468 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002469 audio_extn_dolby_get_snd_codec_id(adev, out,
2470 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002471 else
2472 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002473 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002474 if (audio_is_offload_pcm(config->offload_info.format)) {
2475 out->compr_config.fragment_size =
2476 platform_get_pcm_offload_buffer_size(&config->offload_info);
2477 } else {
2478 out->compr_config.fragment_size =
2479 platform_get_compress_offload_buffer_size(&config->offload_info);
2480 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002481 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2482 out->compr_config.codec->sample_rate =
2483 compress_get_alsa_rate(config->offload_info.sample_rate);
2484 out->compr_config.codec->bit_rate =
2485 config->offload_info.bit_rate;
2486 out->compr_config.codec->ch_in =
2487 popcount(config->channel_mask);
2488 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002489 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490
Mingming Yin3ee55c62014-08-04 14:23:35 -07002491 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2492 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002493 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2494 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002495 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002496 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2497
Mingming Yin3ee55c62014-08-04 14:23:35 -07002498 if (out->bit_width == 24) {
2499 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2500 }
2501
2502 if (out->bit_width == 24 && !platform_check_24_bit_support()) {
2503 ALOGW("24 bit support is not enabled, using 16 bit backend");
2504 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
2505 }
2506
Amit Shekhar6f461b12014-08-01 14:52:58 -07002507 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
2508 out->compr_config.codec->options.flac_dec.sample_size = config->offload_info.bit_width;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002509
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002510 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2511 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002512
2513 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002514 out->offload_state = OFFLOAD_STATE_IDLE;
2515 out->playback_started = 0;
2516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002517 create_offload_callback_thread(out);
2518 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2519 __func__, config->offload_info.version,
2520 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002521 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002522 check_and_set_gapless_mode(adev);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002523
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002524 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2525 ret = voice_check_and_set_incall_music_usecase(adev, out);
2526 if (ret != 0) {
2527 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2528 __func__, ret);
2529 goto error_open;
2530 }
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002531 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002532 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2534 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002535 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002536 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002537 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002538 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002539 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002540 out->config = pcm_config_deep_buffer;
2541 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 }
2543
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002544 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2545 &adev->streams_output_cfg_list,
Amit Shekhar6f461b12014-08-01 14:52:58 -07002546 flags, format, out->sample_rate,
2547 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002548 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2549 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2550 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002551 if(adev->primary_output == NULL)
2552 adev->primary_output = out;
2553 else {
2554 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002555 ret = -EEXIST;
2556 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002557 }
2558 }
2559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 /* Check if this usecase is already existing */
2561 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07002562 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2563 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002566 ret = -EEXIST;
2567 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 }
2569 pthread_mutex_unlock(&adev->lock);
2570
2571 out->stream.common.get_sample_rate = out_get_sample_rate;
2572 out->stream.common.set_sample_rate = out_set_sample_rate;
2573 out->stream.common.get_buffer_size = out_get_buffer_size;
2574 out->stream.common.get_channels = out_get_channels;
2575 out->stream.common.get_format = out_get_format;
2576 out->stream.common.set_format = out_set_format;
2577 out->stream.common.standby = out_standby;
2578 out->stream.common.dump = out_dump;
2579 out->stream.common.set_parameters = out_set_parameters;
2580 out->stream.common.get_parameters = out_get_parameters;
2581 out->stream.common.add_audio_effect = out_add_audio_effect;
2582 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2583 out->stream.get_latency = out_get_latency;
2584 out->stream.set_volume = out_set_volume;
2585 out->stream.write = out_write;
2586 out->stream.get_render_position = out_get_render_position;
2587 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002588 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002591 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002592 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593
2594 config->format = out->stream.common.get_format(&out->stream.common);
2595 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
2596 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
2597
2598 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302599 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
2600 use_case_table[out->usecase]);
Eric Laurent994a6932013-07-17 11:51:42 -07002601 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002603
2604error_open:
2605 free(out);
2606 *stream_out = NULL;
2607 ALOGD("%s: exit: ret %d", __func__, ret);
2608 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609}
2610
2611static void adev_close_output_stream(struct audio_hw_device *dev,
2612 struct audio_stream_out *stream)
2613{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002614 struct stream_out *out = (struct stream_out *)stream;
2615 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002616 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002617
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302618 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
2619
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002620 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302621 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002622 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302623 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002624 if(ret != 0)
2625 ALOGE("%s: Compress voip output cannot be closed, error:%d",
2626 __func__, ret);
2627 }
2628 else
2629 out_standby(&stream->common);
2630
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002631 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002632 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002633 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002634 if (out->compr_config.codec != NULL)
2635 free(out->compr_config.codec);
2636 }
2637 pthread_cond_destroy(&out->cond);
2638 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002640 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641}
2642
2643static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2644{
2645 struct audio_device *adev = (struct audio_device *)dev;
2646 struct str_parms *parms;
2647 char *str;
2648 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002649 int val;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002650 int ret = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002652 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654
Naresh Tanniru4c630392014-05-12 01:05:52 +05302655 err = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
2656 if (err >= 0) {
2657 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302658 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302659 struct listnode *node;
2660 struct audio_usecase *usecase;
2661
Naresh Tanniru4c630392014-05-12 01:05:52 +05302662 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05302663 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2664
2665 pthread_mutex_lock(&adev->lock);
2666 //close compress session on OFFLINE status
2667 usecase = get_usecase_from_list(adev,USECASE_AUDIO_PLAYBACK_OFFLOAD);
2668 if (usecase && usecase->stream.out) {
2669 ALOGD(" %s closing compress session on OFFLINE state", __func__);
2670
2671 struct stream_out *out = usecase->stream.out;
2672
2673 pthread_mutex_unlock(&adev->lock);
2674 out_standby(&out->stream.common);
2675 } else
2676 pthread_mutex_unlock(&adev->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302677 } else if (strstr(snd_card_status, "ONLINE")) {
2678 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05302679 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302680 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302681 }
2682
2683 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002684 ret = voice_set_parameters(adev, parms);
2685 if (ret != 0)
2686 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002688 ret = platform_set_parameters(adev->platform, parms);
2689 if (ret != 0)
2690 goto done;
2691
2692 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
2693 if (err >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07002694 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2696 adev->bluetooth_nrec = true;
2697 else
2698 adev->bluetooth_nrec = false;
2699 }
2700
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002701 err = str_parms_get_str(parms, "screen_state", value, sizeof(value));
2702 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2704 adev->screen_off = false;
2705 else
2706 adev->screen_off = true;
2707 }
2708
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002709 err = str_parms_get_int(parms, "rotation", &val);
2710 if (err >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002711 bool reverse_speakers = false;
2712 switch(val) {
2713 // FIXME: note that the code below assumes that the speakers are in the correct placement
2714 // relative to the user when the device is rotated 90deg from its default rotation. This
2715 // assumption is device-specific, not platform-specific like this code.
2716 case 270:
2717 reverse_speakers = true;
2718 break;
2719 case 0:
2720 case 90:
2721 case 180:
2722 break;
2723 default:
2724 ALOGE("%s: unexpected rotation of %d", __func__, val);
2725 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002726 if (adev->speaker_lr_swap != reverse_speakers) {
2727 adev->speaker_lr_swap = reverse_speakers;
2728 // only update the selected device if there is active pcm playback
2729 struct audio_usecase *usecase;
2730 struct listnode *node;
2731 list_for_each(node, &adev->usecase_list) {
2732 usecase = node_to_item(node, struct audio_usecase, list);
2733 if (usecase->type == PCM_PLAYBACK) {
2734 select_devices(adev, usecase->id);
2735 break;
2736 }
2737 }
2738 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002739 }
2740
Mingming Yin514a8bc2014-07-29 15:22:21 -07002741 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
2742 if (ret >= 0) {
2743 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2744 adev->bt_wb_speech_enabled = true;
2745 else
2746 adev->bt_wb_speech_enabled = false;
2747 }
2748
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07002749 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002750
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002751done:
2752 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002753 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002754 ALOGV("%s: exit with code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 return ret;
2756}
2757
2758static char* adev_get_parameters(const struct audio_hw_device *dev,
2759 const char *keys)
2760{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002761 struct audio_device *adev = (struct audio_device *)dev;
2762 struct str_parms *reply = str_parms_create();
2763 struct str_parms *query = str_parms_create_str(keys);
2764 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05302765 char value[256] = {0};
2766 int ret = 0;
2767
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002768 if (!query || !reply) {
2769 ALOGE("adev_get_parameters: failed to create query or reply");
2770 return NULL;
2771 }
2772
Naresh Tannirud7205b62014-06-20 02:54:48 +05302773 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
2774 sizeof(value));
2775 if (ret >=0) {
2776 int val = 1;
2777 pthread_mutex_lock(&adev->snd_card_status.lock);
2778 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
2779 val = 0;
2780 pthread_mutex_unlock(&adev->snd_card_status.lock);
2781 str_parms_add_int(reply, "SND_CARD_STATUS", val);
2782 goto exit;
2783 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002784
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002785 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002786 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002787 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002788 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05302789 pthread_mutex_unlock(&adev->lock);
2790
Naresh Tannirud7205b62014-06-20 02:54:48 +05302791exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002792 str = str_parms_to_str(reply);
2793 str_parms_destroy(query);
2794 str_parms_destroy(reply);
2795
2796 ALOGV("%s: exit: returns - %s", __func__, str);
2797 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798}
2799
2800static int adev_init_check(const struct audio_hw_device *dev)
2801{
2802 return 0;
2803}
2804
2805static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
2806{
Haynes Mathew George5191a852013-09-11 14:19:36 -07002807 int ret;
2808 struct audio_device *adev = (struct audio_device *)dev;
2809 pthread_mutex_lock(&adev->lock);
2810 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07002811 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07002812 pthread_mutex_unlock(&adev->lock);
2813 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814}
2815
2816static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
2817{
2818 return -ENOSYS;
2819}
2820
2821static int adev_get_master_volume(struct audio_hw_device *dev,
2822 float *volume)
2823{
2824 return -ENOSYS;
2825}
2826
2827static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
2828{
2829 return -ENOSYS;
2830}
2831
2832static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
2833{
2834 return -ENOSYS;
2835}
2836
2837static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
2838{
2839 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 pthread_mutex_lock(&adev->lock);
2841 if (adev->mode != mode) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002842 ALOGD("%s mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002843 adev->mode = mode;
2844 }
2845 pthread_mutex_unlock(&adev->lock);
2846 return 0;
2847}
2848
2849static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
2850{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002851 int ret;
2852
2853 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002854 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002855 ret = voice_set_mic_mute((struct audio_device *)dev, state);
2856 pthread_mutex_unlock(&adev->lock);
2857
2858 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859}
2860
2861static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
2862{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002863 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864 return 0;
2865}
2866
2867static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
2868 const struct audio_config *config)
2869{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 int channel_count = popcount(config->channel_mask);
2871
2872 return get_input_buffer_size(config->sample_rate, config->format, channel_count);
2873}
2874
2875static int adev_open_input_stream(struct audio_hw_device *dev,
2876 audio_io_handle_t handle,
2877 audio_devices_t devices,
2878 struct audio_config *config,
2879 struct audio_stream_in **stream_in)
2880{
2881 struct audio_device *adev = (struct audio_device *)dev;
2882 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002883 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884 int channel_count = popcount(config->channel_mask);
2885
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887 *stream_in = NULL;
2888 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
2889 return -EINVAL;
2890
2891 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002892
2893 if (!in) {
2894 ALOGE("failed to allocate input stream");
2895 return -ENOMEM;
2896 }
2897
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302898 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
2899 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2900 devices, &in->stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002901
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07002902 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
2903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002904 in->stream.common.get_sample_rate = in_get_sample_rate;
2905 in->stream.common.set_sample_rate = in_set_sample_rate;
2906 in->stream.common.get_buffer_size = in_get_buffer_size;
2907 in->stream.common.get_channels = in_get_channels;
2908 in->stream.common.get_format = in_get_format;
2909 in->stream.common.set_format = in_set_format;
2910 in->stream.common.standby = in_standby;
2911 in->stream.common.dump = in_dump;
2912 in->stream.common.set_parameters = in_set_parameters;
2913 in->stream.common.get_parameters = in_get_parameters;
2914 in->stream.common.add_audio_effect = in_add_audio_effect;
2915 in->stream.common.remove_audio_effect = in_remove_audio_effect;
2916 in->stream.set_gain = in_set_gain;
2917 in->stream.read = in_read;
2918 in->stream.get_input_frames_lost = in_get_input_frames_lost;
2919
2920 in->device = devices;
2921 in->source = AUDIO_SOURCE_DEFAULT;
2922 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923 in->standby = 1;
2924 in->channel_mask = config->channel_mask;
2925
2926 /* Update config params with the requested sample rate and channels */
2927 in->usecase = USECASE_AUDIO_RECORD;
2928 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002930 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002932 if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002933 if(audio_extn_ssr_get_enabled()) {
2934 if(audio_extn_ssr_init(adev, in)) {
2935 ALOGE("%s: audio_extn_ssr_init failed", __func__);
2936 ret = -EINVAL;
2937 goto err_open;
2938 }
2939 } else {
2940 ret = -EINVAL;
2941 goto err_open;
2942 }
Mingming Yine62d7842013-10-25 16:26:03 -07002943 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002944 audio_extn_compr_cap_format_supported(config->format) &&
2945 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Mingming Yine62d7842013-10-25 16:26:03 -07002946 audio_extn_compr_cap_init(adev, in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002947 } else {
2948 in->config.channels = channel_count;
2949 frame_size = audio_stream_frame_size((struct audio_stream *)in);
2950 buffer_size = get_input_buffer_size(config->sample_rate,
2951 config->format,
2952 channel_count);
2953 in->config.period_size = buffer_size / frame_size;
2954 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955
2956 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002957 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002958 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959
2960err_open:
2961 free(in);
2962 *stream_in = NULL;
2963 return ret;
2964}
2965
2966static void adev_close_input_stream(struct audio_hw_device *dev,
2967 struct audio_stream_in *stream)
2968{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002969 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002970 struct stream_in *in = (struct stream_in *)stream;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302971 struct audio_device *adev = in->dev;
2972
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302973 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002974
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002975 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302976 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002977 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302978 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002979 if (ret != 0)
2980 ALOGE("%s: Compress voip input cannot be closed, error:%d",
2981 __func__, ret);
2982 } else
2983 in_standby(&stream->common);
2984
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002985 if (audio_extn_ssr_get_enabled() && (popcount(in->channel_mask) == 6)) {
2986 audio_extn_ssr_deinit();
2987 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988 free(stream);
2989
Mingming Yine62d7842013-10-25 16:26:03 -07002990 if(audio_extn_compr_cap_enabled() &&
2991 audio_extn_compr_cap_format_supported(in->config.format))
2992 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 return;
2994}
2995
2996static int adev_dump(const audio_hw_device_t *device, int fd)
2997{
2998 return 0;
2999}
3000
3001static int adev_close(hw_device_t *device)
3002{
3003 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003004
3005 if (!adev)
3006 return 0;
3007
3008 pthread_mutex_lock(&adev_init_lock);
3009
3010 if ((--audio_device_ref_count) == 0) {
Kiran Kandide144c82013-11-20 15:58:32 -08003011 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003012 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003013 audio_route_free(adev->audio_route);
3014 free(adev->snd_dev_ref_cnt);
3015 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003016 free(device);
3017 adev = NULL;
3018 }
3019 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 return 0;
3021}
3022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023static int adev_open(const hw_module_t *module, const char *name,
3024 hw_device_t **device)
3025{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003026 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003028 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3030
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003031 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003032 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003033 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003034 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003035 ALOGD("%s: returning existing instance of adev", __func__);
3036 ALOGD("%s: exit", __func__);
3037 pthread_mutex_unlock(&adev_init_lock);
3038 return 0;
3039 }
3040
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 adev = calloc(1, sizeof(struct audio_device));
3042
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003043 if (!adev) {
3044 pthread_mutex_unlock(&adev_init_lock);
3045 return -ENOMEM;
3046 }
3047
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003048 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3051 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3052 adev->device.common.module = (struct hw_module_t *)module;
3053 adev->device.common.close = adev_close;
3054
3055 adev->device.init_check = adev_init_check;
3056 adev->device.set_voice_volume = adev_set_voice_volume;
3057 adev->device.set_master_volume = adev_set_master_volume;
3058 adev->device.get_master_volume = adev_get_master_volume;
3059 adev->device.set_master_mute = adev_set_master_mute;
3060 adev->device.get_master_mute = adev_get_master_mute;
3061 adev->device.set_mode = adev_set_mode;
3062 adev->device.set_mic_mute = adev_set_mic_mute;
3063 adev->device.get_mic_mute = adev_get_mic_mute;
3064 adev->device.set_parameters = adev_set_parameters;
3065 adev->device.get_parameters = adev_get_parameters;
3066 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3067 adev->device.open_output_stream = adev_open_output_stream;
3068 adev->device.close_output_stream = adev_close_output_stream;
3069 adev->device.open_input_stream = adev_open_input_stream;
3070 adev->device.close_input_stream = adev_close_input_stream;
3071 adev->device.dump = adev_dump;
3072
3073 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003075 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003076 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003079 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003080 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003081 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3082 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003083 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003084 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003085 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003086 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003087 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303088
3089 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3090 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003092 adev->platform = platform_init(adev);
3093 if (!adev->platform) {
3094 free(adev->snd_dev_ref_cnt);
3095 free(adev);
3096 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3097 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003098 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003099 return -EINVAL;
3100 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003101
Naresh Tanniru4c630392014-05-12 01:05:52 +05303102 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3103
Eric Laurentc4aef752013-09-12 17:45:53 -07003104 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3105 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3106 if (adev->visualizer_lib == NULL) {
3107 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3108 } else {
3109 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3110 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003111 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003112 "visualizer_hal_start_output");
3113 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003114 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003115 "visualizer_hal_stop_output");
3116 }
3117 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003118 audio_extn_listen_init(adev, adev->snd_card);
Eric Laurentc4aef752013-09-12 17:45:53 -07003119
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003120 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3121 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3122 if (adev->offload_effects_lib == NULL) {
3123 ALOGE("%s: DLOPEN failed for %s", __func__,
3124 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3125 } else {
3126 ALOGV("%s: DLOPEN successful for %s", __func__,
3127 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3128 adev->offload_effects_start_output =
3129 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3130 "offload_effects_bundle_hal_start_output");
3131 adev->offload_effects_stop_output =
3132 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3133 "offload_effects_bundle_hal_stop_output");
3134 }
3135 }
3136
Mingming Yin514a8bc2014-07-29 15:22:21 -07003137 adev->bt_wb_speech_enabled = false;
3138
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 *device = &adev->device.common;
3140
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003141 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3142 &adev->streams_output_cfg_list);
3143
Kiran Kandi910e1862013-10-29 13:29:42 -07003144 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003145 pthread_mutex_unlock(&adev_init_lock);
3146
Eric Laurent994a6932013-07-17 11:51:42 -07003147 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 return 0;
3149}
3150
Mingming Yin07972cc2014-06-06 17:11:23 -07003151int pcm_ioctl(struct pcm *pcm, int request, ...)
3152{
3153 va_list ap;
3154 void * arg;
3155 int pcm_fd = *(int*)pcm;
3156
3157 va_start(ap, request);
3158 arg = va_arg(ap, void *);
3159 va_end(ap);
3160
3161 return ioctl(pcm_fd, request, arg);
3162}
3163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164static struct hw_module_methods_t hal_module_methods = {
3165 .open = adev_open,
3166};
3167
3168struct audio_module HAL_MODULE_INFO_SYM = {
3169 .common = {
3170 .tag = HARDWARE_MODULE_TAG,
3171 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3172 .hal_api_version = HARDWARE_HAL_API_VERSION,
3173 .id = AUDIO_HARDWARE_MODULE_ID,
3174 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003175 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176 .methods = &hal_module_methods,
3177 },
3178};