blob: 8a0ca37ee94f602240e1c03b0cd261218f6afedd [file] [log] [blame]
Simon Wilson15f60a82012-04-24 20:56:32 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
18/*#define LOG_NDEBUG 0*/
19
20#include <errno.h>
21#include <pthread.h>
22#include <stdint.h>
23#include <stdlib.h>
24#include <sys/time.h>
Eric Laurent688880c2012-09-07 16:46:00 -070025#include <fcntl.h>
Simon Wilson15f60a82012-04-24 20:56:32 -070026
27#include <cutils/log.h>
28#include <cutils/properties.h>
29#include <cutils/str_parms.h>
30
31#include <hardware/audio.h>
32#include <hardware/hardware.h>
33
Simon Wilsonf051bcf2012-09-26 14:10:07 -070034#include <linux/videodev2.h>
35#include <videodev2_exynos_media.h>
36
Simon Wilson15f60a82012-04-24 20:56:32 -070037#include <system/audio.h>
38
39#include <tinyalsa/asoundlib.h>
40
41#include <audio_utils/resampler.h>
Simon Wilson759c6f02013-01-15 16:38:56 -080042#include <audio_route/audio_route.h>
Simon Wilson15f60a82012-04-24 20:56:32 -070043
Eric Laurenta989ebf2012-10-15 15:14:44 -070044#include <BubbleLevel.h>
45
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -070046#include <eS305VoiceProcessing.h>
47
Simon Wilson15f60a82012-04-24 20:56:32 -070048#define PCM_CARD 0
Simon Wilson56d84e22012-08-17 13:55:27 -070049#define PCM_CARD_SPDIF 1
50#define PCM_TOTAL 2
51
Simon Wilson15f60a82012-04-24 20:56:32 -070052#define PCM_DEVICE 0
Glenn Kastene0aa8f32012-08-17 09:26:58 -070053#define PCM_DEVICE_DEEP 1
Simon Wilsona282d2f2012-09-12 16:14:24 -070054#define PCM_DEVICE_VOICE 2
55#define PCM_DEVICE_SCO 3
Simon Wilson15f60a82012-04-24 20:56:32 -070056
Simon Wilson759c6f02013-01-15 16:38:56 -080057#define MIXER_CARD 0
58
Eric Laurent1a0c0a72012-08-24 11:29:04 -070059/* duration in ms of volume ramp applied when starting capture to remove plop */
60#define CAPTURE_START_RAMP_MS 100
61
Eric Laurentb2c0b4f2012-09-21 11:42:48 -070062/* default sampling for HDMI multichannel output */
63#define HDMI_MULTI_DEFAULT_SAMPLING_RATE 44100
64/* maximum number of channel mask configurations supported. Currently the primary
65 * output only supports 1 (stereo) and the multi channel HDMI output 2 (5.1 and 7.1) */
66#define MAX_SUPPORTED_CHANNEL_MASKS 2
67
68#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
69
Simon Wilson15f60a82012-04-24 20:56:32 -070070struct pcm_config pcm_config = {
71 .channels = 2,
72 .rate = 44100,
Glenn Kasten22db1772012-09-04 09:26:50 -070073 .period_size = 256,
Glenn Kastenb9366272012-07-18 14:06:12 -070074 .period_count = 2,
Simon Wilson15f60a82012-04-24 20:56:32 -070075 .format = PCM_FORMAT_S16_LE,
76};
77
Glenn Kasten7ecf6232012-09-28 12:01:31 -070078struct pcm_config pcm_config_in = {
79 .channels = 2,
80 .rate = 44100,
81 .period_size = 1024,
82 .period_count = 2,
83 .format = PCM_FORMAT_S16_LE,
84};
85
Simon Wilsona282d2f2012-09-12 16:14:24 -070086struct pcm_config pcm_config_sco = {
87 .channels = 1,
88 .rate = 8000,
89 .period_size = 128,
90 .period_count = 2,
91 .format = PCM_FORMAT_S16_LE,
92};
93
Glenn Kastene0aa8f32012-08-17 09:26:58 -070094struct pcm_config pcm_config_deep = {
95 .channels = 2,
96 .rate = 44100,
97 /* FIXME This is an arbitrary number, may change.
98 * Dynamic configuration based on screen on/off is not implemented;
99 * let's see what power consumption is first to see if necessary.
100 */
101 .period_size = 8192,
102 .period_count = 2,
103 .format = PCM_FORMAT_S16_LE,
104};
105
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700106struct pcm_config pcm_config_hdmi_multi = {
107 .channels = 6, /* changed when the stream is opened */
108 .rate = HDMI_MULTI_DEFAULT_SAMPLING_RATE,
109 .period_size = 1024,
110 .period_count = 4,
111 .format = PCM_FORMAT_S16_LE,
112};
113
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700114enum output_type {
115 OUTPUT_DEEP_BUF, // deep PCM buffers output stream
116 OUTPUT_LOW_LATENCY, // low latency output stream
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700117 OUTPUT_HDMI, // HDMI multi channel
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700118 OUTPUT_TOTAL
119};
120
Simon Wilson15f60a82012-04-24 20:56:32 -0700121struct audio_device {
122 struct audio_hw_device hw_device;
123
124 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700125 audio_devices_t out_device; /* "or" of stream_out.device for all active output streams */
Eric Laurent42531fa2012-10-03 09:06:14 -0700126 audio_devices_t in_device;
Simon Wilson15f60a82012-04-24 20:56:32 -0700127 bool mic_mute;
128 struct audio_route *ar;
Eric Laurent87532032012-07-16 13:53:20 -0700129 audio_source_t input_source;
130 int cur_route_id; /* current route ID: combination of input source
131 * and output device IDs */
Simon Wilsona282d2f2012-09-12 16:14:24 -0700132 struct pcm *pcm_voice_out;
133 struct pcm *pcm_sco_out;
134 struct pcm *pcm_voice_in;
135 struct pcm *pcm_sco_in;
Eric Laurent688880c2012-09-07 16:46:00 -0700136 int es305_preset;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700137 int es305_new_mode;
Eric Laurent688880c2012-09-07 16:46:00 -0700138 int es305_mode;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700139 int hdmi_drv_fd;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700140 struct bubble_level *bubble_level;
Eric Laurentb52afc82013-01-18 15:12:57 -0800141 audio_channel_mask_t in_channel_mask;
Eric Laurent4f1aece2013-04-19 17:10:25 -0700142 unsigned int sco_on_count;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700143
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700144 struct stream_out *outputs[OUTPUT_TOTAL];
Simon Wilson15f60a82012-04-24 20:56:32 -0700145};
146
147struct stream_out {
148 struct audio_stream_out stream;
149
150 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Simon Wilson56d84e22012-08-17 13:55:27 -0700151 struct pcm *pcm[PCM_TOTAL];
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700152 struct pcm_config config;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700153 unsigned int pcm_device;
Simon Wilson56d84e22012-08-17 13:55:27 -0700154 bool standby; /* true if all PCMs are inactive */
Eric Laurent42531fa2012-10-03 09:06:14 -0700155 audio_devices_t device;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700156 /* FIXME: when HDMI multichannel output is active, other outputs must be disabled as
157 * HDMI and WM1811 share the same I2S. This means that notifications and other sounds are
158 * silent when watching a 5.1 movie. */
159 bool disabled;
160 audio_channel_mask_t channel_mask;
161 /* Array of supported channel mask configurations. +1 so that the last entry is always 0 */
162 audio_channel_mask_t supported_channel_masks[MAX_SUPPORTED_CHANNEL_MASKS + 1];
Eric Laurent3948fda2013-04-04 09:24:22 -0700163 bool muted;
Glenn Kasten21169cb2013-08-20 15:36:18 -0700164 uint64_t written; /* total frames written, not cleared when entering standby */
Simon Wilson15f60a82012-04-24 20:56:32 -0700165
166 struct audio_device *dev;
167};
168
169struct stream_in {
170 struct audio_stream_in stream;
171
172 pthread_mutex_t lock; /* see note below on mutex acquisition order */
173 struct pcm *pcm;
174 bool standby;
175
176 unsigned int requested_rate;
177 struct resampler_itfe *resampler;
178 struct resampler_buffer_provider buf_provider;
179 int16_t *buffer;
180 size_t frames_in;
181 int read_status;
Eric Laurent87532032012-07-16 13:53:20 -0700182 audio_source_t input_source;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700183 audio_io_handle_t io_handle;
Eric Laurent42531fa2012-10-03 09:06:14 -0700184 audio_devices_t device;
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700185 uint16_t ramp_vol;
186 uint16_t ramp_step;
187 size_t ramp_frames;
Eric Laurentb52afc82013-01-18 15:12:57 -0800188 audio_channel_mask_t channel_mask;
Simon Wilson15f60a82012-04-24 20:56:32 -0700189
190 struct audio_device *dev;
191};
192
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700193#define STRING_TO_ENUM(string) { #string, string }
194
195struct string_to_enum {
196 const char *name;
197 uint32_t value;
198};
199
200const struct string_to_enum out_channels_name_to_enum_table[] = {
201 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
202 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
203 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
204};
205
Eric Laurent87532032012-07-16 13:53:20 -0700206enum {
207 OUT_DEVICE_SPEAKER,
208 OUT_DEVICE_HEADSET,
209 OUT_DEVICE_HEADPHONES,
210 OUT_DEVICE_BT_SCO,
211 OUT_DEVICE_SPEAKER_AND_HEADSET,
212 OUT_DEVICE_TAB_SIZE, /* number of rows in route_configs[][] */
213 OUT_DEVICE_NONE,
Eric Laurent87532032012-07-16 13:53:20 -0700214 OUT_DEVICE_CNT
215};
216
217enum {
218 IN_SOURCE_MIC,
219 IN_SOURCE_CAMCORDER,
220 IN_SOURCE_VOICE_RECOGNITION,
221 IN_SOURCE_VOICE_COMMUNICATION,
222 IN_SOURCE_TAB_SIZE, /* number of lines in route_configs[][] */
223 IN_SOURCE_NONE,
Eric Laurent87532032012-07-16 13:53:20 -0700224 IN_SOURCE_CNT
225};
226
Eric Laurent688880c2012-09-07 16:46:00 -0700227enum {
Eric Laurent688880c2012-09-07 16:46:00 -0700228 ES305_MODE_DEFAULT,
Eric Laurenta989ebf2012-10-15 15:14:44 -0700229 ES305_MODE_LEVEL,
Eric Laurent688880c2012-09-07 16:46:00 -0700230 ES305_NUM_MODES,
231};
232
Eric Laurent42531fa2012-10-03 09:06:14 -0700233int get_output_device_id(audio_devices_t device)
Eric Laurent87532032012-07-16 13:53:20 -0700234{
Eric Laurent6a466d72012-08-28 12:13:38 -0700235 if (device == AUDIO_DEVICE_NONE)
Eric Laurent87532032012-07-16 13:53:20 -0700236 return OUT_DEVICE_NONE;
237
238 if (popcount(device) == 2) {
239 if ((device == (AUDIO_DEVICE_OUT_SPEAKER |
240 AUDIO_DEVICE_OUT_WIRED_HEADSET)) ||
241 (device == (AUDIO_DEVICE_OUT_SPEAKER |
242 AUDIO_DEVICE_OUT_WIRED_HEADPHONE)))
243 return OUT_DEVICE_SPEAKER_AND_HEADSET;
244 else
Simon Wilsona6b94122012-09-12 12:52:24 -0700245 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700246 }
247
248 if (popcount(device) != 1)
Simon Wilsona6b94122012-09-12 12:52:24 -0700249 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700250
251 switch (device) {
252 case AUDIO_DEVICE_OUT_SPEAKER:
253 return OUT_DEVICE_SPEAKER;
254 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
255 return OUT_DEVICE_HEADSET;
256 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
257 return OUT_DEVICE_HEADPHONES;
258 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
259 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
260 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
261 return OUT_DEVICE_BT_SCO;
262 default:
Simon Wilsona6b94122012-09-12 12:52:24 -0700263 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700264 }
265}
266
267int get_input_source_id(audio_source_t source)
268{
269 switch (source) {
270 case AUDIO_SOURCE_DEFAULT:
271 return IN_SOURCE_NONE;
272 case AUDIO_SOURCE_MIC:
273 return IN_SOURCE_MIC;
274 case AUDIO_SOURCE_CAMCORDER:
275 return IN_SOURCE_CAMCORDER;
276 case AUDIO_SOURCE_VOICE_RECOGNITION:
277 return IN_SOURCE_VOICE_RECOGNITION;
278 case AUDIO_SOURCE_VOICE_COMMUNICATION:
279 return IN_SOURCE_VOICE_COMMUNICATION;
280 default:
Simon Wilsona6b94122012-09-12 12:52:24 -0700281 return IN_SOURCE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700282 }
283}
284
285struct route_config {
286 const char * const output_route;
287 const char * const input_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700288 int es305_preset[ES305_NUM_MODES]; // es305 preset for this route.
289 // -1 means es305 bypass
Eric Laurent87532032012-07-16 13:53:20 -0700290};
291
292const struct route_config media_speaker = {
293 "media-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700294 "media-main-mic",
295 { ES305_PRESET_OFF,
296 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700297};
298
299const struct route_config media_headphones = {
300 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700301 "media-main-mic",
302 { ES305_PRESET_OFF,
303 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700304};
305
306const struct route_config media_headset = {
307 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700308 "media-headset-mic",
309 { ES305_PRESET_OFF,
310 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700311};
312
313const struct route_config camcorder_speaker = {
314 "media-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700315 "media-second-mic",
Jean-Michel Trivi48277c52012-10-08 10:22:59 -0700316 { ES305_PRESET_CAMCORDER,
317 ES305_PRESET_CAMCORDER }
Eric Laurent87532032012-07-16 13:53:20 -0700318};
319
320const struct route_config camcorder_headphones = {
321 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700322 "media-second-mic",
Jean-Michel Trivi48277c52012-10-08 10:22:59 -0700323 { ES305_PRESET_CAMCORDER,
324 ES305_PRESET_CAMCORDER }
Eric Laurent87532032012-07-16 13:53:20 -0700325};
326
327const struct route_config voice_rec_speaker = {
328 "voice-rec-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700329 "voice-rec-main-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700330 { ES305_PRESET_ASRA_HANDHELD,
331 ES305_PRESET_ASRA_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700332};
333
334const struct route_config voice_rec_headphones = {
335 "voice-rec-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700336 "voice-rec-main-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700337 { ES305_PRESET_ASRA_HANDHELD,
338 ES305_PRESET_ASRA_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700339};
340
341const struct route_config voice_rec_headset = {
342 "voice-rec-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700343 "voice-rec-headset-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700344 { ES305_PRESET_ASRA_HEADSET,
345 ES305_PRESET_ASRA_HEADSET }
Eric Laurent87532032012-07-16 13:53:20 -0700346};
347
348const struct route_config communication_speaker = {
349 "communication-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700350 "communication-main-mic",
351 { ES305_PRESET_VOIP_HANDHELD,
352 ES305_PRESET_VOIP_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700353};
354
355const struct route_config communication_headphones = {
356 "communication-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700357 "communication-main-mic",
358 { ES305_PRESET_VOIP_HEADPHONES,
359 ES305_PRESET_VOIP_HP_DESKTOP}
Eric Laurent87532032012-07-16 13:53:20 -0700360};
361
362const struct route_config communication_headset = {
363 "communication-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700364 "communication-headset-mic",
365 { ES305_PRESET_VOIP_HEADSET,
366 ES305_PRESET_VOIP_HEADSET }
Eric Laurent87532032012-07-16 13:53:20 -0700367};
368
369const struct route_config speaker_and_headphones = {
370 "speaker-and-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700371 "main-mic",
372 { ES305_PRESET_CURRENT,
373 ES305_PRESET_CURRENT }
Eric Laurent87532032012-07-16 13:53:20 -0700374};
375
376const struct route_config bluetooth_sco = {
377 "bt-sco-headset",
Eric Laurent688880c2012-09-07 16:46:00 -0700378 "bt-sco-mic",
379 { ES305_PRESET_OFF,
380 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700381};
382
383const struct route_config * const route_configs[IN_SOURCE_TAB_SIZE]
384 [OUT_DEVICE_TAB_SIZE] = {
385 { /* IN_SOURCE_MIC */
386 &media_speaker, /* OUT_DEVICE_SPEAKER */
387 &media_headset, /* OUT_DEVICE_HEADSET */
388 &media_headphones, /* OUT_DEVICE_HEADPHONES */
389 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
390 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
391 },
392 { /* IN_SOURCE_CAMCORDER */
393 &camcorder_speaker, /* OUT_DEVICE_SPEAKER */
394 &camcorder_headphones, /* OUT_DEVICE_HEADSET */
395 &camcorder_headphones, /* OUT_DEVICE_HEADPHONES */
396 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
397 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
398 },
399 { /* IN_SOURCE_VOICE_RECOGNITION */
400 &voice_rec_speaker, /* OUT_DEVICE_SPEAKER */
401 &voice_rec_headset, /* OUT_DEVICE_HEADSET */
402 &voice_rec_headphones, /* OUT_DEVICE_HEADPHONES */
403 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
404 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
405 },
406 { /* IN_SOURCE_VOICE_COMMUNICATION */
407 &communication_speaker, /* OUT_DEVICE_SPEAKER */
408 &communication_headset, /* OUT_DEVICE_HEADSET */
409 &communication_headphones, /* OUT_DEVICE_HEADPHONES */
410 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
411 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
412 }
413};
414
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700415static int do_out_standby(struct stream_out *out);
416
Simon Wilson15f60a82012-04-24 20:56:32 -0700417/**
418 * NOTE: when multiple mutexes have to be acquired, always respect the
419 * following order: hw device > in stream > out stream
420 */
421
422/* Helper functions */
423
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700424static int open_hdmi_driver(struct audio_device *adev)
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700425{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700426 if (adev->hdmi_drv_fd < 0) {
427 adev->hdmi_drv_fd = open("/dev/video16", O_RDWR);
428 if (adev->hdmi_drv_fd < 0)
429 ALOGE("%s cannot open video16 (%d)", __func__, adev->hdmi_drv_fd);
430 }
431 return adev->hdmi_drv_fd;
432}
433
434/* must be called with hw device mutex locked */
435static int enable_hdmi_audio(struct audio_device *adev, int enable)
436{
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700437 int ret;
438 struct v4l2_control ctrl;
439
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700440 ret = open_hdmi_driver(adev);
441 if (ret < 0)
442 return ret;
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700443
444 ctrl.id = V4L2_CID_TV_ENABLE_HDMI_AUDIO;
445 ctrl.value = !!enable;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700446 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_S_CTRL, &ctrl);
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700447
448 if (ret < 0)
449 ALOGE("V4L2_CID_TV_ENABLE_HDMI_AUDIO ioctl error (%d)", errno);
450
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700451 return ret;
452}
453
454/* must be called with hw device mutex locked */
455static int read_hdmi_channel_masks(struct audio_device *adev, struct stream_out *out) {
456 int ret;
457 struct v4l2_control ctrl;
458
459 ret = open_hdmi_driver(adev);
460 if (ret < 0)
461 return ret;
462
463 ctrl.id = V4L2_CID_TV_MAX_AUDIO_CHANNELS;
464 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_G_CTRL, &ctrl);
465 if (ret < 0) {
466 ALOGE("V4L2_CID_TV_MAX_AUDIO_CHANNELS ioctl error (%d)", errno);
467 return ret;
468 }
469
470 ALOGV("%s ioctl %d got %d max channels", __func__, ret, ctrl.value);
471
472 if (ctrl.value != 6 && ctrl.value != 8)
473 return -ENOSYS;
474
475 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
476 if (ctrl.value == 8)
477 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
478
479 return ret;
480}
481
482/* must be called with hw device mutex locked */
483static int set_hdmi_channels(struct audio_device *adev, int channels) {
484 int ret;
485 struct v4l2_control ctrl;
486
487 ret = open_hdmi_driver(adev);
488 if (ret < 0)
489 return ret;
490
491 ctrl.id = V4L2_CID_TV_SET_NUM_CHANNELS;
492 ctrl.value = channels;
493 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_S_CTRL, &ctrl);
494 if (ret < 0)
495 ALOGE("V4L2_CID_TV_SET_NUM_CHANNELS ioctl error (%d)", errno);
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700496
497 return ret;
498}
499
Simon Wilson15f60a82012-04-24 20:56:32 -0700500static void select_devices(struct audio_device *adev)
501{
Eric Laurent6a466d72012-08-28 12:13:38 -0700502 int output_device_id = get_output_device_id(adev->out_device);
Eric Laurent87532032012-07-16 13:53:20 -0700503 int input_source_id = get_input_source_id(adev->input_source);
Simon Wilsonc4006be2012-08-17 11:23:38 -0700504 const char *output_route = NULL;
505 const char *input_route = NULL;
Eric Laurent87532032012-07-16 13:53:20 -0700506 int new_route_id;
Eric Laurent688880c2012-09-07 16:46:00 -0700507 int new_es305_preset = -1;
Simon Wilson15f60a82012-04-24 20:56:32 -0700508
Simon Wilson759c6f02013-01-15 16:38:56 -0800509 audio_route_reset(adev->ar);
Simon Wilsonc4006be2012-08-17 11:23:38 -0700510
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700511 enable_hdmi_audio(adev, adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL);
Simon Wilsonab5dda62012-10-01 17:44:38 -0700512
Eric Laurent87532032012-07-16 13:53:20 -0700513 new_route_id = (1 << (input_source_id + OUT_DEVICE_CNT)) + (1 << output_device_id);
Eric Laurenta989ebf2012-10-15 15:14:44 -0700514 if ((new_route_id == adev->cur_route_id) && (adev->es305_mode == adev->es305_new_mode))
Eric Laurent87532032012-07-16 13:53:20 -0700515 return;
516 adev->cur_route_id = new_route_id;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700517 adev->es305_mode = adev->es305_new_mode;
Simon Wilson15f60a82012-04-24 20:56:32 -0700518
Eric Laurent87532032012-07-16 13:53:20 -0700519 if (input_source_id != IN_SOURCE_NONE) {
520 if (output_device_id != OUT_DEVICE_NONE) {
521 input_route =
522 route_configs[input_source_id][output_device_id]->input_route;
523 output_route =
524 route_configs[input_source_id][output_device_id]->output_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700525 new_es305_preset =
526 route_configs[input_source_id][output_device_id]->es305_preset[adev->es305_mode];
Eric Laurent87532032012-07-16 13:53:20 -0700527 } else {
Eric Laurent42531fa2012-10-03 09:06:14 -0700528 switch (adev->in_device) {
Eric Laurent4f1aece2013-04-19 17:10:25 -0700529 case AUDIO_DEVICE_IN_WIRED_HEADSET & ~AUDIO_DEVICE_BIT_IN:
Eric Laurent42531fa2012-10-03 09:06:14 -0700530 output_device_id = OUT_DEVICE_HEADSET;
531 break;
Eric Laurent4f1aece2013-04-19 17:10:25 -0700532 case AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET & ~AUDIO_DEVICE_BIT_IN:
Eric Laurent42531fa2012-10-03 09:06:14 -0700533 output_device_id = OUT_DEVICE_BT_SCO;
534 break;
535 default:
536 output_device_id = OUT_DEVICE_SPEAKER;
537 break;
538 }
Eric Laurent87532032012-07-16 13:53:20 -0700539 input_route =
Eric Laurent42531fa2012-10-03 09:06:14 -0700540 route_configs[input_source_id][output_device_id]->input_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700541 new_es305_preset =
Eric Laurent42531fa2012-10-03 09:06:14 -0700542 route_configs[input_source_id][output_device_id]->es305_preset[adev->es305_mode];
Eric Laurent87532032012-07-16 13:53:20 -0700543 }
Eric Laurentb52afc82013-01-18 15:12:57 -0800544 // disable noise suppression when capturing front and back mic for voice recognition
545 if ((adev->input_source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
Jean-Michel Trivi3f467de2013-06-06 15:26:01 -0700546 (adev->in_channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK))
Eric Laurentb52afc82013-01-18 15:12:57 -0800547 new_es305_preset = -1;
Eric Laurent87532032012-07-16 13:53:20 -0700548 } else {
549 if (output_device_id != OUT_DEVICE_NONE) {
550 output_route =
551 route_configs[IN_SOURCE_MIC][output_device_id]->output_route;
552 }
553 }
554
555 ALOGV("select_devices() devices %#x input src %d output route %s input route %s",
Eric Laurent6a466d72012-08-28 12:13:38 -0700556 adev->out_device, adev->input_source,
Simon Wilsonc4006be2012-08-17 11:23:38 -0700557 output_route ? output_route : "none",
558 input_route ? input_route : "none");
Eric Laurent87532032012-07-16 13:53:20 -0700559
Simon Wilsonc4006be2012-08-17 11:23:38 -0700560 if (output_route)
561 audio_route_apply_path(adev->ar, output_route);
562 if (input_route)
563 audio_route_apply_path(adev->ar, input_route);
Simon Wilson15f60a82012-04-24 20:56:32 -0700564
Eric Laurent688880c2012-09-07 16:46:00 -0700565 if ((new_es305_preset != ES305_PRESET_CURRENT) &&
566 (new_es305_preset != adev->es305_preset)) {
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700567 ALOGV(" select_devices() changing es305 preset from %d to %d",
568 adev->es305_preset, new_es305_preset);
569 if (eS305_UsePreset(new_es305_preset) == 0) {
Eric Laurent688880c2012-09-07 16:46:00 -0700570 adev->es305_preset = new_es305_preset;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700571 }
Eric Laurent688880c2012-09-07 16:46:00 -0700572 }
573
Simon Wilson759c6f02013-01-15 16:38:56 -0800574 audio_route_update_mixer(adev->ar);
Simon Wilson15f60a82012-04-24 20:56:32 -0700575}
576
Eric Laurenta989ebf2012-10-15 15:14:44 -0700577void bubblelevel_callback(bool is_level, void *user_data)
578{
579 struct audio_device *adev = (struct audio_device *)user_data;
580 int es305_mode;
581
582 if (is_level)
583 es305_mode = ES305_MODE_LEVEL;
584 else
585 es305_mode = ES305_MODE_DEFAULT;
586
587 pthread_mutex_lock(&adev->lock);
588 if (es305_mode != adev->es305_mode) {
589 adev->es305_new_mode = es305_mode;
590 select_devices(adev);
591 ALOGV("bubblelevel_callback is_level %d es305_mode %d", is_level, es305_mode);
592 }
593 pthread_mutex_unlock(&adev->lock);
594}
595
Eric Laurent429f24d2012-11-02 14:37:38 -0700596/* must be called with hw device mutex locked */
597bool get_bubblelevel(struct audio_device *adev)
598{
599 if (!adev->bubble_level) {
600 adev->bubble_level = bubble_level_create();
601 if (adev->bubble_level)
602 adev->bubble_level->set_callback(adev->bubble_level, bubblelevel_callback, adev);
603 }
604 return (adev->bubble_level != NULL);
605}
606
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700607static void force_non_hdmi_out_standby(struct audio_device *adev)
608{
609 enum output_type type;
610 struct stream_out *out;
611
612 for (type = 0; type < OUTPUT_TOTAL; ++type) {
613 out = adev->outputs[type];
614 if (type == OUTPUT_HDMI || !out)
615 continue;
616 pthread_mutex_lock(&out->lock);
617 do_out_standby(out);
618 pthread_mutex_unlock(&out->lock);
619 }
620}
621
Eric Laurent4f1aece2013-04-19 17:10:25 -0700622/* must be called with the hw device mutex locked, OK to hold other mutexes */
623static void start_bt_sco(struct audio_device *adev) {
624 if (adev->sco_on_count++ > 0)
625 return;
626
Glenn Kasten21169cb2013-08-20 15:36:18 -0700627 adev->pcm_voice_out = pcm_open(PCM_CARD, PCM_DEVICE_VOICE, PCM_OUT | PCM_MONOTONIC,
Eric Laurent4f1aece2013-04-19 17:10:25 -0700628 &pcm_config_sco);
629 if (adev->pcm_voice_out && !pcm_is_ready(adev->pcm_voice_out)) {
630 ALOGE("pcm_open(VOICE_OUT) failed: %s", pcm_get_error(adev->pcm_voice_out));
631 goto err_voice_out;
632 }
Glenn Kasten21169cb2013-08-20 15:36:18 -0700633 adev->pcm_sco_out = pcm_open(PCM_CARD, PCM_DEVICE_SCO, PCM_OUT | PCM_MONOTONIC,
Eric Laurent4f1aece2013-04-19 17:10:25 -0700634 &pcm_config_sco);
635 if (adev->pcm_sco_out && !pcm_is_ready(adev->pcm_sco_out)) {
636 ALOGE("pcm_open(SCO_OUT) failed: %s", pcm_get_error(adev->pcm_sco_out));
637 goto err_sco_out;
638 }
639 adev->pcm_voice_in = pcm_open(PCM_CARD, PCM_DEVICE_VOICE, PCM_IN,
640 &pcm_config_sco);
641 if (adev->pcm_voice_in && !pcm_is_ready(adev->pcm_voice_in)) {
642 ALOGE("pcm_open(VOICE_IN) failed: %s", pcm_get_error(adev->pcm_voice_in));
643 goto err_voice_in;
644 }
645 adev->pcm_sco_in = pcm_open(PCM_CARD, PCM_DEVICE_SCO, PCM_IN,
646 &pcm_config_sco);
647 if (adev->pcm_sco_in && !pcm_is_ready(adev->pcm_sco_in)) {
648 ALOGE("pcm_open(SCO_IN) failed: %s", pcm_get_error(adev->pcm_sco_in));
649 goto err_sco_in;
650 }
651
652 pcm_start(adev->pcm_voice_out);
653 pcm_start(adev->pcm_sco_out);
654 pcm_start(adev->pcm_voice_in);
655 pcm_start(adev->pcm_sco_in);
656
657 return;
658
659err_sco_in:
660 pcm_close(adev->pcm_sco_in);
661err_voice_in:
662 pcm_close(adev->pcm_voice_in);
663err_sco_out:
664 pcm_close(adev->pcm_sco_out);
665err_voice_out:
666 pcm_close(adev->pcm_voice_out);
667}
668
669/* must be called with the hw device mutex locked, OK to hold other mutexes */
670static void stop_bt_sco(struct audio_device *adev) {
671 if (adev->sco_on_count == 0 || --adev->sco_on_count > 0)
672 return;
673
674 pcm_stop(adev->pcm_voice_out);
675 pcm_stop(adev->pcm_sco_out);
676 pcm_stop(adev->pcm_voice_in);
677 pcm_stop(adev->pcm_sco_in);
678
679 pcm_close(adev->pcm_voice_out);
680 pcm_close(adev->pcm_sco_out);
681 pcm_close(adev->pcm_voice_in);
682 pcm_close(adev->pcm_sco_in);
683}
684
Simon Wilson15f60a82012-04-24 20:56:32 -0700685/* must be called with hw device and output stream mutexes locked */
686static int start_output_stream(struct stream_out *out)
687{
688 struct audio_device *adev = out->dev;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700689 int type;
690
691 if (out == adev->outputs[OUTPUT_HDMI]) {
692 force_non_hdmi_out_standby(adev);
693 } else if (adev->outputs[OUTPUT_HDMI] && !adev->outputs[OUTPUT_HDMI]->standby) {
694 out->disabled = true;
695 return 0;
696 }
697
698 out->disabled = false;
Simon Wilson15f60a82012-04-24 20:56:32 -0700699
Simon Wilson56d84e22012-08-17 13:55:27 -0700700 if (out->device & (AUDIO_DEVICE_OUT_SPEAKER |
701 AUDIO_DEVICE_OUT_WIRED_HEADSET |
702 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
Simon Wilsona282d2f2012-09-12 16:14:24 -0700703 AUDIO_DEVICE_OUT_AUX_DIGITAL |
704 AUDIO_DEVICE_OUT_ALL_SCO)) {
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700705
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700706 out->pcm[PCM_CARD] = pcm_open(PCM_CARD, out->pcm_device,
Glenn Kasten21169cb2013-08-20 15:36:18 -0700707 PCM_OUT | PCM_MONOTONIC, &out->config);
Simon Wilson15f60a82012-04-24 20:56:32 -0700708
Simon Wilson56d84e22012-08-17 13:55:27 -0700709 if (out->pcm[PCM_CARD] && !pcm_is_ready(out->pcm[PCM_CARD])) {
710 ALOGE("pcm_open(PCM_CARD) failed: %s",
711 pcm_get_error(out->pcm[PCM_CARD]));
712 pcm_close(out->pcm[PCM_CARD]);
713 return -ENOMEM;
714 }
715 }
716
717 if (out->device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700718 out->pcm[PCM_CARD_SPDIF] = pcm_open(PCM_CARD_SPDIF, out->pcm_device,
Glenn Kasten21169cb2013-08-20 15:36:18 -0700719 PCM_OUT | PCM_MONOTONIC, &out->config);
Simon Wilson56d84e22012-08-17 13:55:27 -0700720
721 if (out->pcm[PCM_CARD_SPDIF] &&
722 !pcm_is_ready(out->pcm[PCM_CARD_SPDIF])) {
723 ALOGE("pcm_open(PCM_CARD_SPDIF) failed: %s",
724 pcm_get_error(out->pcm[PCM_CARD_SPDIF]));
725 pcm_close(out->pcm[PCM_CARD_SPDIF]);
726 return -ENOMEM;
727 }
Simon Wilson15f60a82012-04-24 20:56:32 -0700728 }
729
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700730 adev->out_device |= out->device;
Eric Laurent87532032012-07-16 13:53:20 -0700731 select_devices(adev);
732
Eric Laurent4f1aece2013-04-19 17:10:25 -0700733 if (out->device & AUDIO_DEVICE_OUT_ALL_SCO)
734 start_bt_sco(adev);
735
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700736 if (out->device & AUDIO_DEVICE_OUT_AUX_DIGITAL)
737 set_hdmi_channels(adev, out->config.channels);
738
Eric Laurenta989ebf2012-10-15 15:14:44 -0700739 /* anticipate level measurement in case we start capture later */
Eric Laurent429f24d2012-11-02 14:37:38 -0700740 if (get_bubblelevel(adev))
741 adev->bubble_level->poll_once(adev->bubble_level);
Eric Laurenta989ebf2012-10-15 15:14:44 -0700742
Simon Wilson15f60a82012-04-24 20:56:32 -0700743 return 0;
744}
745
746/* must be called with hw device and input stream mutexes locked */
747static int start_input_stream(struct stream_in *in)
748{
749 struct audio_device *adev = in->dev;
750
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700751 in->pcm = pcm_open(PCM_CARD, PCM_DEVICE, PCM_IN, &pcm_config_in);
Simon Wilson15f60a82012-04-24 20:56:32 -0700752
753 if (in->pcm && !pcm_is_ready(in->pcm)) {
754 ALOGE("pcm_open() failed: %s", pcm_get_error(in->pcm));
755 pcm_close(in->pcm);
756 return -ENOMEM;
757 }
758
759 /* if no supported sample rate is available, use the resampler */
760 if (in->resampler)
761 in->resampler->reset(in->resampler);
762
Eric Laurentf4231822012-08-22 16:06:38 -0700763 in->frames_in = 0;
Eric Laurent87532032012-07-16 13:53:20 -0700764 adev->input_source = in->input_source;
Eric Laurent42531fa2012-10-03 09:06:14 -0700765 adev->in_device = in->device;
Jean-Michel Trivi3f467de2013-06-06 15:26:01 -0700766 adev->in_channel_mask = in->channel_mask;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700767
768 eS305_SetActiveIoHandle(in->io_handle);
Eric Laurent87532032012-07-16 13:53:20 -0700769 select_devices(adev);
770
Eric Laurent4f1aece2013-04-19 17:10:25 -0700771 if (in->device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)
772 start_bt_sco(adev);
773
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700774 /* initialize volume ramp */
775 in->ramp_frames = (CAPTURE_START_RAMP_MS * in->requested_rate) / 1000;
776 in->ramp_step = (uint16_t)(USHRT_MAX / in->ramp_frames);
777 in->ramp_vol = 0;;
778
Eric Laurent429f24d2012-11-02 14:37:38 -0700779 if (get_bubblelevel(adev)) {
780 adev->bubble_level->set_poll_interval(adev->bubble_level, BL_POLL_INTERVAL_MIN_SEC);
781 adev->bubble_level->start_polling(adev->bubble_level);
782 }
Eric Laurenta989ebf2012-10-15 15:14:44 -0700783
Simon Wilson15f60a82012-04-24 20:56:32 -0700784 return 0;
785}
786
787static size_t get_input_buffer_size(unsigned int sample_rate,
788 audio_format_t format,
789 unsigned int channel_count)
790{
791 size_t size;
792
793 /*
794 * take resampling into account and return the closest majoring
795 * multiple of 16 frames, as audioflinger expects audio buffers to
796 * be a multiple of 16 frames
797 */
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700798 size = (pcm_config_in.period_size * sample_rate) / pcm_config_in.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -0700799 size = ((size + 15) / 16) * 16;
800
801 return size * channel_count * audio_bytes_per_sample(format);
802}
803
804static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
805 struct resampler_buffer* buffer)
806{
807 struct stream_in *in;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700808 size_t i;
Simon Wilson15f60a82012-04-24 20:56:32 -0700809
810 if (buffer_provider == NULL || buffer == NULL)
811 return -EINVAL;
812
813 in = (struct stream_in *)((char *)buffer_provider -
814 offsetof(struct stream_in, buf_provider));
815
816 if (in->pcm == NULL) {
817 buffer->raw = NULL;
818 buffer->frame_count = 0;
819 in->read_status = -ENODEV;
820 return -ENODEV;
821 }
822
823 if (in->frames_in == 0) {
824 in->read_status = pcm_read(in->pcm,
825 (void*)in->buffer,
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700826 pcm_frames_to_bytes(in->pcm, pcm_config_in.period_size));
Simon Wilson15f60a82012-04-24 20:56:32 -0700827 if (in->read_status != 0) {
828 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
829 buffer->raw = NULL;
830 buffer->frame_count = 0;
831 return in->read_status;
832 }
Eric Laurentd7abdd02012-07-27 14:54:41 -0700833
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700834 in->frames_in = pcm_config_in.period_size;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700835
836 /* Do stereo to mono conversion in place by discarding right channel */
Eric Laurentb52afc82013-01-18 15:12:57 -0800837 if (in->channel_mask == AUDIO_CHANNEL_IN_MONO)
838 for (i = 1; i < in->frames_in; i++)
839 in->buffer[i] = in->buffer[i * 2];
Simon Wilson15f60a82012-04-24 20:56:32 -0700840 }
841
842 buffer->frame_count = (buffer->frame_count > in->frames_in) ?
843 in->frames_in : buffer->frame_count;
Eric Laurentb52afc82013-01-18 15:12:57 -0800844 buffer->i16 = in->buffer +
845 (pcm_config_in.period_size - in->frames_in) * popcount(in->channel_mask);
Simon Wilson15f60a82012-04-24 20:56:32 -0700846
847 return in->read_status;
848
849}
850
851static void release_buffer(struct resampler_buffer_provider *buffer_provider,
852 struct resampler_buffer* buffer)
853{
854 struct stream_in *in;
855
856 if (buffer_provider == NULL || buffer == NULL)
857 return;
858
859 in = (struct stream_in *)((char *)buffer_provider -
860 offsetof(struct stream_in, buf_provider));
861
862 in->frames_in -= buffer->frame_count;
863}
864
865/* read_frames() reads frames from kernel driver, down samples to capture rate
866 * if necessary and output the number of frames requested to the buffer specified */
867static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
868{
869 ssize_t frames_wr = 0;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700870 size_t frame_size = audio_stream_frame_size(&in->stream.common);
Simon Wilson15f60a82012-04-24 20:56:32 -0700871
872 while (frames_wr < frames) {
873 size_t frames_rd = frames - frames_wr;
874 if (in->resampler != NULL) {
875 in->resampler->resample_from_provider(in->resampler,
876 (int16_t *)((char *)buffer +
Eric Laurentd7abdd02012-07-27 14:54:41 -0700877 frames_wr * frame_size),
Simon Wilson15f60a82012-04-24 20:56:32 -0700878 &frames_rd);
879 } else {
880 struct resampler_buffer buf = {
881 { raw : NULL, },
882 frame_count : frames_rd,
883 };
884 get_next_buffer(&in->buf_provider, &buf);
885 if (buf.raw != NULL) {
886 memcpy((char *)buffer +
Eric Laurentd7abdd02012-07-27 14:54:41 -0700887 frames_wr * frame_size,
Simon Wilson15f60a82012-04-24 20:56:32 -0700888 buf.raw,
Eric Laurentd7abdd02012-07-27 14:54:41 -0700889 buf.frame_count * frame_size);
Simon Wilson15f60a82012-04-24 20:56:32 -0700890 frames_rd = buf.frame_count;
891 }
892 release_buffer(&in->buf_provider, &buf);
893 }
894 /* in->read_status is updated by getNextBuffer() also called by
895 * in->resampler->resample_from_provider() */
896 if (in->read_status != 0)
897 return in->read_status;
898
899 frames_wr += frames_rd;
900 }
901 return frames_wr;
902}
903
904/* API functions */
905
906static uint32_t out_get_sample_rate(const struct audio_stream *stream)
907{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700908 struct stream_out *out = (struct stream_out *)stream;
909
910 return out->config.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -0700911}
912
913static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
914{
915 return -ENOSYS;
916}
917
918static size_t out_get_buffer_size(const struct audio_stream *stream)
919{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700920 struct stream_out *out = (struct stream_out *)stream;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700921
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700922 return out->config.period_size *
923 audio_stream_frame_size((struct audio_stream *)stream);
Simon Wilson15f60a82012-04-24 20:56:32 -0700924}
925
Glenn Kastenca1414b2012-06-25 10:38:47 -0700926static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
Simon Wilson15f60a82012-04-24 20:56:32 -0700927{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700928 struct stream_out *out = (struct stream_out *)stream;
929
930 return out->channel_mask;
Simon Wilson15f60a82012-04-24 20:56:32 -0700931}
932
933static audio_format_t out_get_format(const struct audio_stream *stream)
934{
935 return AUDIO_FORMAT_PCM_16_BIT;
936}
937
938static int out_set_format(struct audio_stream *stream, audio_format_t format)
939{
940 return -ENOSYS;
941}
942
Glenn Kasten068b84e2012-09-26 12:34:51 -0700943/* Return the set of output devices associated with active streams
944 * other than out. Assumes out is non-NULL and out->dev is locked.
945 */
946static audio_devices_t output_devices(struct stream_out *out)
947{
948 struct audio_device *dev = out->dev;
949 enum output_type type;
950 audio_devices_t devices = AUDIO_DEVICE_NONE;
951
952 for (type = 0; type < OUTPUT_TOTAL; ++type) {
953 struct stream_out *other = dev->outputs[type];
954 if (other && (other != out) && !other->standby) {
955 /* safe to access other stream without a mutex,
956 * because we hold the dev lock,
957 * which prevents the other stream from being closed
958 */
959 devices |= other->device;
960 }
961 }
962
963 return devices;
964}
965
Simon Wilson459d5bd2012-08-21 12:18:07 -0700966static int do_out_standby(struct stream_out *out)
Simon Wilson15f60a82012-04-24 20:56:32 -0700967{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700968 struct audio_device *adev = out->dev;
Simon Wilson56d84e22012-08-17 13:55:27 -0700969 int i;
Simon Wilson15f60a82012-04-24 20:56:32 -0700970
Simon Wilson15f60a82012-04-24 20:56:32 -0700971 if (!out->standby) {
Simon Wilson56d84e22012-08-17 13:55:27 -0700972 for (i = 0; i < PCM_TOTAL; i++) {
973 if (out->pcm[i]) {
974 pcm_close(out->pcm[i]);
975 out->pcm[i] = NULL;
976 }
977 }
Simon Wilson15f60a82012-04-24 20:56:32 -0700978 out->standby = true;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700979
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700980 if (out == adev->outputs[OUTPUT_HDMI]) {
981 /* force standby on low latency output stream so that it can reuse HDMI driver if
982 * necessary when restarted */
983 force_non_hdmi_out_standby(adev);
984 }
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700985
Eric Laurent4f1aece2013-04-19 17:10:25 -0700986 if (out->device & AUDIO_DEVICE_OUT_ALL_SCO)
987 stop_bt_sco(adev);
988
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700989 /* re-calculate the set of active devices from other streams */
990 adev->out_device = output_devices(out);
Simon Wilson79a2e012012-10-19 14:20:33 -0700991
992 /* Skip resetting the mixer if no output device is active */
993 if (adev->out_device)
994 select_devices(adev);
Simon Wilson15f60a82012-04-24 20:56:32 -0700995 }
996
Simon Wilson459d5bd2012-08-21 12:18:07 -0700997 return 0;
998}
999
1000static int out_standby(struct audio_stream *stream)
1001{
1002 struct stream_out *out = (struct stream_out *)stream;
1003 int ret;
1004
1005 pthread_mutex_lock(&out->dev->lock);
1006 pthread_mutex_lock(&out->lock);
1007
1008 ret = do_out_standby(out);
1009
Simon Wilson15f60a82012-04-24 20:56:32 -07001010 pthread_mutex_unlock(&out->lock);
1011 pthread_mutex_unlock(&out->dev->lock);
1012
Simon Wilson459d5bd2012-08-21 12:18:07 -07001013 return ret;
Simon Wilson15f60a82012-04-24 20:56:32 -07001014}
1015
1016static int out_dump(const struct audio_stream *stream, int fd)
1017{
1018 return 0;
1019}
1020
1021static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1022{
1023 struct stream_out *out = (struct stream_out *)stream;
1024 struct audio_device *adev = out->dev;
1025 struct str_parms *parms;
1026 char value[32];
1027 int ret;
1028 unsigned int val;
1029
1030 parms = str_parms_create_str(kvpairs);
1031
1032 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
1033 value, sizeof(value));
1034 pthread_mutex_lock(&adev->lock);
Eric Laurent87532032012-07-16 13:53:20 -07001035 pthread_mutex_lock(&out->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001036 if (ret >= 0) {
1037 val = atoi(value);
Eric Laurent87532032012-07-16 13:53:20 -07001038 if ((out->device != val) && (val != 0)) {
Simon Wilson459d5bd2012-08-21 12:18:07 -07001039 /* Force standby if moving to/from SPDIF or if the output
1040 * device changes when in SPDIF mode */
1041 if (((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
Eric Laurent6a466d72012-08-28 12:13:38 -07001042 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
1043 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) {
Simon Wilson459d5bd2012-08-21 12:18:07 -07001044 do_out_standby(out);
1045 }
1046
Eric Laurent4f1aece2013-04-19 17:10:25 -07001047 /* force output standby to start or stop SCO pcm stream if needed */
Simon Wilsona282d2f2012-09-12 16:14:24 -07001048 if ((val & AUDIO_DEVICE_OUT_ALL_SCO) ^
Eric Laurent4f1aece2013-04-19 17:10:25 -07001049 (out->device & AUDIO_DEVICE_OUT_ALL_SCO)) {
1050 do_out_standby(out);
Simon Wilsona282d2f2012-09-12 16:14:24 -07001051 }
1052
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001053 if (!out->standby && (out == adev->outputs[OUTPUT_HDMI] ||
1054 !adev->outputs[OUTPUT_HDMI] ||
1055 adev->outputs[OUTPUT_HDMI]->standby)) {
1056 adev->out_device = output_devices(out) | val;
Eric Laurent87532032012-07-16 13:53:20 -07001057 select_devices(adev);
1058 }
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001059 out->device = val;
Simon Wilson15f60a82012-04-24 20:56:32 -07001060 }
1061 }
Eric Laurent87532032012-07-16 13:53:20 -07001062 pthread_mutex_unlock(&out->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001063 pthread_mutex_unlock(&adev->lock);
1064
1065 str_parms_destroy(parms);
1066 return ret;
1067}
1068
1069static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
1070{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001071 struct stream_out *out = (struct stream_out *)stream;
1072 struct str_parms *query = str_parms_create_str(keys);
1073 char *str;
1074 char value[256];
1075 struct str_parms *reply = str_parms_create();
1076 size_t i, j;
1077 int ret;
1078 bool first = true;
1079
1080 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1081 if (ret >= 0) {
1082 value[0] = '\0';
1083 i = 0;
1084 /* the last entry in supported_channel_masks[] is always 0 */
1085 while (out->supported_channel_masks[i] != 0) {
1086 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1087 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1088 if (!first) {
1089 strcat(value, "|");
1090 }
1091 strcat(value, out_channels_name_to_enum_table[j].name);
1092 first = false;
1093 break;
1094 }
1095 }
1096 i++;
1097 }
1098 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1099 str = str_parms_to_str(reply);
1100 } else {
1101 str = strdup(keys);
1102 }
1103
1104 str_parms_destroy(query);
1105 str_parms_destroy(reply);
1106 return str;
Simon Wilson15f60a82012-04-24 20:56:32 -07001107}
1108
1109static uint32_t out_get_latency(const struct audio_stream_out *stream)
1110{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001111 struct stream_out *out = (struct stream_out *)stream;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001112
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001113 return (out->config.period_size * out->config.period_count * 1000) /
1114 out->config.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -07001115}
1116
1117static int out_set_volume(struct audio_stream_out *stream, float left,
1118 float right)
1119{
Eric Laurent3948fda2013-04-04 09:24:22 -07001120 struct stream_out *out = (struct stream_out *)stream;
1121 struct audio_device *adev = out->dev;
1122
1123 if (out == adev->outputs[OUTPUT_HDMI]) {
1124 /* only take left channel into account: the API is for stereo anyway */
1125 out->muted = (left == 0.0f);
1126 return 0;
1127 }
Simon Wilson15f60a82012-04-24 20:56:32 -07001128 return -ENOSYS;
1129}
1130
1131static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
1132 size_t bytes)
1133{
Glenn Kastenf2d98022013-08-30 16:20:49 -07001134 int ret = 0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001135 struct stream_out *out = (struct stream_out *)stream;
1136 struct audio_device *adev = out->dev;
Simon Wilson56d84e22012-08-17 13:55:27 -07001137 int i;
Simon Wilson15f60a82012-04-24 20:56:32 -07001138
1139 /*
1140 * acquiring hw device mutex systematically is useful if a low
1141 * priority thread is waiting on the output stream mutex - e.g.
1142 * executing out_set_parameters() while holding the hw device
1143 * mutex
1144 */
1145 pthread_mutex_lock(&adev->lock);
1146 pthread_mutex_lock(&out->lock);
1147 if (out->standby) {
1148 ret = start_output_stream(out);
1149 if (ret != 0) {
1150 pthread_mutex_unlock(&adev->lock);
1151 goto exit;
1152 }
1153 out->standby = false;
1154 }
1155 pthread_mutex_unlock(&adev->lock);
1156
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001157 if (out->disabled) {
1158 ret = -EPIPE;
1159 goto exit;
1160 }
1161
Eric Laurent3948fda2013-04-04 09:24:22 -07001162 if (out->muted)
1163 memset((void *)buffer, 0, bytes);
1164
Simon Wilson56d84e22012-08-17 13:55:27 -07001165 /* Write to all active PCMs */
1166 for (i = 0; i < PCM_TOTAL; i++)
Glenn Kasten21169cb2013-08-20 15:36:18 -07001167 if (out->pcm[i]) {
1168 ret = pcm_write(out->pcm[i], (void *)buffer, bytes);
1169 if (ret != 0)
1170 break;
1171 }
1172 if (ret == 0)
1173 out->written += bytes / (out->config.channels * sizeof(short));
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001174
Simon Wilson15f60a82012-04-24 20:56:32 -07001175exit:
1176 pthread_mutex_unlock(&out->lock);
1177
1178 if (ret != 0) {
1179 usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
1180 out_get_sample_rate(&stream->common));
1181 }
1182
1183 return bytes;
1184}
1185
1186static int out_get_render_position(const struct audio_stream_out *stream,
1187 uint32_t *dsp_frames)
1188{
1189 return -EINVAL;
1190}
1191
1192static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1193{
1194 return 0;
1195}
1196
1197static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1198{
1199 return 0;
1200}
1201
1202static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1203 int64_t *timestamp)
1204{
1205 return -EINVAL;
1206}
1207
Glenn Kasten21169cb2013-08-20 15:36:18 -07001208static int out_get_presentation_position(const struct audio_stream_out *stream,
1209 uint64_t *frames, struct timespec *timestamp)
1210{
1211 struct stream_out *out = (struct stream_out *)stream;
1212 int ret = -1;
1213
1214 pthread_mutex_lock(&out->lock);
1215
1216 int i;
1217 // There is a question how to implement this correctly when there is more than one PCM stream.
1218 // We are just interested in the frames pending for playback in the kernel buffer here,
1219 // not the total played since start. The current behavior should be safe because the
1220 // cases where both cards are active are marginal.
1221 for (i = 0; i < PCM_TOTAL; i++)
1222 if (out->pcm[i]) {
1223 size_t avail;
1224 if (pcm_get_htimestamp(out->pcm[i], &avail, timestamp) == 0) {
1225 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
1226 // FIXME This calculation is incorrect if there is buffering after app processor
1227 int64_t signed_frames = out->written - kernel_buffer_size + avail;
1228 // It would be unusual for this value to be negative, but check just in case ...
1229 if (signed_frames >= 0) {
1230 *frames = signed_frames;
1231 ret = 0;
1232 }
1233 break;
1234 }
1235 }
1236
1237 pthread_mutex_unlock(&out->lock);
1238
1239 return ret;
1240}
1241
Simon Wilson15f60a82012-04-24 20:56:32 -07001242/** audio_stream_in implementation **/
1243static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1244{
1245 struct stream_in *in = (struct stream_in *)stream;
1246
1247 return in->requested_rate;
1248}
1249
1250static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1251{
1252 return 0;
1253}
1254
Eric Laurentd7abdd02012-07-27 14:54:41 -07001255static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
1256{
Eric Laurentb52afc82013-01-18 15:12:57 -08001257 struct stream_in *in = (struct stream_in *)stream;
1258
1259 return in->channel_mask;
Eric Laurentd7abdd02012-07-27 14:54:41 -07001260}
1261
1262
Simon Wilson15f60a82012-04-24 20:56:32 -07001263static size_t in_get_buffer_size(const struct audio_stream *stream)
1264{
1265 struct stream_in *in = (struct stream_in *)stream;
1266
1267 return get_input_buffer_size(in->requested_rate,
1268 AUDIO_FORMAT_PCM_16_BIT,
Eric Laurentd7abdd02012-07-27 14:54:41 -07001269 popcount(in_get_channels(stream)));
Simon Wilson15f60a82012-04-24 20:56:32 -07001270}
1271
1272static audio_format_t in_get_format(const struct audio_stream *stream)
1273{
1274 return AUDIO_FORMAT_PCM_16_BIT;
1275}
1276
1277static int in_set_format(struct audio_stream *stream, audio_format_t format)
1278{
1279 return -ENOSYS;
1280}
1281
Eric Laurent4f1aece2013-04-19 17:10:25 -07001282static int do_in_standby(struct stream_in *in)
Simon Wilson15f60a82012-04-24 20:56:32 -07001283{
Eric Laurent4f1aece2013-04-19 17:10:25 -07001284 struct audio_device *adev = in->dev;
Simon Wilson15f60a82012-04-24 20:56:32 -07001285
1286 if (!in->standby) {
1287 pcm_close(in->pcm);
1288 in->pcm = NULL;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001289
1290 if (in->device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)
1291 stop_bt_sco(adev);
1292
Eric Laurent87532032012-07-16 13:53:20 -07001293 in->dev->input_source = AUDIO_SOURCE_DEFAULT;
Eric Laurent42531fa2012-10-03 09:06:14 -07001294 in->dev->in_device = AUDIO_DEVICE_NONE;
Jean-Michel Trivi3f467de2013-06-06 15:26:01 -07001295 in->dev->in_channel_mask = 0;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001296 select_devices(adev);
Simon Wilson15f60a82012-04-24 20:56:32 -07001297 in->standby = true;
Eric Laurenta989ebf2012-10-15 15:14:44 -07001298
Eric Laurent4f1aece2013-04-19 17:10:25 -07001299 if (get_bubblelevel(adev))
1300 in->dev->bubble_level->stop_polling(adev->bubble_level);
Simon Wilson15f60a82012-04-24 20:56:32 -07001301 }
1302
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001303 eS305_SetActiveIoHandle(ES305_IO_HANDLE_NONE);
Eric Laurent4f1aece2013-04-19 17:10:25 -07001304 return 0;
1305}
1306
1307static int in_standby(struct audio_stream *stream)
1308{
1309 struct stream_in *in = (struct stream_in *)stream;
1310 int ret;
1311
1312 pthread_mutex_lock(&in->dev->lock);
1313 pthread_mutex_lock(&in->lock);
1314
1315 ret = do_in_standby(in);
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001316
Simon Wilson15f60a82012-04-24 20:56:32 -07001317 pthread_mutex_unlock(&in->lock);
1318 pthread_mutex_unlock(&in->dev->lock);
1319
Eric Laurent4f1aece2013-04-19 17:10:25 -07001320 return ret;
Simon Wilson15f60a82012-04-24 20:56:32 -07001321}
1322
1323static int in_dump(const struct audio_stream *stream, int fd)
1324{
1325 return 0;
1326}
1327
1328static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1329{
1330 struct stream_in *in = (struct stream_in *)stream;
1331 struct audio_device *adev = in->dev;
1332 struct str_parms *parms;
1333 char value[32];
1334 int ret;
1335 unsigned int val;
Eric Laurent87532032012-07-16 13:53:20 -07001336 bool apply_now = false;
Simon Wilson15f60a82012-04-24 20:56:32 -07001337
1338 parms = str_parms_create_str(kvpairs);
1339
Simon Wilson15f60a82012-04-24 20:56:32 -07001340 pthread_mutex_lock(&adev->lock);
Eric Laurent87532032012-07-16 13:53:20 -07001341 pthread_mutex_lock(&in->lock);
Eric Laurent42531fa2012-10-03 09:06:14 -07001342 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE,
1343 value, sizeof(value));
Simon Wilson15f60a82012-04-24 20:56:32 -07001344 if (ret >= 0) {
1345 val = atoi(value);
Eric Laurent87532032012-07-16 13:53:20 -07001346 /* no audio source uses val == 0 */
1347 if ((in->input_source != val) && (val != 0)) {
1348 in->input_source = val;
1349 apply_now = !in->standby;
Simon Wilson15f60a82012-04-24 20:56:32 -07001350 }
1351 }
Eric Laurent87532032012-07-16 13:53:20 -07001352
Eric Laurent42531fa2012-10-03 09:06:14 -07001353 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
1354 value, sizeof(value));
1355 if (ret >= 0) {
Eric Laurent4f1aece2013-04-19 17:10:25 -07001356 /* strip AUDIO_DEVICE_BIT_IN to allow bitwise comparisons */
1357 val = atoi(value) & ~AUDIO_DEVICE_BIT_IN;
Eric Laurent42531fa2012-10-03 09:06:14 -07001358 /* no audio device uses val == 0 */
1359 if ((in->device != val) && (val != 0)) {
Eric Laurent4f1aece2013-04-19 17:10:25 -07001360 /* force output standby to start or stop SCO pcm stream if needed */
1361 if ((val & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) ^
1362 (in->device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
1363 do_in_standby(in);
1364 }
Eric Laurent42531fa2012-10-03 09:06:14 -07001365 in->device = val;
1366 apply_now = !in->standby;
1367 }
1368 }
1369
Eric Laurent87532032012-07-16 13:53:20 -07001370 if (apply_now) {
Eric Laurent87532032012-07-16 13:53:20 -07001371 adev->input_source = in->input_source;
Eric Laurent42531fa2012-10-03 09:06:14 -07001372 adev->in_device = in->device;
Eric Laurent87532032012-07-16 13:53:20 -07001373 select_devices(adev);
1374 }
1375
1376 pthread_mutex_unlock(&in->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001377 pthread_mutex_unlock(&adev->lock);
1378
1379 str_parms_destroy(parms);
1380 return ret;
1381}
1382
1383static char * in_get_parameters(const struct audio_stream *stream,
1384 const char *keys)
1385{
1386 return strdup("");
1387}
1388
1389static int in_set_gain(struct audio_stream_in *stream, float gain)
1390{
1391 return 0;
1392}
1393
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001394static void in_apply_ramp(struct stream_in *in, int16_t *buffer, size_t frames)
1395{
1396 size_t i;
1397 uint16_t vol = in->ramp_vol;
1398 uint16_t step = in->ramp_step;
1399
1400 frames = (frames < in->ramp_frames) ? frames : in->ramp_frames;
1401
Eric Laurentb52afc82013-01-18 15:12:57 -08001402 if (in->channel_mask == AUDIO_CHANNEL_IN_MONO)
1403 for (i = 0; i < frames; i++)
1404 {
1405 buffer[i] = (int16_t)((buffer[i] * vol) >> 16);
1406 vol += step;
1407 }
1408 else
1409 for (i = 0; i < frames; i++)
1410 {
1411 buffer[2*i] = (int16_t)((buffer[2*i] * vol) >> 16);
1412 buffer[2*i + 1] = (int16_t)((buffer[2*i + 1] * vol) >> 16);
1413 vol += step;
1414 }
1415
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001416
1417 in->ramp_vol = vol;
1418 in->ramp_frames -= frames;
1419}
1420
Simon Wilson15f60a82012-04-24 20:56:32 -07001421static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
1422 size_t bytes)
1423{
1424 int ret = 0;
1425 struct stream_in *in = (struct stream_in *)stream;
1426 struct audio_device *adev = in->dev;
1427 size_t frames_rq = bytes / audio_stream_frame_size(&stream->common);
1428
1429 /*
1430 * acquiring hw device mutex systematically is useful if a low
1431 * priority thread is waiting on the input stream mutex - e.g.
1432 * executing in_set_parameters() while holding the hw device
1433 * mutex
1434 */
1435 pthread_mutex_lock(&adev->lock);
1436 pthread_mutex_lock(&in->lock);
1437 if (in->standby) {
1438 ret = start_input_stream(in);
1439 if (ret == 0)
1440 in->standby = 0;
1441 }
1442 pthread_mutex_unlock(&adev->lock);
1443
1444 if (ret < 0)
1445 goto exit;
1446
1447 /*if (in->num_preprocessors != 0)
1448 ret = process_frames(in, buffer, frames_rq);
Eric Laurentd7abdd02012-07-27 14:54:41 -07001449 else */
1450 ret = read_frames(in, buffer, frames_rq);
Simon Wilson15f60a82012-04-24 20:56:32 -07001451
1452 if (ret > 0)
1453 ret = 0;
1454
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001455 if (in->ramp_frames > 0)
1456 in_apply_ramp(in, buffer, frames_rq);
1457
Simon Wilson15f60a82012-04-24 20:56:32 -07001458 /*
1459 * Instead of writing zeroes here, we could trust the hardware
1460 * to always provide zeroes when muted.
1461 */
1462 if (ret == 0 && adev->mic_mute)
1463 memset(buffer, 0, bytes);
1464
1465exit:
1466 if (ret < 0)
1467 usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
1468 in_get_sample_rate(&stream->common));
1469
1470 pthread_mutex_unlock(&in->lock);
1471 return bytes;
1472}
1473
1474static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1475{
1476 return 0;
1477}
1478
1479static int in_add_audio_effect(const struct audio_stream *stream,
1480 effect_handle_t effect)
1481{
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001482 struct stream_in *in = (struct stream_in *)stream;
1483 effect_descriptor_t descr;
1484 if ((*effect)->get_descriptor(effect, &descr) == 0) {
1485
1486 pthread_mutex_lock(&in->dev->lock);
1487 pthread_mutex_lock(&in->lock);
1488
1489 eS305_AddEffect(&descr, in->io_handle);
1490
1491 pthread_mutex_unlock(&in->lock);
1492 pthread_mutex_unlock(&in->dev->lock);
1493 }
1494
Simon Wilson15f60a82012-04-24 20:56:32 -07001495 return 0;
1496}
1497
1498static int in_remove_audio_effect(const struct audio_stream *stream,
1499 effect_handle_t effect)
1500{
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001501 struct stream_in *in = (struct stream_in *)stream;
1502 effect_descriptor_t descr;
1503 if ((*effect)->get_descriptor(effect, &descr) == 0) {
1504
1505 pthread_mutex_lock(&in->dev->lock);
1506 pthread_mutex_lock(&in->lock);
1507
1508 eS305_RemoveEffect(&descr, in->io_handle);
1509
1510 pthread_mutex_unlock(&in->lock);
1511 pthread_mutex_unlock(&in->dev->lock);
1512 }
1513
Simon Wilson15f60a82012-04-24 20:56:32 -07001514 return 0;
1515}
1516
Simon Wilson15f60a82012-04-24 20:56:32 -07001517static int adev_open_output_stream(struct audio_hw_device *dev,
1518 audio_io_handle_t handle,
1519 audio_devices_t devices,
1520 audio_output_flags_t flags,
1521 struct audio_config *config,
1522 struct audio_stream_out **stream_out)
1523{
1524 struct audio_device *adev = (struct audio_device *)dev;
1525 struct stream_out *out;
1526 int ret;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001527 enum output_type type;
Simon Wilson15f60a82012-04-24 20:56:32 -07001528
1529 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1530 if (!out)
1531 return -ENOMEM;
1532
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001533 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1534 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1535 if (devices == AUDIO_DEVICE_NONE)
1536 devices = AUDIO_DEVICE_OUT_SPEAKER;
1537 out->device = devices;
1538
1539 if (flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1540 devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1541 pthread_mutex_lock(&adev->lock);
1542 ret = read_hdmi_channel_masks(adev, out);
1543 pthread_mutex_unlock(&adev->lock);
1544 if (ret != 0)
1545 goto err_open;
1546 if (config->sample_rate == 0)
1547 config->sample_rate = HDMI_MULTI_DEFAULT_SAMPLING_RATE;
1548 if (config->channel_mask == 0)
1549 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1550 out->channel_mask = config->channel_mask;
1551 out->config = pcm_config_hdmi_multi;
1552 out->config.rate = config->sample_rate;
1553 out->config.channels = popcount(config->channel_mask);
1554 out->pcm_device = PCM_DEVICE;
1555 type = OUTPUT_HDMI;
1556 } else if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1557 out->config = pcm_config_deep;
1558 out->pcm_device = PCM_DEVICE_DEEP;
1559 type = OUTPUT_DEEP_BUF;
1560 } else {
1561 out->config = pcm_config;
1562 out->pcm_device = PCM_DEVICE;
1563 type = OUTPUT_LOW_LATENCY;
1564 }
1565
Simon Wilson15f60a82012-04-24 20:56:32 -07001566 out->stream.common.get_sample_rate = out_get_sample_rate;
1567 out->stream.common.set_sample_rate = out_set_sample_rate;
1568 out->stream.common.get_buffer_size = out_get_buffer_size;
1569 out->stream.common.get_channels = out_get_channels;
1570 out->stream.common.get_format = out_get_format;
1571 out->stream.common.set_format = out_set_format;
1572 out->stream.common.standby = out_standby;
1573 out->stream.common.dump = out_dump;
1574 out->stream.common.set_parameters = out_set_parameters;
1575 out->stream.common.get_parameters = out_get_parameters;
1576 out->stream.common.add_audio_effect = out_add_audio_effect;
1577 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1578 out->stream.get_latency = out_get_latency;
1579 out->stream.set_volume = out_set_volume;
1580 out->stream.write = out_write;
1581 out->stream.get_render_position = out_get_render_position;
1582 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten21169cb2013-08-20 15:36:18 -07001583 out->stream.get_presentation_position = out_get_presentation_position;
Simon Wilson15f60a82012-04-24 20:56:32 -07001584
1585 out->dev = adev;
1586
1587 config->format = out_get_format(&out->stream.common);
1588 config->channel_mask = out_get_channels(&out->stream.common);
1589 config->sample_rate = out_get_sample_rate(&out->stream.common);
1590
1591 out->standby = true;
Eric Laurent3948fda2013-04-04 09:24:22 -07001592 /* out->muted = false; by calloc() */
Glenn Kasten21169cb2013-08-20 15:36:18 -07001593 /* out->written = 0; by calloc() */
Simon Wilson15f60a82012-04-24 20:56:32 -07001594
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001595 pthread_mutex_lock(&adev->lock);
1596 if (adev->outputs[type]) {
1597 pthread_mutex_unlock(&adev->lock);
1598 ret = -EBUSY;
1599 goto err_open;
1600 }
1601 adev->outputs[type] = out;
1602 pthread_mutex_unlock(&adev->lock);
1603
Simon Wilson15f60a82012-04-24 20:56:32 -07001604 *stream_out = &out->stream;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001605
Simon Wilson15f60a82012-04-24 20:56:32 -07001606 return 0;
1607
1608err_open:
1609 free(out);
1610 *stream_out = NULL;
1611 return ret;
1612}
1613
1614static void adev_close_output_stream(struct audio_hw_device *dev,
1615 struct audio_stream_out *stream)
1616{
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001617 struct audio_device *adev;
1618 enum output_type type;
1619
Simon Wilson15f60a82012-04-24 20:56:32 -07001620 out_standby(&stream->common);
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001621 adev = (struct audio_device *)dev;
1622 pthread_mutex_lock(&adev->lock);
1623 for (type = 0; type < OUTPUT_TOTAL; ++type) {
1624 if (adev->outputs[type] == (struct stream_out *) stream) {
1625 adev->outputs[type] = NULL;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001626 break;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001627 }
1628 }
1629 pthread_mutex_unlock(&adev->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001630 free(stream);
1631}
1632
1633static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1634{
Eric Laurenta989ebf2012-10-15 15:14:44 -07001635 return 0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001636}
1637
1638static char * adev_get_parameters(const struct audio_hw_device *dev,
1639 const char *keys)
1640{
Eric Laurent688880c2012-09-07 16:46:00 -07001641 struct audio_device *adev = (struct audio_device *)dev;
1642 struct str_parms *parms = str_parms_create_str(keys);
1643 char value[32];
1644 int ret = str_parms_get_str(parms, "ec_supported", value, sizeof(value));
1645 char *str;
1646
1647 str_parms_destroy(parms);
1648 if (ret >= 0) {
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001649 parms = str_parms_create_str("ec_supported=yes");
Eric Laurent688880c2012-09-07 16:46:00 -07001650 str = str_parms_to_str(parms);
1651 str_parms_destroy(parms);
1652 return str;
1653 }
Simon Wilson15f60a82012-04-24 20:56:32 -07001654 return strdup("");
1655}
1656
1657static int adev_init_check(const struct audio_hw_device *dev)
1658{
1659 return 0;
1660}
1661
1662static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1663{
1664 return -ENOSYS;
1665}
1666
1667static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1668{
1669 return -ENOSYS;
1670}
1671
1672static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1673{
1674 return 0;
1675}
1676
1677static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1678{
1679 struct audio_device *adev = (struct audio_device *)dev;
1680
1681 adev->mic_mute = state;
1682
1683 return 0;
1684}
1685
1686static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1687{
1688 struct audio_device *adev = (struct audio_device *)dev;
1689
1690 *state = adev->mic_mute;
1691
1692 return 0;
1693}
1694
1695static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1696 const struct audio_config *config)
1697{
1698
1699 return get_input_buffer_size(config->sample_rate, config->format,
1700 popcount(config->channel_mask));
1701}
1702
1703static int adev_open_input_stream(struct audio_hw_device *dev,
1704 audio_io_handle_t handle,
1705 audio_devices_t devices,
1706 struct audio_config *config,
1707 struct audio_stream_in **stream_in)
1708{
1709 struct audio_device *adev = (struct audio_device *)dev;
1710 struct stream_in *in;
1711 int ret;
1712
1713 *stream_in = NULL;
1714
Eric Laurentd7abdd02012-07-27 14:54:41 -07001715 /* Respond with a request for mono if a different format is given. */
Eric Laurentb52afc82013-01-18 15:12:57 -08001716 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO &&
1717 config->channel_mask != AUDIO_CHANNEL_IN_FRONT_BACK) {
Eric Laurentd7abdd02012-07-27 14:54:41 -07001718 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
Simon Wilson15f60a82012-04-24 20:56:32 -07001719 return -EINVAL;
1720 }
1721
1722 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
1723 if (!in)
1724 return -ENOMEM;
1725
1726 in->stream.common.get_sample_rate = in_get_sample_rate;
1727 in->stream.common.set_sample_rate = in_set_sample_rate;
1728 in->stream.common.get_buffer_size = in_get_buffer_size;
1729 in->stream.common.get_channels = in_get_channels;
1730 in->stream.common.get_format = in_get_format;
1731 in->stream.common.set_format = in_set_format;
1732 in->stream.common.standby = in_standby;
1733 in->stream.common.dump = in_dump;
1734 in->stream.common.set_parameters = in_set_parameters;
1735 in->stream.common.get_parameters = in_get_parameters;
1736 in->stream.common.add_audio_effect = in_add_audio_effect;
1737 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1738 in->stream.set_gain = in_set_gain;
1739 in->stream.read = in_read;
1740 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1741
1742 in->dev = adev;
1743 in->standby = true;
1744 in->requested_rate = config->sample_rate;
Eric Laurent87532032012-07-16 13:53:20 -07001745 in->input_source = AUDIO_SOURCE_DEFAULT;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001746 /* strip AUDIO_DEVICE_BIT_IN to allow bitwise comparisons */
1747 in->device = devices & ~AUDIO_DEVICE_BIT_IN;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001748 in->io_handle = handle;
Eric Laurentb52afc82013-01-18 15:12:57 -08001749 in->channel_mask = config->channel_mask;
Simon Wilson15f60a82012-04-24 20:56:32 -07001750
Glenn Kasten7ecf6232012-09-28 12:01:31 -07001751 in->buffer = malloc(pcm_config_in.period_size * pcm_config_in.channels
Eric Laurentd7abdd02012-07-27 14:54:41 -07001752 * audio_stream_frame_size(&in->stream.common));
1753
Simon Wilson15f60a82012-04-24 20:56:32 -07001754 if (!in->buffer) {
1755 ret = -ENOMEM;
1756 goto err_malloc;
1757 }
1758
Glenn Kasten7ecf6232012-09-28 12:01:31 -07001759 if (in->requested_rate != pcm_config_in.rate) {
Simon Wilson15f60a82012-04-24 20:56:32 -07001760 in->buf_provider.get_next_buffer = get_next_buffer;
1761 in->buf_provider.release_buffer = release_buffer;
1762
Glenn Kasten7ecf6232012-09-28 12:01:31 -07001763 ret = create_resampler(pcm_config_in.rate,
Simon Wilson15f60a82012-04-24 20:56:32 -07001764 in->requested_rate,
Eric Laurentb52afc82013-01-18 15:12:57 -08001765 popcount(in->channel_mask),
Simon Wilson15f60a82012-04-24 20:56:32 -07001766 RESAMPLER_QUALITY_DEFAULT,
1767 &in->buf_provider,
1768 &in->resampler);
1769 if (ret != 0) {
1770 ret = -EINVAL;
1771 goto err_resampler;
1772 }
1773 }
1774
1775 *stream_in = &in->stream;
1776 return 0;
1777
1778err_resampler:
1779 free(in->buffer);
1780err_malloc:
1781 free(in);
1782 return ret;
1783}
1784
1785static void adev_close_input_stream(struct audio_hw_device *dev,
1786 struct audio_stream_in *stream)
1787{
1788 struct stream_in *in = (struct stream_in *)stream;
1789
1790 in_standby(&stream->common);
1791 if (in->resampler) {
1792 release_resampler(in->resampler);
1793 in->resampler = NULL;
1794 }
1795 free(in->buffer);
1796 free(stream);
1797}
1798
1799static int adev_dump(const audio_hw_device_t *device, int fd)
1800{
1801 return 0;
1802}
1803
1804static int adev_close(hw_device_t *device)
1805{
1806 struct audio_device *adev = (struct audio_device *)device;
1807
1808 audio_route_free(adev->ar);
1809
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001810 eS305_Release();
1811
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001812 if (adev->hdmi_drv_fd >= 0)
1813 close(adev->hdmi_drv_fd);
Eric Laurent688880c2012-09-07 16:46:00 -07001814
Eric Laurent429f24d2012-11-02 14:37:38 -07001815 if (adev->bubble_level)
1816 bubble_level_release(adev->bubble_level);
Eric Laurenta989ebf2012-10-15 15:14:44 -07001817
Simon Wilson15f60a82012-04-24 20:56:32 -07001818 free(device);
1819 return 0;
1820}
1821
Simon Wilson15f60a82012-04-24 20:56:32 -07001822static int adev_open(const hw_module_t* module, const char* name,
1823 hw_device_t** device)
1824{
1825 struct audio_device *adev;
1826 int ret;
1827
1828 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1829 return -EINVAL;
1830
1831 adev = calloc(1, sizeof(struct audio_device));
1832 if (!adev)
1833 return -ENOMEM;
1834
1835 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent6a466d72012-08-28 12:13:38 -07001836 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001837 adev->hw_device.common.module = (struct hw_module_t *) module;
1838 adev->hw_device.common.close = adev_close;
1839
Simon Wilson15f60a82012-04-24 20:56:32 -07001840 adev->hw_device.init_check = adev_init_check;
1841 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1842 adev->hw_device.set_master_volume = adev_set_master_volume;
1843 adev->hw_device.set_mode = adev_set_mode;
1844 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1845 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1846 adev->hw_device.set_parameters = adev_set_parameters;
1847 adev->hw_device.get_parameters = adev_get_parameters;
1848 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1849 adev->hw_device.open_output_stream = adev_open_output_stream;
1850 adev->hw_device.close_output_stream = adev_close_output_stream;
1851 adev->hw_device.open_input_stream = adev_open_input_stream;
1852 adev->hw_device.close_input_stream = adev_close_input_stream;
1853 adev->hw_device.dump = adev_dump;
1854
Simon Wilson759c6f02013-01-15 16:38:56 -08001855 adev->ar = audio_route_init(MIXER_CARD, NULL);
Eric Laurent87532032012-07-16 13:53:20 -07001856 adev->input_source = AUDIO_SOURCE_DEFAULT;
1857 /* adev->cur_route_id initial value is 0 and such that first device
1858 * selection is always applied by select_devices() */
Simon Wilson15f60a82012-04-24 20:56:32 -07001859
Eric Laurent688880c2012-09-07 16:46:00 -07001860 adev->es305_preset = ES305_PRESET_INIT;
Eric Laurenta989ebf2012-10-15 15:14:44 -07001861 adev->es305_new_mode = ES305_MODE_LEVEL;
1862 adev->es305_mode = ES305_MODE_LEVEL;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001863 adev->hdmi_drv_fd = -1;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001864
Simon Wilson15f60a82012-04-24 20:56:32 -07001865 *device = &adev->hw_device.common;
1866
Simon Wilson15f60a82012-04-24 20:56:32 -07001867 return 0;
1868}
1869
1870static struct hw_module_methods_t hal_module_methods = {
1871 .open = adev_open,
1872};
1873
1874struct audio_module HAL_MODULE_INFO_SYM = {
1875 .common = {
1876 .tag = HARDWARE_MODULE_TAG,
1877 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1878 .hal_api_version = HARDWARE_HAL_API_VERSION,
1879 .id = AUDIO_HARDWARE_MODULE_ID,
1880 .name = "Manta audio HW HAL",
1881 .author = "The Android Open Source Project",
1882 .methods = &hal_module_methods,
1883 },
1884};