blob: 4f75f7d6607786020f6da890e68b5abf87984688 [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>
42
Eric Laurenta989ebf2012-10-15 15:14:44 -070043#include <BubbleLevel.h>
44
Simon Wilson15f60a82012-04-24 20:56:32 -070045#include "audio_route.h"
46
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -070047#include <eS305VoiceProcessing.h>
48
Simon Wilson15f60a82012-04-24 20:56:32 -070049#define PCM_CARD 0
Simon Wilson56d84e22012-08-17 13:55:27 -070050#define PCM_CARD_SPDIF 1
51#define PCM_TOTAL 2
52
Simon Wilson15f60a82012-04-24 20:56:32 -070053#define PCM_DEVICE 0
Glenn Kastene0aa8f32012-08-17 09:26:58 -070054#define PCM_DEVICE_DEEP 1
Simon Wilsona282d2f2012-09-12 16:14:24 -070055#define PCM_DEVICE_VOICE 2
56#define PCM_DEVICE_SCO 3
Simon Wilson15f60a82012-04-24 20:56:32 -070057
Eric Laurent1a0c0a72012-08-24 11:29:04 -070058/* duration in ms of volume ramp applied when starting capture to remove plop */
59#define CAPTURE_START_RAMP_MS 100
60
Eric Laurentb2c0b4f2012-09-21 11:42:48 -070061/* default sampling for HDMI multichannel output */
62#define HDMI_MULTI_DEFAULT_SAMPLING_RATE 44100
63/* maximum number of channel mask configurations supported. Currently the primary
64 * output only supports 1 (stereo) and the multi channel HDMI output 2 (5.1 and 7.1) */
65#define MAX_SUPPORTED_CHANNEL_MASKS 2
66
67#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
68
Simon Wilson15f60a82012-04-24 20:56:32 -070069struct pcm_config pcm_config = {
70 .channels = 2,
71 .rate = 44100,
Glenn Kasten22db1772012-09-04 09:26:50 -070072 .period_size = 256,
Glenn Kastenb9366272012-07-18 14:06:12 -070073 .period_count = 2,
Simon Wilson15f60a82012-04-24 20:56:32 -070074 .format = PCM_FORMAT_S16_LE,
75};
76
Glenn Kasten7ecf6232012-09-28 12:01:31 -070077struct pcm_config pcm_config_in = {
78 .channels = 2,
79 .rate = 44100,
80 .period_size = 1024,
81 .period_count = 2,
82 .format = PCM_FORMAT_S16_LE,
83};
84
Simon Wilsona282d2f2012-09-12 16:14:24 -070085struct pcm_config pcm_config_sco = {
86 .channels = 1,
87 .rate = 8000,
88 .period_size = 128,
89 .period_count = 2,
90 .format = PCM_FORMAT_S16_LE,
91};
92
Glenn Kastene0aa8f32012-08-17 09:26:58 -070093struct pcm_config pcm_config_deep = {
94 .channels = 2,
95 .rate = 44100,
96 /* FIXME This is an arbitrary number, may change.
97 * Dynamic configuration based on screen on/off is not implemented;
98 * let's see what power consumption is first to see if necessary.
99 */
100 .period_size = 8192,
101 .period_count = 2,
102 .format = PCM_FORMAT_S16_LE,
103};
104
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700105struct pcm_config pcm_config_hdmi_multi = {
106 .channels = 6, /* changed when the stream is opened */
107 .rate = HDMI_MULTI_DEFAULT_SAMPLING_RATE,
108 .period_size = 1024,
109 .period_count = 4,
110 .format = PCM_FORMAT_S16_LE,
111};
112
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700113enum output_type {
114 OUTPUT_DEEP_BUF, // deep PCM buffers output stream
115 OUTPUT_LOW_LATENCY, // low latency output stream
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700116 OUTPUT_HDMI, // HDMI multi channel
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700117 OUTPUT_TOTAL
118};
119
Simon Wilson15f60a82012-04-24 20:56:32 -0700120struct audio_device {
121 struct audio_hw_device hw_device;
122
123 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700124 audio_devices_t out_device; /* "or" of stream_out.device for all active output streams */
Eric Laurent42531fa2012-10-03 09:06:14 -0700125 audio_devices_t in_device;
Simon Wilson15f60a82012-04-24 20:56:32 -0700126 bool mic_mute;
127 struct audio_route *ar;
Eric Laurent87532032012-07-16 13:53:20 -0700128 audio_source_t input_source;
129 int cur_route_id; /* current route ID: combination of input source
130 * and output device IDs */
Simon Wilsona282d2f2012-09-12 16:14:24 -0700131 struct pcm *pcm_voice_out;
132 struct pcm *pcm_sco_out;
133 struct pcm *pcm_voice_in;
134 struct pcm *pcm_sco_in;
Eric Laurent688880c2012-09-07 16:46:00 -0700135 int es305_preset;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700136 int es305_new_mode;
Eric Laurent688880c2012-09-07 16:46:00 -0700137 int es305_mode;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700138 int hdmi_drv_fd;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700139 struct bubble_level *bubble_level;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700140
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700141 struct stream_out *outputs[OUTPUT_TOTAL];
Simon Wilson15f60a82012-04-24 20:56:32 -0700142};
143
144struct stream_out {
145 struct audio_stream_out stream;
146
147 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Simon Wilson56d84e22012-08-17 13:55:27 -0700148 struct pcm *pcm[PCM_TOTAL];
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700149 struct pcm_config config;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700150 unsigned int pcm_device;
Simon Wilson56d84e22012-08-17 13:55:27 -0700151 bool standby; /* true if all PCMs are inactive */
Eric Laurent42531fa2012-10-03 09:06:14 -0700152 audio_devices_t device;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700153 /* FIXME: when HDMI multichannel output is active, other outputs must be disabled as
154 * HDMI and WM1811 share the same I2S. This means that notifications and other sounds are
155 * silent when watching a 5.1 movie. */
156 bool disabled;
157 audio_channel_mask_t channel_mask;
158 /* Array of supported channel mask configurations. +1 so that the last entry is always 0 */
159 audio_channel_mask_t supported_channel_masks[MAX_SUPPORTED_CHANNEL_MASKS + 1];
Simon Wilson15f60a82012-04-24 20:56:32 -0700160
161 struct audio_device *dev;
162};
163
164struct stream_in {
165 struct audio_stream_in stream;
166
167 pthread_mutex_t lock; /* see note below on mutex acquisition order */
168 struct pcm *pcm;
169 bool standby;
170
171 unsigned int requested_rate;
172 struct resampler_itfe *resampler;
173 struct resampler_buffer_provider buf_provider;
174 int16_t *buffer;
175 size_t frames_in;
176 int read_status;
Eric Laurent87532032012-07-16 13:53:20 -0700177 audio_source_t input_source;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700178 audio_io_handle_t io_handle;
Eric Laurent42531fa2012-10-03 09:06:14 -0700179 audio_devices_t device;
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700180 uint16_t ramp_vol;
181 uint16_t ramp_step;
182 size_t ramp_frames;
Simon Wilson15f60a82012-04-24 20:56:32 -0700183
184 struct audio_device *dev;
185};
186
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700187#define STRING_TO_ENUM(string) { #string, string }
188
189struct string_to_enum {
190 const char *name;
191 uint32_t value;
192};
193
194const struct string_to_enum out_channels_name_to_enum_table[] = {
195 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
196 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
197 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
198};
199
Eric Laurent87532032012-07-16 13:53:20 -0700200enum {
201 OUT_DEVICE_SPEAKER,
202 OUT_DEVICE_HEADSET,
203 OUT_DEVICE_HEADPHONES,
204 OUT_DEVICE_BT_SCO,
205 OUT_DEVICE_SPEAKER_AND_HEADSET,
206 OUT_DEVICE_TAB_SIZE, /* number of rows in route_configs[][] */
207 OUT_DEVICE_NONE,
Eric Laurent87532032012-07-16 13:53:20 -0700208 OUT_DEVICE_CNT
209};
210
211enum {
212 IN_SOURCE_MIC,
213 IN_SOURCE_CAMCORDER,
214 IN_SOURCE_VOICE_RECOGNITION,
215 IN_SOURCE_VOICE_COMMUNICATION,
216 IN_SOURCE_TAB_SIZE, /* number of lines in route_configs[][] */
217 IN_SOURCE_NONE,
Eric Laurent87532032012-07-16 13:53:20 -0700218 IN_SOURCE_CNT
219};
220
Eric Laurent688880c2012-09-07 16:46:00 -0700221enum {
Eric Laurent688880c2012-09-07 16:46:00 -0700222 ES305_MODE_DEFAULT,
Eric Laurenta989ebf2012-10-15 15:14:44 -0700223 ES305_MODE_LEVEL,
Eric Laurent688880c2012-09-07 16:46:00 -0700224 ES305_NUM_MODES,
225};
226
Eric Laurent42531fa2012-10-03 09:06:14 -0700227int get_output_device_id(audio_devices_t device)
Eric Laurent87532032012-07-16 13:53:20 -0700228{
Eric Laurent6a466d72012-08-28 12:13:38 -0700229 if (device == AUDIO_DEVICE_NONE)
Eric Laurent87532032012-07-16 13:53:20 -0700230 return OUT_DEVICE_NONE;
231
232 if (popcount(device) == 2) {
233 if ((device == (AUDIO_DEVICE_OUT_SPEAKER |
234 AUDIO_DEVICE_OUT_WIRED_HEADSET)) ||
235 (device == (AUDIO_DEVICE_OUT_SPEAKER |
236 AUDIO_DEVICE_OUT_WIRED_HEADPHONE)))
237 return OUT_DEVICE_SPEAKER_AND_HEADSET;
238 else
Simon Wilsona6b94122012-09-12 12:52:24 -0700239 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700240 }
241
242 if (popcount(device) != 1)
Simon Wilsona6b94122012-09-12 12:52:24 -0700243 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700244
245 switch (device) {
246 case AUDIO_DEVICE_OUT_SPEAKER:
247 return OUT_DEVICE_SPEAKER;
248 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
249 return OUT_DEVICE_HEADSET;
250 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
251 return OUT_DEVICE_HEADPHONES;
252 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
253 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
254 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
255 return OUT_DEVICE_BT_SCO;
256 default:
Simon Wilsona6b94122012-09-12 12:52:24 -0700257 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700258 }
259}
260
261int get_input_source_id(audio_source_t source)
262{
263 switch (source) {
264 case AUDIO_SOURCE_DEFAULT:
265 return IN_SOURCE_NONE;
266 case AUDIO_SOURCE_MIC:
267 return IN_SOURCE_MIC;
268 case AUDIO_SOURCE_CAMCORDER:
269 return IN_SOURCE_CAMCORDER;
270 case AUDIO_SOURCE_VOICE_RECOGNITION:
271 return IN_SOURCE_VOICE_RECOGNITION;
272 case AUDIO_SOURCE_VOICE_COMMUNICATION:
273 return IN_SOURCE_VOICE_COMMUNICATION;
274 default:
Simon Wilsona6b94122012-09-12 12:52:24 -0700275 return IN_SOURCE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700276 }
277}
278
279struct route_config {
280 const char * const output_route;
281 const char * const input_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700282 int es305_preset[ES305_NUM_MODES]; // es305 preset for this route.
283 // -1 means es305 bypass
Eric Laurent87532032012-07-16 13:53:20 -0700284};
285
286const struct route_config media_speaker = {
287 "media-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700288 "media-main-mic",
289 { ES305_PRESET_OFF,
290 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700291};
292
293const struct route_config media_headphones = {
294 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700295 "media-main-mic",
296 { ES305_PRESET_OFF,
297 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700298};
299
300const struct route_config media_headset = {
301 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700302 "media-headset-mic",
303 { ES305_PRESET_OFF,
304 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700305};
306
307const struct route_config camcorder_speaker = {
308 "media-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700309 "media-second-mic",
Jean-Michel Trivi48277c52012-10-08 10:22:59 -0700310 { ES305_PRESET_CAMCORDER,
311 ES305_PRESET_CAMCORDER }
Eric Laurent87532032012-07-16 13:53:20 -0700312};
313
314const struct route_config camcorder_headphones = {
315 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700316 "media-second-mic",
Jean-Michel Trivi48277c52012-10-08 10:22:59 -0700317 { ES305_PRESET_CAMCORDER,
318 ES305_PRESET_CAMCORDER }
Eric Laurent87532032012-07-16 13:53:20 -0700319};
320
321const struct route_config voice_rec_speaker = {
322 "voice-rec-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700323 "voice-rec-main-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700324 { ES305_PRESET_ASRA_HANDHELD,
325 ES305_PRESET_ASRA_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700326};
327
328const struct route_config voice_rec_headphones = {
329 "voice-rec-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700330 "voice-rec-main-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700331 { ES305_PRESET_ASRA_HANDHELD,
332 ES305_PRESET_ASRA_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700333};
334
335const struct route_config voice_rec_headset = {
336 "voice-rec-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700337 "voice-rec-headset-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700338 { ES305_PRESET_ASRA_HEADSET,
339 ES305_PRESET_ASRA_HEADSET }
Eric Laurent87532032012-07-16 13:53:20 -0700340};
341
342const struct route_config communication_speaker = {
343 "communication-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700344 "communication-main-mic",
345 { ES305_PRESET_VOIP_HANDHELD,
346 ES305_PRESET_VOIP_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700347};
348
349const struct route_config communication_headphones = {
350 "communication-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700351 "communication-main-mic",
352 { ES305_PRESET_VOIP_HEADPHONES,
353 ES305_PRESET_VOIP_HP_DESKTOP}
Eric Laurent87532032012-07-16 13:53:20 -0700354};
355
356const struct route_config communication_headset = {
357 "communication-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700358 "communication-headset-mic",
359 { ES305_PRESET_VOIP_HEADSET,
360 ES305_PRESET_VOIP_HEADSET }
Eric Laurent87532032012-07-16 13:53:20 -0700361};
362
363const struct route_config speaker_and_headphones = {
364 "speaker-and-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700365 "main-mic",
366 { ES305_PRESET_CURRENT,
367 ES305_PRESET_CURRENT }
Eric Laurent87532032012-07-16 13:53:20 -0700368};
369
370const struct route_config bluetooth_sco = {
371 "bt-sco-headset",
Eric Laurent688880c2012-09-07 16:46:00 -0700372 "bt-sco-mic",
373 { ES305_PRESET_OFF,
374 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700375};
376
377const struct route_config * const route_configs[IN_SOURCE_TAB_SIZE]
378 [OUT_DEVICE_TAB_SIZE] = {
379 { /* IN_SOURCE_MIC */
380 &media_speaker, /* OUT_DEVICE_SPEAKER */
381 &media_headset, /* OUT_DEVICE_HEADSET */
382 &media_headphones, /* OUT_DEVICE_HEADPHONES */
383 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
384 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
385 },
386 { /* IN_SOURCE_CAMCORDER */
387 &camcorder_speaker, /* OUT_DEVICE_SPEAKER */
388 &camcorder_headphones, /* OUT_DEVICE_HEADSET */
389 &camcorder_headphones, /* OUT_DEVICE_HEADPHONES */
390 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
391 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
392 },
393 { /* IN_SOURCE_VOICE_RECOGNITION */
394 &voice_rec_speaker, /* OUT_DEVICE_SPEAKER */
395 &voice_rec_headset, /* OUT_DEVICE_HEADSET */
396 &voice_rec_headphones, /* OUT_DEVICE_HEADPHONES */
397 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
398 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
399 },
400 { /* IN_SOURCE_VOICE_COMMUNICATION */
401 &communication_speaker, /* OUT_DEVICE_SPEAKER */
402 &communication_headset, /* OUT_DEVICE_HEADSET */
403 &communication_headphones, /* OUT_DEVICE_HEADPHONES */
404 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
405 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
406 }
407};
408
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700409static int do_out_standby(struct stream_out *out);
410
Simon Wilson15f60a82012-04-24 20:56:32 -0700411/**
412 * NOTE: when multiple mutexes have to be acquired, always respect the
413 * following order: hw device > in stream > out stream
414 */
415
416/* Helper functions */
417
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700418static int open_hdmi_driver(struct audio_device *adev)
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700419{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700420 if (adev->hdmi_drv_fd < 0) {
421 adev->hdmi_drv_fd = open("/dev/video16", O_RDWR);
422 if (adev->hdmi_drv_fd < 0)
423 ALOGE("%s cannot open video16 (%d)", __func__, adev->hdmi_drv_fd);
424 }
425 return adev->hdmi_drv_fd;
426}
427
428/* must be called with hw device mutex locked */
429static int enable_hdmi_audio(struct audio_device *adev, int enable)
430{
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700431 int ret;
432 struct v4l2_control ctrl;
433
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700434 ret = open_hdmi_driver(adev);
435 if (ret < 0)
436 return ret;
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700437
438 ctrl.id = V4L2_CID_TV_ENABLE_HDMI_AUDIO;
439 ctrl.value = !!enable;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700440 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_S_CTRL, &ctrl);
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700441
442 if (ret < 0)
443 ALOGE("V4L2_CID_TV_ENABLE_HDMI_AUDIO ioctl error (%d)", errno);
444
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700445 return ret;
446}
447
448/* must be called with hw device mutex locked */
449static int read_hdmi_channel_masks(struct audio_device *adev, struct stream_out *out) {
450 int ret;
451 struct v4l2_control ctrl;
452
453 ret = open_hdmi_driver(adev);
454 if (ret < 0)
455 return ret;
456
457 ctrl.id = V4L2_CID_TV_MAX_AUDIO_CHANNELS;
458 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_G_CTRL, &ctrl);
459 if (ret < 0) {
460 ALOGE("V4L2_CID_TV_MAX_AUDIO_CHANNELS ioctl error (%d)", errno);
461 return ret;
462 }
463
464 ALOGV("%s ioctl %d got %d max channels", __func__, ret, ctrl.value);
465
466 if (ctrl.value != 6 && ctrl.value != 8)
467 return -ENOSYS;
468
469 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
470 if (ctrl.value == 8)
471 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
472
473 return ret;
474}
475
476/* must be called with hw device mutex locked */
477static int set_hdmi_channels(struct audio_device *adev, int channels) {
478 int ret;
479 struct v4l2_control ctrl;
480
481 ret = open_hdmi_driver(adev);
482 if (ret < 0)
483 return ret;
484
485 ctrl.id = V4L2_CID_TV_SET_NUM_CHANNELS;
486 ctrl.value = channels;
487 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_S_CTRL, &ctrl);
488 if (ret < 0)
489 ALOGE("V4L2_CID_TV_SET_NUM_CHANNELS ioctl error (%d)", errno);
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700490
491 return ret;
492}
493
Simon Wilson15f60a82012-04-24 20:56:32 -0700494static void select_devices(struct audio_device *adev)
495{
Eric Laurent6a466d72012-08-28 12:13:38 -0700496 int output_device_id = get_output_device_id(adev->out_device);
Eric Laurent87532032012-07-16 13:53:20 -0700497 int input_source_id = get_input_source_id(adev->input_source);
Simon Wilsonc4006be2012-08-17 11:23:38 -0700498 const char *output_route = NULL;
499 const char *input_route = NULL;
Eric Laurent87532032012-07-16 13:53:20 -0700500 int new_route_id;
Eric Laurent688880c2012-09-07 16:46:00 -0700501 int new_es305_preset = -1;
Simon Wilson15f60a82012-04-24 20:56:32 -0700502
Simon Wilsonc4006be2012-08-17 11:23:38 -0700503 reset_mixer_state(adev->ar);
504
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700505 enable_hdmi_audio(adev, adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL);
Simon Wilsonab5dda62012-10-01 17:44:38 -0700506
Eric Laurent87532032012-07-16 13:53:20 -0700507 new_route_id = (1 << (input_source_id + OUT_DEVICE_CNT)) + (1 << output_device_id);
Eric Laurenta989ebf2012-10-15 15:14:44 -0700508 if ((new_route_id == adev->cur_route_id) && (adev->es305_mode == adev->es305_new_mode))
Eric Laurent87532032012-07-16 13:53:20 -0700509 return;
510 adev->cur_route_id = new_route_id;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700511 adev->es305_mode = adev->es305_new_mode;
Simon Wilson15f60a82012-04-24 20:56:32 -0700512
Eric Laurent87532032012-07-16 13:53:20 -0700513 if (input_source_id != IN_SOURCE_NONE) {
514 if (output_device_id != OUT_DEVICE_NONE) {
515 input_route =
516 route_configs[input_source_id][output_device_id]->input_route;
517 output_route =
518 route_configs[input_source_id][output_device_id]->output_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700519 new_es305_preset =
520 route_configs[input_source_id][output_device_id]->es305_preset[adev->es305_mode];
Eric Laurent87532032012-07-16 13:53:20 -0700521 } else {
Eric Laurent42531fa2012-10-03 09:06:14 -0700522 switch (adev->in_device) {
523 case AUDIO_DEVICE_IN_WIRED_HEADSET:
524 output_device_id = OUT_DEVICE_HEADSET;
525 break;
526 case AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET:
527 output_device_id = OUT_DEVICE_BT_SCO;
528 break;
529 default:
530 output_device_id = OUT_DEVICE_SPEAKER;
531 break;
532 }
Eric Laurent87532032012-07-16 13:53:20 -0700533 input_route =
Eric Laurent42531fa2012-10-03 09:06:14 -0700534 route_configs[input_source_id][output_device_id]->input_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700535 new_es305_preset =
Eric Laurent42531fa2012-10-03 09:06:14 -0700536 route_configs[input_source_id][output_device_id]->es305_preset[adev->es305_mode];
Eric Laurent87532032012-07-16 13:53:20 -0700537 }
538 } else {
539 if (output_device_id != OUT_DEVICE_NONE) {
540 output_route =
541 route_configs[IN_SOURCE_MIC][output_device_id]->output_route;
542 }
543 }
544
545 ALOGV("select_devices() devices %#x input src %d output route %s input route %s",
Eric Laurent6a466d72012-08-28 12:13:38 -0700546 adev->out_device, adev->input_source,
Simon Wilsonc4006be2012-08-17 11:23:38 -0700547 output_route ? output_route : "none",
548 input_route ? input_route : "none");
Eric Laurent87532032012-07-16 13:53:20 -0700549
Simon Wilsonc4006be2012-08-17 11:23:38 -0700550 if (output_route)
551 audio_route_apply_path(adev->ar, output_route);
552 if (input_route)
553 audio_route_apply_path(adev->ar, input_route);
Simon Wilson15f60a82012-04-24 20:56:32 -0700554
Eric Laurent688880c2012-09-07 16:46:00 -0700555 if ((new_es305_preset != ES305_PRESET_CURRENT) &&
556 (new_es305_preset != adev->es305_preset)) {
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700557 ALOGV(" select_devices() changing es305 preset from %d to %d",
558 adev->es305_preset, new_es305_preset);
559 if (eS305_UsePreset(new_es305_preset) == 0) {
Eric Laurent688880c2012-09-07 16:46:00 -0700560 adev->es305_preset = new_es305_preset;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700561 }
Eric Laurent688880c2012-09-07 16:46:00 -0700562 }
563
564 update_mixer_state(adev->ar);
Simon Wilson15f60a82012-04-24 20:56:32 -0700565}
566
Eric Laurenta989ebf2012-10-15 15:14:44 -0700567void bubblelevel_callback(bool is_level, void *user_data)
568{
569 struct audio_device *adev = (struct audio_device *)user_data;
570 int es305_mode;
571
572 if (is_level)
573 es305_mode = ES305_MODE_LEVEL;
574 else
575 es305_mode = ES305_MODE_DEFAULT;
576
577 pthread_mutex_lock(&adev->lock);
578 if (es305_mode != adev->es305_mode) {
579 adev->es305_new_mode = es305_mode;
580 select_devices(adev);
581 ALOGV("bubblelevel_callback is_level %d es305_mode %d", is_level, es305_mode);
582 }
583 pthread_mutex_unlock(&adev->lock);
584}
585
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700586static void force_non_hdmi_out_standby(struct audio_device *adev)
587{
588 enum output_type type;
589 struct stream_out *out;
590
591 for (type = 0; type < OUTPUT_TOTAL; ++type) {
592 out = adev->outputs[type];
593 if (type == OUTPUT_HDMI || !out)
594 continue;
595 pthread_mutex_lock(&out->lock);
596 do_out_standby(out);
597 pthread_mutex_unlock(&out->lock);
598 }
599}
600
Simon Wilson15f60a82012-04-24 20:56:32 -0700601/* must be called with hw device and output stream mutexes locked */
602static int start_output_stream(struct stream_out *out)
603{
604 struct audio_device *adev = out->dev;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700605 int type;
606
607 if (out == adev->outputs[OUTPUT_HDMI]) {
608 force_non_hdmi_out_standby(adev);
609 } else if (adev->outputs[OUTPUT_HDMI] && !adev->outputs[OUTPUT_HDMI]->standby) {
610 out->disabled = true;
611 return 0;
612 }
613
614 out->disabled = false;
Simon Wilson15f60a82012-04-24 20:56:32 -0700615
Simon Wilson56d84e22012-08-17 13:55:27 -0700616 if (out->device & (AUDIO_DEVICE_OUT_SPEAKER |
617 AUDIO_DEVICE_OUT_WIRED_HEADSET |
618 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
Simon Wilsona282d2f2012-09-12 16:14:24 -0700619 AUDIO_DEVICE_OUT_AUX_DIGITAL |
620 AUDIO_DEVICE_OUT_ALL_SCO)) {
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700621
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700622 out->pcm[PCM_CARD] = pcm_open(PCM_CARD, out->pcm_device,
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700623 PCM_OUT, &out->config);
Simon Wilson15f60a82012-04-24 20:56:32 -0700624
Simon Wilson56d84e22012-08-17 13:55:27 -0700625 if (out->pcm[PCM_CARD] && !pcm_is_ready(out->pcm[PCM_CARD])) {
626 ALOGE("pcm_open(PCM_CARD) failed: %s",
627 pcm_get_error(out->pcm[PCM_CARD]));
628 pcm_close(out->pcm[PCM_CARD]);
629 return -ENOMEM;
630 }
631 }
632
633 if (out->device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700634 out->pcm[PCM_CARD_SPDIF] = pcm_open(PCM_CARD_SPDIF, out->pcm_device,
635 PCM_OUT, &out->config);
Simon Wilson56d84e22012-08-17 13:55:27 -0700636
637 if (out->pcm[PCM_CARD_SPDIF] &&
638 !pcm_is_ready(out->pcm[PCM_CARD_SPDIF])) {
639 ALOGE("pcm_open(PCM_CARD_SPDIF) failed: %s",
640 pcm_get_error(out->pcm[PCM_CARD_SPDIF]));
641 pcm_close(out->pcm[PCM_CARD_SPDIF]);
642 return -ENOMEM;
643 }
Simon Wilson15f60a82012-04-24 20:56:32 -0700644 }
645
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700646 adev->out_device |= out->device;
Eric Laurent87532032012-07-16 13:53:20 -0700647 select_devices(adev);
648
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700649 if (out->device & AUDIO_DEVICE_OUT_AUX_DIGITAL)
650 set_hdmi_channels(adev, out->config.channels);
651
Eric Laurenta989ebf2012-10-15 15:14:44 -0700652 /* anticipate level measurement in case we start capture later */
653 adev->bubble_level->poll_once(adev->bubble_level);
654
Simon Wilson15f60a82012-04-24 20:56:32 -0700655 return 0;
656}
657
658/* must be called with hw device and input stream mutexes locked */
659static int start_input_stream(struct stream_in *in)
660{
661 struct audio_device *adev = in->dev;
662
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700663 in->pcm = pcm_open(PCM_CARD, PCM_DEVICE, PCM_IN, &pcm_config_in);
Simon Wilson15f60a82012-04-24 20:56:32 -0700664
665 if (in->pcm && !pcm_is_ready(in->pcm)) {
666 ALOGE("pcm_open() failed: %s", pcm_get_error(in->pcm));
667 pcm_close(in->pcm);
668 return -ENOMEM;
669 }
670
671 /* if no supported sample rate is available, use the resampler */
672 if (in->resampler)
673 in->resampler->reset(in->resampler);
674
Eric Laurentf4231822012-08-22 16:06:38 -0700675 in->frames_in = 0;
Eric Laurent87532032012-07-16 13:53:20 -0700676 adev->input_source = in->input_source;
Eric Laurent42531fa2012-10-03 09:06:14 -0700677 adev->in_device = in->device;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700678
679 eS305_SetActiveIoHandle(in->io_handle);
Eric Laurent87532032012-07-16 13:53:20 -0700680 select_devices(adev);
681
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700682 /* initialize volume ramp */
683 in->ramp_frames = (CAPTURE_START_RAMP_MS * in->requested_rate) / 1000;
684 in->ramp_step = (uint16_t)(USHRT_MAX / in->ramp_frames);
685 in->ramp_vol = 0;;
686
Eric Laurenta989ebf2012-10-15 15:14:44 -0700687 adev->bubble_level->set_poll_interval(adev->bubble_level, BL_POLL_INTERVAL_MIN_SEC);
688 adev->bubble_level->start_polling(adev->bubble_level);
689
Simon Wilson15f60a82012-04-24 20:56:32 -0700690 return 0;
691}
692
Simon Wilsona282d2f2012-09-12 16:14:24 -0700693/* must be called with the hw device mutex locked, OK to hold other mutexes */
694static void start_bt_sco(struct audio_device *adev) {
695 adev->pcm_voice_out = pcm_open(PCM_CARD, PCM_DEVICE_VOICE, PCM_OUT,
696 &pcm_config_sco);
697 if (adev->pcm_voice_out && !pcm_is_ready(adev->pcm_voice_out)) {
698 ALOGE("pcm_open(VOICE_OUT) failed: %s", pcm_get_error(adev->pcm_voice_out));
699 goto err_voice_out;
700 }
701 adev->pcm_sco_out = pcm_open(PCM_CARD, PCM_DEVICE_SCO, PCM_OUT,
702 &pcm_config_sco);
703 if (adev->pcm_sco_out && !pcm_is_ready(adev->pcm_sco_out)) {
704 ALOGE("pcm_open(SCO_OUT) failed: %s", pcm_get_error(adev->pcm_sco_out));
705 goto err_sco_out;
706 }
707 adev->pcm_voice_in = pcm_open(PCM_CARD, PCM_DEVICE_VOICE, PCM_IN,
708 &pcm_config_sco);
709 if (adev->pcm_voice_in && !pcm_is_ready(adev->pcm_voice_in)) {
710 ALOGE("pcm_open(VOICE_IN) failed: %s", pcm_get_error(adev->pcm_voice_in));
711 goto err_voice_in;
712 }
713 adev->pcm_sco_in = pcm_open(PCM_CARD, PCM_DEVICE_SCO, PCM_IN,
714 &pcm_config_sco);
715 if (adev->pcm_sco_in && !pcm_is_ready(adev->pcm_sco_in)) {
716 ALOGE("pcm_open(SCO_IN) failed: %s", pcm_get_error(adev->pcm_sco_in));
717 goto err_sco_in;
718 }
719
720 pcm_start(adev->pcm_voice_out);
721 pcm_start(adev->pcm_sco_out);
722 pcm_start(adev->pcm_voice_in);
723 pcm_start(adev->pcm_sco_in);
724
725 return;
726
727err_sco_in:
728 pcm_close(adev->pcm_sco_in);
729err_voice_in:
730 pcm_close(adev->pcm_voice_in);
731err_sco_out:
732 pcm_close(adev->pcm_sco_out);
733err_voice_out:
734 pcm_close(adev->pcm_voice_out);
735}
736
737/* must be called with the hw device mutex locked, OK to hold other mutexes */
738static void stop_bt_sco(struct audio_device *adev) {
739 pcm_stop(adev->pcm_voice_out);
740 pcm_stop(adev->pcm_sco_out);
741 pcm_stop(adev->pcm_voice_in);
742 pcm_stop(adev->pcm_sco_in);
743
744 pcm_close(adev->pcm_voice_out);
745 pcm_close(adev->pcm_sco_out);
746 pcm_close(adev->pcm_voice_in);
747 pcm_close(adev->pcm_sco_in);
748}
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700749
Simon Wilson15f60a82012-04-24 20:56:32 -0700750static size_t get_input_buffer_size(unsigned int sample_rate,
751 audio_format_t format,
752 unsigned int channel_count)
753{
754 size_t size;
755
756 /*
757 * take resampling into account and return the closest majoring
758 * multiple of 16 frames, as audioflinger expects audio buffers to
759 * be a multiple of 16 frames
760 */
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700761 size = (pcm_config_in.period_size * sample_rate) / pcm_config_in.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -0700762 size = ((size + 15) / 16) * 16;
763
764 return size * channel_count * audio_bytes_per_sample(format);
765}
766
767static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
768 struct resampler_buffer* buffer)
769{
770 struct stream_in *in;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700771 size_t i;
Simon Wilson15f60a82012-04-24 20:56:32 -0700772
773 if (buffer_provider == NULL || buffer == NULL)
774 return -EINVAL;
775
776 in = (struct stream_in *)((char *)buffer_provider -
777 offsetof(struct stream_in, buf_provider));
778
779 if (in->pcm == NULL) {
780 buffer->raw = NULL;
781 buffer->frame_count = 0;
782 in->read_status = -ENODEV;
783 return -ENODEV;
784 }
785
786 if (in->frames_in == 0) {
787 in->read_status = pcm_read(in->pcm,
788 (void*)in->buffer,
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700789 pcm_frames_to_bytes(in->pcm, pcm_config_in.period_size));
Simon Wilson15f60a82012-04-24 20:56:32 -0700790 if (in->read_status != 0) {
791 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
792 buffer->raw = NULL;
793 buffer->frame_count = 0;
794 return in->read_status;
795 }
Eric Laurentd7abdd02012-07-27 14:54:41 -0700796
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700797 in->frames_in = pcm_config_in.period_size;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700798
799 /* Do stereo to mono conversion in place by discarding right channel */
800 for (i = 1; i < in->frames_in; i++)
801 in->buffer[i] = in->buffer[i * 2];
Simon Wilson15f60a82012-04-24 20:56:32 -0700802 }
803
804 buffer->frame_count = (buffer->frame_count > in->frames_in) ?
805 in->frames_in : buffer->frame_count;
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700806 buffer->i16 = in->buffer + (pcm_config_in.period_size - in->frames_in);
Simon Wilson15f60a82012-04-24 20:56:32 -0700807
808 return in->read_status;
809
810}
811
812static void release_buffer(struct resampler_buffer_provider *buffer_provider,
813 struct resampler_buffer* buffer)
814{
815 struct stream_in *in;
816
817 if (buffer_provider == NULL || buffer == NULL)
818 return;
819
820 in = (struct stream_in *)((char *)buffer_provider -
821 offsetof(struct stream_in, buf_provider));
822
823 in->frames_in -= buffer->frame_count;
824}
825
826/* read_frames() reads frames from kernel driver, down samples to capture rate
827 * if necessary and output the number of frames requested to the buffer specified */
828static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
829{
830 ssize_t frames_wr = 0;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700831 size_t frame_size = audio_stream_frame_size(&in->stream.common);
Simon Wilson15f60a82012-04-24 20:56:32 -0700832
833 while (frames_wr < frames) {
834 size_t frames_rd = frames - frames_wr;
835 if (in->resampler != NULL) {
836 in->resampler->resample_from_provider(in->resampler,
837 (int16_t *)((char *)buffer +
Eric Laurentd7abdd02012-07-27 14:54:41 -0700838 frames_wr * frame_size),
Simon Wilson15f60a82012-04-24 20:56:32 -0700839 &frames_rd);
840 } else {
841 struct resampler_buffer buf = {
842 { raw : NULL, },
843 frame_count : frames_rd,
844 };
845 get_next_buffer(&in->buf_provider, &buf);
846 if (buf.raw != NULL) {
847 memcpy((char *)buffer +
Eric Laurentd7abdd02012-07-27 14:54:41 -0700848 frames_wr * frame_size,
Simon Wilson15f60a82012-04-24 20:56:32 -0700849 buf.raw,
Eric Laurentd7abdd02012-07-27 14:54:41 -0700850 buf.frame_count * frame_size);
Simon Wilson15f60a82012-04-24 20:56:32 -0700851 frames_rd = buf.frame_count;
852 }
853 release_buffer(&in->buf_provider, &buf);
854 }
855 /* in->read_status is updated by getNextBuffer() also called by
856 * in->resampler->resample_from_provider() */
857 if (in->read_status != 0)
858 return in->read_status;
859
860 frames_wr += frames_rd;
861 }
862 return frames_wr;
863}
864
865/* API functions */
866
867static uint32_t out_get_sample_rate(const struct audio_stream *stream)
868{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700869 struct stream_out *out = (struct stream_out *)stream;
870
871 return out->config.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -0700872}
873
874static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
875{
876 return -ENOSYS;
877}
878
879static size_t out_get_buffer_size(const struct audio_stream *stream)
880{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700881 struct stream_out *out = (struct stream_out *)stream;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700882
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700883 return out->config.period_size *
884 audio_stream_frame_size((struct audio_stream *)stream);
Simon Wilson15f60a82012-04-24 20:56:32 -0700885}
886
Glenn Kastenca1414b2012-06-25 10:38:47 -0700887static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
Simon Wilson15f60a82012-04-24 20:56:32 -0700888{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700889 struct stream_out *out = (struct stream_out *)stream;
890
891 return out->channel_mask;
Simon Wilson15f60a82012-04-24 20:56:32 -0700892}
893
894static audio_format_t out_get_format(const struct audio_stream *stream)
895{
896 return AUDIO_FORMAT_PCM_16_BIT;
897}
898
899static int out_set_format(struct audio_stream *stream, audio_format_t format)
900{
901 return -ENOSYS;
902}
903
Glenn Kasten068b84e2012-09-26 12:34:51 -0700904/* Return the set of output devices associated with active streams
905 * other than out. Assumes out is non-NULL and out->dev is locked.
906 */
907static audio_devices_t output_devices(struct stream_out *out)
908{
909 struct audio_device *dev = out->dev;
910 enum output_type type;
911 audio_devices_t devices = AUDIO_DEVICE_NONE;
912
913 for (type = 0; type < OUTPUT_TOTAL; ++type) {
914 struct stream_out *other = dev->outputs[type];
915 if (other && (other != out) && !other->standby) {
916 /* safe to access other stream without a mutex,
917 * because we hold the dev lock,
918 * which prevents the other stream from being closed
919 */
920 devices |= other->device;
921 }
922 }
923
924 return devices;
925}
926
Simon Wilson459d5bd2012-08-21 12:18:07 -0700927static int do_out_standby(struct stream_out *out)
Simon Wilson15f60a82012-04-24 20:56:32 -0700928{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700929 struct audio_device *adev = out->dev;
Simon Wilson56d84e22012-08-17 13:55:27 -0700930 int i;
Simon Wilson15f60a82012-04-24 20:56:32 -0700931
Simon Wilson15f60a82012-04-24 20:56:32 -0700932 if (!out->standby) {
Simon Wilson56d84e22012-08-17 13:55:27 -0700933 for (i = 0; i < PCM_TOTAL; i++) {
934 if (out->pcm[i]) {
935 pcm_close(out->pcm[i]);
936 out->pcm[i] = NULL;
937 }
938 }
Simon Wilson15f60a82012-04-24 20:56:32 -0700939 out->standby = true;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700940
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700941 if (out == adev->outputs[OUTPUT_HDMI]) {
942 /* force standby on low latency output stream so that it can reuse HDMI driver if
943 * necessary when restarted */
944 force_non_hdmi_out_standby(adev);
945 }
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700946
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700947 /* re-calculate the set of active devices from other streams */
948 adev->out_device = output_devices(out);
Simon Wilson79a2e012012-10-19 14:20:33 -0700949
950 /* Skip resetting the mixer if no output device is active */
951 if (adev->out_device)
952 select_devices(adev);
Simon Wilson15f60a82012-04-24 20:56:32 -0700953 }
954
Simon Wilson459d5bd2012-08-21 12:18:07 -0700955 return 0;
956}
957
958static int out_standby(struct audio_stream *stream)
959{
960 struct stream_out *out = (struct stream_out *)stream;
961 int ret;
962
963 pthread_mutex_lock(&out->dev->lock);
964 pthread_mutex_lock(&out->lock);
965
966 ret = do_out_standby(out);
967
Simon Wilson15f60a82012-04-24 20:56:32 -0700968 pthread_mutex_unlock(&out->lock);
969 pthread_mutex_unlock(&out->dev->lock);
970
Simon Wilson459d5bd2012-08-21 12:18:07 -0700971 return ret;
Simon Wilson15f60a82012-04-24 20:56:32 -0700972}
973
974static int out_dump(const struct audio_stream *stream, int fd)
975{
976 return 0;
977}
978
979static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
980{
981 struct stream_out *out = (struct stream_out *)stream;
982 struct audio_device *adev = out->dev;
983 struct str_parms *parms;
984 char value[32];
985 int ret;
986 unsigned int val;
987
988 parms = str_parms_create_str(kvpairs);
989
990 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
991 value, sizeof(value));
992 pthread_mutex_lock(&adev->lock);
Eric Laurent87532032012-07-16 13:53:20 -0700993 pthread_mutex_lock(&out->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -0700994 if (ret >= 0) {
995 val = atoi(value);
Eric Laurent87532032012-07-16 13:53:20 -0700996 if ((out->device != val) && (val != 0)) {
Simon Wilson459d5bd2012-08-21 12:18:07 -0700997 /* Force standby if moving to/from SPDIF or if the output
998 * device changes when in SPDIF mode */
999 if (((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
Eric Laurent6a466d72012-08-28 12:13:38 -07001000 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
1001 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) {
Simon Wilson459d5bd2012-08-21 12:18:07 -07001002 do_out_standby(out);
1003 }
1004
Simon Wilsona282d2f2012-09-12 16:14:24 -07001005 /* Start/stop the BT SCO stream */
1006 if ((val & AUDIO_DEVICE_OUT_ALL_SCO) ^
1007 (adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO)) {
1008 if (val & AUDIO_DEVICE_OUT_ALL_SCO)
1009 start_bt_sco(adev);
1010 else
1011 stop_bt_sco(adev);
1012 }
1013
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001014 if (!out->standby && (out == adev->outputs[OUTPUT_HDMI] ||
1015 !adev->outputs[OUTPUT_HDMI] ||
1016 adev->outputs[OUTPUT_HDMI]->standby)) {
1017 adev->out_device = output_devices(out) | val;
Eric Laurent87532032012-07-16 13:53:20 -07001018 select_devices(adev);
1019 }
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001020 out->device = val;
Simon Wilson15f60a82012-04-24 20:56:32 -07001021 }
1022 }
Eric Laurent87532032012-07-16 13:53:20 -07001023 pthread_mutex_unlock(&out->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001024 pthread_mutex_unlock(&adev->lock);
1025
1026 str_parms_destroy(parms);
1027 return ret;
1028}
1029
1030static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
1031{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001032 struct stream_out *out = (struct stream_out *)stream;
1033 struct str_parms *query = str_parms_create_str(keys);
1034 char *str;
1035 char value[256];
1036 struct str_parms *reply = str_parms_create();
1037 size_t i, j;
1038 int ret;
1039 bool first = true;
1040
1041 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1042 if (ret >= 0) {
1043 value[0] = '\0';
1044 i = 0;
1045 /* the last entry in supported_channel_masks[] is always 0 */
1046 while (out->supported_channel_masks[i] != 0) {
1047 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1048 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1049 if (!first) {
1050 strcat(value, "|");
1051 }
1052 strcat(value, out_channels_name_to_enum_table[j].name);
1053 first = false;
1054 break;
1055 }
1056 }
1057 i++;
1058 }
1059 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1060 str = str_parms_to_str(reply);
1061 } else {
1062 str = strdup(keys);
1063 }
1064
1065 str_parms_destroy(query);
1066 str_parms_destroy(reply);
1067 return str;
Simon Wilson15f60a82012-04-24 20:56:32 -07001068}
1069
1070static uint32_t out_get_latency(const struct audio_stream_out *stream)
1071{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001072 struct stream_out *out = (struct stream_out *)stream;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001073
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001074 return (out->config.period_size * out->config.period_count * 1000) /
1075 out->config.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -07001076}
1077
1078static int out_set_volume(struct audio_stream_out *stream, float left,
1079 float right)
1080{
1081 return -ENOSYS;
1082}
1083
1084static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
1085 size_t bytes)
1086{
1087 int ret;
1088 struct stream_out *out = (struct stream_out *)stream;
1089 struct audio_device *adev = out->dev;
Simon Wilson56d84e22012-08-17 13:55:27 -07001090 int i;
Simon Wilson15f60a82012-04-24 20:56:32 -07001091
1092 /*
1093 * acquiring hw device mutex systematically is useful if a low
1094 * priority thread is waiting on the output stream mutex - e.g.
1095 * executing out_set_parameters() while holding the hw device
1096 * mutex
1097 */
1098 pthread_mutex_lock(&adev->lock);
1099 pthread_mutex_lock(&out->lock);
1100 if (out->standby) {
1101 ret = start_output_stream(out);
1102 if (ret != 0) {
1103 pthread_mutex_unlock(&adev->lock);
1104 goto exit;
1105 }
1106 out->standby = false;
1107 }
1108 pthread_mutex_unlock(&adev->lock);
1109
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001110 if (out->disabled) {
1111 ret = -EPIPE;
1112 goto exit;
1113 }
1114
Simon Wilson56d84e22012-08-17 13:55:27 -07001115 /* Write to all active PCMs */
1116 for (i = 0; i < PCM_TOTAL; i++)
1117 if (out->pcm[i])
1118 pcm_write(out->pcm[i], (void *)buffer, bytes);
Simon Wilson15f60a82012-04-24 20:56:32 -07001119
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001120
Simon Wilson15f60a82012-04-24 20:56:32 -07001121exit:
1122 pthread_mutex_unlock(&out->lock);
1123
1124 if (ret != 0) {
1125 usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
1126 out_get_sample_rate(&stream->common));
1127 }
1128
1129 return bytes;
1130}
1131
1132static int out_get_render_position(const struct audio_stream_out *stream,
1133 uint32_t *dsp_frames)
1134{
1135 return -EINVAL;
1136}
1137
1138static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1139{
1140 return 0;
1141}
1142
1143static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1144{
1145 return 0;
1146}
1147
1148static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1149 int64_t *timestamp)
1150{
1151 return -EINVAL;
1152}
1153
1154/** audio_stream_in implementation **/
1155static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1156{
1157 struct stream_in *in = (struct stream_in *)stream;
1158
1159 return in->requested_rate;
1160}
1161
1162static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1163{
1164 return 0;
1165}
1166
Eric Laurentd7abdd02012-07-27 14:54:41 -07001167static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
1168{
1169 return AUDIO_CHANNEL_IN_MONO;
1170}
1171
1172
Simon Wilson15f60a82012-04-24 20:56:32 -07001173static size_t in_get_buffer_size(const struct audio_stream *stream)
1174{
1175 struct stream_in *in = (struct stream_in *)stream;
1176
1177 return get_input_buffer_size(in->requested_rate,
1178 AUDIO_FORMAT_PCM_16_BIT,
Eric Laurentd7abdd02012-07-27 14:54:41 -07001179 popcount(in_get_channels(stream)));
Simon Wilson15f60a82012-04-24 20:56:32 -07001180}
1181
1182static audio_format_t in_get_format(const struct audio_stream *stream)
1183{
1184 return AUDIO_FORMAT_PCM_16_BIT;
1185}
1186
1187static int in_set_format(struct audio_stream *stream, audio_format_t format)
1188{
1189 return -ENOSYS;
1190}
1191
1192static int in_standby(struct audio_stream *stream)
1193{
1194 struct stream_in *in = (struct stream_in *)stream;
1195
1196 pthread_mutex_lock(&in->dev->lock);
1197 pthread_mutex_lock(&in->lock);
1198
1199 if (!in->standby) {
1200 pcm_close(in->pcm);
1201 in->pcm = NULL;
Eric Laurent87532032012-07-16 13:53:20 -07001202 in->dev->input_source = AUDIO_SOURCE_DEFAULT;
Eric Laurent42531fa2012-10-03 09:06:14 -07001203 in->dev->in_device = AUDIO_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -07001204 select_devices(in->dev);
Simon Wilson15f60a82012-04-24 20:56:32 -07001205 in->standby = true;
Eric Laurenta989ebf2012-10-15 15:14:44 -07001206
1207 in->dev->bubble_level->stop_polling(in->dev->bubble_level);
Simon Wilson15f60a82012-04-24 20:56:32 -07001208 }
1209
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001210 eS305_SetActiveIoHandle(ES305_IO_HANDLE_NONE);
1211
Simon Wilson15f60a82012-04-24 20:56:32 -07001212 pthread_mutex_unlock(&in->lock);
1213 pthread_mutex_unlock(&in->dev->lock);
1214
1215 return 0;
1216}
1217
1218static int in_dump(const struct audio_stream *stream, int fd)
1219{
1220 return 0;
1221}
1222
1223static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1224{
1225 struct stream_in *in = (struct stream_in *)stream;
1226 struct audio_device *adev = in->dev;
1227 struct str_parms *parms;
1228 char value[32];
1229 int ret;
1230 unsigned int val;
Eric Laurent87532032012-07-16 13:53:20 -07001231 bool apply_now = false;
Simon Wilson15f60a82012-04-24 20:56:32 -07001232
1233 parms = str_parms_create_str(kvpairs);
1234
Simon Wilson15f60a82012-04-24 20:56:32 -07001235 pthread_mutex_lock(&adev->lock);
Eric Laurent87532032012-07-16 13:53:20 -07001236 pthread_mutex_lock(&in->lock);
Eric Laurent42531fa2012-10-03 09:06:14 -07001237 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE,
1238 value, sizeof(value));
Simon Wilson15f60a82012-04-24 20:56:32 -07001239 if (ret >= 0) {
1240 val = atoi(value);
Eric Laurent87532032012-07-16 13:53:20 -07001241 /* no audio source uses val == 0 */
1242 if ((in->input_source != val) && (val != 0)) {
1243 in->input_source = val;
1244 apply_now = !in->standby;
Simon Wilson15f60a82012-04-24 20:56:32 -07001245 }
1246 }
Eric Laurent87532032012-07-16 13:53:20 -07001247
Eric Laurent42531fa2012-10-03 09:06:14 -07001248 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
1249 value, sizeof(value));
1250 if (ret >= 0) {
1251 val = atoi(value);
1252 /* no audio device uses val == 0 */
1253 if ((in->device != val) && (val != 0)) {
1254 in->device = val;
1255 apply_now = !in->standby;
1256 }
1257 }
1258
Eric Laurent87532032012-07-16 13:53:20 -07001259 if (apply_now) {
Eric Laurent87532032012-07-16 13:53:20 -07001260 adev->input_source = in->input_source;
Eric Laurent42531fa2012-10-03 09:06:14 -07001261 adev->in_device = in->device;
Eric Laurent87532032012-07-16 13:53:20 -07001262 select_devices(adev);
1263 }
1264
1265 pthread_mutex_unlock(&in->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001266 pthread_mutex_unlock(&adev->lock);
1267
1268 str_parms_destroy(parms);
1269 return ret;
1270}
1271
1272static char * in_get_parameters(const struct audio_stream *stream,
1273 const char *keys)
1274{
1275 return strdup("");
1276}
1277
1278static int in_set_gain(struct audio_stream_in *stream, float gain)
1279{
1280 return 0;
1281}
1282
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001283static void in_apply_ramp(struct stream_in *in, int16_t *buffer, size_t frames)
1284{
1285 size_t i;
1286 uint16_t vol = in->ramp_vol;
1287 uint16_t step = in->ramp_step;
1288
1289 frames = (frames < in->ramp_frames) ? frames : in->ramp_frames;
1290
1291 for (i = 0; i < frames; i++)
1292 {
1293 buffer[i] = (int16_t)((buffer[i] * vol) >> 16);
1294 vol += step;
1295 }
1296
1297 in->ramp_vol = vol;
1298 in->ramp_frames -= frames;
1299}
1300
Simon Wilson15f60a82012-04-24 20:56:32 -07001301static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
1302 size_t bytes)
1303{
1304 int ret = 0;
1305 struct stream_in *in = (struct stream_in *)stream;
1306 struct audio_device *adev = in->dev;
1307 size_t frames_rq = bytes / audio_stream_frame_size(&stream->common);
1308
1309 /*
1310 * acquiring hw device mutex systematically is useful if a low
1311 * priority thread is waiting on the input stream mutex - e.g.
1312 * executing in_set_parameters() while holding the hw device
1313 * mutex
1314 */
1315 pthread_mutex_lock(&adev->lock);
1316 pthread_mutex_lock(&in->lock);
1317 if (in->standby) {
1318 ret = start_input_stream(in);
1319 if (ret == 0)
1320 in->standby = 0;
1321 }
1322 pthread_mutex_unlock(&adev->lock);
1323
1324 if (ret < 0)
1325 goto exit;
1326
1327 /*if (in->num_preprocessors != 0)
1328 ret = process_frames(in, buffer, frames_rq);
Eric Laurentd7abdd02012-07-27 14:54:41 -07001329 else */
1330 ret = read_frames(in, buffer, frames_rq);
Simon Wilson15f60a82012-04-24 20:56:32 -07001331
1332 if (ret > 0)
1333 ret = 0;
1334
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001335 if (in->ramp_frames > 0)
1336 in_apply_ramp(in, buffer, frames_rq);
1337
Simon Wilson15f60a82012-04-24 20:56:32 -07001338 /*
1339 * Instead of writing zeroes here, we could trust the hardware
1340 * to always provide zeroes when muted.
1341 */
1342 if (ret == 0 && adev->mic_mute)
1343 memset(buffer, 0, bytes);
1344
1345exit:
1346 if (ret < 0)
1347 usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
1348 in_get_sample_rate(&stream->common));
1349
1350 pthread_mutex_unlock(&in->lock);
1351 return bytes;
1352}
1353
1354static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1355{
1356 return 0;
1357}
1358
1359static int in_add_audio_effect(const struct audio_stream *stream,
1360 effect_handle_t effect)
1361{
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001362 struct stream_in *in = (struct stream_in *)stream;
1363 effect_descriptor_t descr;
1364 if ((*effect)->get_descriptor(effect, &descr) == 0) {
1365
1366 pthread_mutex_lock(&in->dev->lock);
1367 pthread_mutex_lock(&in->lock);
1368
1369 eS305_AddEffect(&descr, in->io_handle);
1370
1371 pthread_mutex_unlock(&in->lock);
1372 pthread_mutex_unlock(&in->dev->lock);
1373 }
1374
Simon Wilson15f60a82012-04-24 20:56:32 -07001375 return 0;
1376}
1377
1378static int in_remove_audio_effect(const struct audio_stream *stream,
1379 effect_handle_t effect)
1380{
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001381 struct stream_in *in = (struct stream_in *)stream;
1382 effect_descriptor_t descr;
1383 if ((*effect)->get_descriptor(effect, &descr) == 0) {
1384
1385 pthread_mutex_lock(&in->dev->lock);
1386 pthread_mutex_lock(&in->lock);
1387
1388 eS305_RemoveEffect(&descr, in->io_handle);
1389
1390 pthread_mutex_unlock(&in->lock);
1391 pthread_mutex_unlock(&in->dev->lock);
1392 }
1393
Simon Wilson15f60a82012-04-24 20:56:32 -07001394 return 0;
1395}
1396
Simon Wilson15f60a82012-04-24 20:56:32 -07001397static int adev_open_output_stream(struct audio_hw_device *dev,
1398 audio_io_handle_t handle,
1399 audio_devices_t devices,
1400 audio_output_flags_t flags,
1401 struct audio_config *config,
1402 struct audio_stream_out **stream_out)
1403{
1404 struct audio_device *adev = (struct audio_device *)dev;
1405 struct stream_out *out;
1406 int ret;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001407 enum output_type type;
Simon Wilson15f60a82012-04-24 20:56:32 -07001408
1409 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1410 if (!out)
1411 return -ENOMEM;
1412
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001413 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1414 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1415 if (devices == AUDIO_DEVICE_NONE)
1416 devices = AUDIO_DEVICE_OUT_SPEAKER;
1417 out->device = devices;
1418
1419 if (flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1420 devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1421 pthread_mutex_lock(&adev->lock);
1422 ret = read_hdmi_channel_masks(adev, out);
1423 pthread_mutex_unlock(&adev->lock);
1424 if (ret != 0)
1425 goto err_open;
1426 if (config->sample_rate == 0)
1427 config->sample_rate = HDMI_MULTI_DEFAULT_SAMPLING_RATE;
1428 if (config->channel_mask == 0)
1429 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1430 out->channel_mask = config->channel_mask;
1431 out->config = pcm_config_hdmi_multi;
1432 out->config.rate = config->sample_rate;
1433 out->config.channels = popcount(config->channel_mask);
1434 out->pcm_device = PCM_DEVICE;
1435 type = OUTPUT_HDMI;
1436 } else if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1437 out->config = pcm_config_deep;
1438 out->pcm_device = PCM_DEVICE_DEEP;
1439 type = OUTPUT_DEEP_BUF;
1440 } else {
1441 out->config = pcm_config;
1442 out->pcm_device = PCM_DEVICE;
1443 type = OUTPUT_LOW_LATENCY;
1444 }
1445
Simon Wilson15f60a82012-04-24 20:56:32 -07001446 out->stream.common.get_sample_rate = out_get_sample_rate;
1447 out->stream.common.set_sample_rate = out_set_sample_rate;
1448 out->stream.common.get_buffer_size = out_get_buffer_size;
1449 out->stream.common.get_channels = out_get_channels;
1450 out->stream.common.get_format = out_get_format;
1451 out->stream.common.set_format = out_set_format;
1452 out->stream.common.standby = out_standby;
1453 out->stream.common.dump = out_dump;
1454 out->stream.common.set_parameters = out_set_parameters;
1455 out->stream.common.get_parameters = out_get_parameters;
1456 out->stream.common.add_audio_effect = out_add_audio_effect;
1457 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1458 out->stream.get_latency = out_get_latency;
1459 out->stream.set_volume = out_set_volume;
1460 out->stream.write = out_write;
1461 out->stream.get_render_position = out_get_render_position;
1462 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1463
1464 out->dev = adev;
1465
1466 config->format = out_get_format(&out->stream.common);
1467 config->channel_mask = out_get_channels(&out->stream.common);
1468 config->sample_rate = out_get_sample_rate(&out->stream.common);
1469
1470 out->standby = true;
1471
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001472 pthread_mutex_lock(&adev->lock);
1473 if (adev->outputs[type]) {
1474 pthread_mutex_unlock(&adev->lock);
1475 ret = -EBUSY;
1476 goto err_open;
1477 }
1478 adev->outputs[type] = out;
1479 pthread_mutex_unlock(&adev->lock);
1480
Simon Wilson15f60a82012-04-24 20:56:32 -07001481 *stream_out = &out->stream;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001482
Simon Wilson15f60a82012-04-24 20:56:32 -07001483 return 0;
1484
1485err_open:
1486 free(out);
1487 *stream_out = NULL;
1488 return ret;
1489}
1490
1491static void adev_close_output_stream(struct audio_hw_device *dev,
1492 struct audio_stream_out *stream)
1493{
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001494 struct audio_device *adev;
1495 enum output_type type;
1496
Simon Wilson15f60a82012-04-24 20:56:32 -07001497 out_standby(&stream->common);
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001498 adev = (struct audio_device *)dev;
1499 pthread_mutex_lock(&adev->lock);
1500 for (type = 0; type < OUTPUT_TOTAL; ++type) {
1501 if (adev->outputs[type] == (struct stream_out *) stream) {
1502 adev->outputs[type] = NULL;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001503 break;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001504 }
1505 }
1506 pthread_mutex_unlock(&adev->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001507 free(stream);
1508}
1509
1510static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1511{
Eric Laurenta989ebf2012-10-15 15:14:44 -07001512 return 0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001513}
1514
1515static char * adev_get_parameters(const struct audio_hw_device *dev,
1516 const char *keys)
1517{
Eric Laurent688880c2012-09-07 16:46:00 -07001518 struct audio_device *adev = (struct audio_device *)dev;
1519 struct str_parms *parms = str_parms_create_str(keys);
1520 char value[32];
1521 int ret = str_parms_get_str(parms, "ec_supported", value, sizeof(value));
1522 char *str;
1523
1524 str_parms_destroy(parms);
1525 if (ret >= 0) {
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001526 parms = str_parms_create_str("ec_supported=yes");
Eric Laurent688880c2012-09-07 16:46:00 -07001527 str = str_parms_to_str(parms);
1528 str_parms_destroy(parms);
1529 return str;
1530 }
Simon Wilson15f60a82012-04-24 20:56:32 -07001531 return strdup("");
1532}
1533
1534static int adev_init_check(const struct audio_hw_device *dev)
1535{
1536 return 0;
1537}
1538
1539static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1540{
1541 return -ENOSYS;
1542}
1543
1544static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1545{
1546 return -ENOSYS;
1547}
1548
1549static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1550{
1551 return 0;
1552}
1553
1554static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1555{
1556 struct audio_device *adev = (struct audio_device *)dev;
1557
1558 adev->mic_mute = state;
1559
1560 return 0;
1561}
1562
1563static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1564{
1565 struct audio_device *adev = (struct audio_device *)dev;
1566
1567 *state = adev->mic_mute;
1568
1569 return 0;
1570}
1571
1572static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1573 const struct audio_config *config)
1574{
1575
1576 return get_input_buffer_size(config->sample_rate, config->format,
1577 popcount(config->channel_mask));
1578}
1579
1580static int adev_open_input_stream(struct audio_hw_device *dev,
1581 audio_io_handle_t handle,
1582 audio_devices_t devices,
1583 struct audio_config *config,
1584 struct audio_stream_in **stream_in)
1585{
1586 struct audio_device *adev = (struct audio_device *)dev;
1587 struct stream_in *in;
1588 int ret;
1589
1590 *stream_in = NULL;
1591
Eric Laurentd7abdd02012-07-27 14:54:41 -07001592 /* Respond with a request for mono if a different format is given. */
1593 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
1594 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
Simon Wilson15f60a82012-04-24 20:56:32 -07001595 return -EINVAL;
1596 }
1597
1598 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
1599 if (!in)
1600 return -ENOMEM;
1601
1602 in->stream.common.get_sample_rate = in_get_sample_rate;
1603 in->stream.common.set_sample_rate = in_set_sample_rate;
1604 in->stream.common.get_buffer_size = in_get_buffer_size;
1605 in->stream.common.get_channels = in_get_channels;
1606 in->stream.common.get_format = in_get_format;
1607 in->stream.common.set_format = in_set_format;
1608 in->stream.common.standby = in_standby;
1609 in->stream.common.dump = in_dump;
1610 in->stream.common.set_parameters = in_set_parameters;
1611 in->stream.common.get_parameters = in_get_parameters;
1612 in->stream.common.add_audio_effect = in_add_audio_effect;
1613 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1614 in->stream.set_gain = in_set_gain;
1615 in->stream.read = in_read;
1616 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1617
1618 in->dev = adev;
1619 in->standby = true;
1620 in->requested_rate = config->sample_rate;
Eric Laurent87532032012-07-16 13:53:20 -07001621 in->input_source = AUDIO_SOURCE_DEFAULT;
Eric Laurent42531fa2012-10-03 09:06:14 -07001622 in->device = devices;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001623 in->io_handle = handle;
Simon Wilson15f60a82012-04-24 20:56:32 -07001624
Glenn Kasten7ecf6232012-09-28 12:01:31 -07001625 in->buffer = malloc(pcm_config_in.period_size * pcm_config_in.channels
Eric Laurentd7abdd02012-07-27 14:54:41 -07001626 * audio_stream_frame_size(&in->stream.common));
1627
Simon Wilson15f60a82012-04-24 20:56:32 -07001628 if (!in->buffer) {
1629 ret = -ENOMEM;
1630 goto err_malloc;
1631 }
1632
Glenn Kasten7ecf6232012-09-28 12:01:31 -07001633 if (in->requested_rate != pcm_config_in.rate) {
Simon Wilson15f60a82012-04-24 20:56:32 -07001634 in->buf_provider.get_next_buffer = get_next_buffer;
1635 in->buf_provider.release_buffer = release_buffer;
1636
Glenn Kasten7ecf6232012-09-28 12:01:31 -07001637 ret = create_resampler(pcm_config_in.rate,
Simon Wilson15f60a82012-04-24 20:56:32 -07001638 in->requested_rate,
Eric Laurentd7abdd02012-07-27 14:54:41 -07001639 1,
Simon Wilson15f60a82012-04-24 20:56:32 -07001640 RESAMPLER_QUALITY_DEFAULT,
1641 &in->buf_provider,
1642 &in->resampler);
1643 if (ret != 0) {
1644 ret = -EINVAL;
1645 goto err_resampler;
1646 }
1647 }
1648
1649 *stream_in = &in->stream;
1650 return 0;
1651
1652err_resampler:
1653 free(in->buffer);
1654err_malloc:
1655 free(in);
1656 return ret;
1657}
1658
1659static void adev_close_input_stream(struct audio_hw_device *dev,
1660 struct audio_stream_in *stream)
1661{
1662 struct stream_in *in = (struct stream_in *)stream;
1663
1664 in_standby(&stream->common);
1665 if (in->resampler) {
1666 release_resampler(in->resampler);
1667 in->resampler = NULL;
1668 }
1669 free(in->buffer);
1670 free(stream);
1671}
1672
1673static int adev_dump(const audio_hw_device_t *device, int fd)
1674{
1675 return 0;
1676}
1677
1678static int adev_close(hw_device_t *device)
1679{
1680 struct audio_device *adev = (struct audio_device *)device;
1681
1682 audio_route_free(adev->ar);
1683
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001684 eS305_Release();
1685
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001686 if (adev->hdmi_drv_fd >= 0)
1687 close(adev->hdmi_drv_fd);
Eric Laurent688880c2012-09-07 16:46:00 -07001688
Eric Laurenta989ebf2012-10-15 15:14:44 -07001689 bubble_level_release(adev->bubble_level);
1690
Simon Wilson15f60a82012-04-24 20:56:32 -07001691 free(device);
1692 return 0;
1693}
1694
Simon Wilson15f60a82012-04-24 20:56:32 -07001695static int adev_open(const hw_module_t* module, const char* name,
1696 hw_device_t** device)
1697{
1698 struct audio_device *adev;
1699 int ret;
1700
1701 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1702 return -EINVAL;
1703
1704 adev = calloc(1, sizeof(struct audio_device));
1705 if (!adev)
1706 return -ENOMEM;
1707
1708 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent6a466d72012-08-28 12:13:38 -07001709 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001710 adev->hw_device.common.module = (struct hw_module_t *) module;
1711 adev->hw_device.common.close = adev_close;
1712
Simon Wilson15f60a82012-04-24 20:56:32 -07001713 adev->hw_device.init_check = adev_init_check;
1714 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1715 adev->hw_device.set_master_volume = adev_set_master_volume;
1716 adev->hw_device.set_mode = adev_set_mode;
1717 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1718 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1719 adev->hw_device.set_parameters = adev_set_parameters;
1720 adev->hw_device.get_parameters = adev_get_parameters;
1721 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1722 adev->hw_device.open_output_stream = adev_open_output_stream;
1723 adev->hw_device.close_output_stream = adev_close_output_stream;
1724 adev->hw_device.open_input_stream = adev_open_input_stream;
1725 adev->hw_device.close_input_stream = adev_close_input_stream;
1726 adev->hw_device.dump = adev_dump;
1727
1728 adev->ar = audio_route_init();
Eric Laurent87532032012-07-16 13:53:20 -07001729 adev->input_source = AUDIO_SOURCE_DEFAULT;
1730 /* adev->cur_route_id initial value is 0 and such that first device
1731 * selection is always applied by select_devices() */
Simon Wilson15f60a82012-04-24 20:56:32 -07001732
Eric Laurent688880c2012-09-07 16:46:00 -07001733 adev->es305_preset = ES305_PRESET_INIT;
Eric Laurenta989ebf2012-10-15 15:14:44 -07001734 adev->es305_new_mode = ES305_MODE_LEVEL;
1735 adev->es305_mode = ES305_MODE_LEVEL;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001736 adev->hdmi_drv_fd = -1;
Simon Wilson15f60a82012-04-24 20:56:32 -07001737 *device = &adev->hw_device.common;
1738
Eric Laurenta989ebf2012-10-15 15:14:44 -07001739 adev->bubble_level = bubble_level_create();
1740 adev->bubble_level->set_callback(adev->bubble_level, bubblelevel_callback, adev);
1741
Simon Wilson15f60a82012-04-24 20:56:32 -07001742 return 0;
1743}
1744
1745static struct hw_module_methods_t hal_module_methods = {
1746 .open = adev_open,
1747};
1748
1749struct audio_module HAL_MODULE_INFO_SYM = {
1750 .common = {
1751 .tag = HARDWARE_MODULE_TAG,
1752 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1753 .hal_api_version = HARDWARE_HAL_API_VERSION,
1754 .id = AUDIO_HARDWARE_MODULE_ID,
1755 .name = "Manta audio HW HAL",
1756 .author = "The Android Open Source Project",
1757 .methods = &hal_module_methods,
1758 },
1759};