blob: 8bd0ce97bf5ae6eaba6e7158e082800f3e021a9b [file] [log] [blame]
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#define LOG_TAG "audio.primary.msm8660"
19//#define LOG_NDEBUG 0
20
21#include <stdint.h>
22
23#include <hardware/hardware.h>
24#include <system/audio.h>
25#include <hardware/audio.h>
26
27#include <hardware_legacy/AudioHardwareInterface.h>
28#include <hardware_legacy/AudioSystemLegacy.h>
29
30namespace android_audio_legacy {
31
32extern "C" {
33
34struct qcom_audio_module {
35 struct audio_module module;
36};
37
38struct qcom_audio_device {
39 struct audio_hw_device device;
40
41 struct AudioHardwareInterface *hwif;
42};
43
44struct qcom_stream_out {
45 struct audio_stream_out stream;
46
47 AudioStreamOut *qcom_out;
48};
49
50struct qcom_stream_in {
51 struct audio_stream_in stream;
52
53 AudioStreamIn *qcom_in;
54};
55
56enum {
57 HAL_API_REV_1_0,
58 HAL_API_REV_2_0,
59 HAL_API_REV_NUM
60} hal_api_rev;
61
62static uint32_t audio_device_conv_table[][HAL_API_REV_NUM] =
63{
64 /* output devices */
65 { AudioSystem::DEVICE_OUT_EARPIECE, AUDIO_DEVICE_OUT_EARPIECE },
66 { AudioSystem::DEVICE_OUT_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER },
67 { AudioSystem::DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET },
68 { AudioSystem::DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADPHONE },
69 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO, AUDIO_DEVICE_OUT_BLUETOOTH_SCO },
70 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET },
71 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT },
72 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP },
73 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES },
74 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER },
75 { AudioSystem::DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_AUX_DIGITAL },
76 { AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET },
77 { AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET },
78 { AudioSystem::DEVICE_OUT_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT },
79#ifdef QCOM_ANC_HEADSET_ENABLED
80 { AudioSystem::DEVICE_OUT_ANC_HEADSET, AUDIO_DEVICE_OUT_ANC_HEADSET },
81 { AudioSystem::DEVICE_OUT_ANC_HEADPHONE, AUDIO_DEVICE_OUT_ANC_HEADPHONE },
82#endif
83#ifdef QCOM_FM_ENABLED
84 { AudioSystem::DEVICE_OUT_FM, AUDIO_DEVICE_OUT_FM },
85#endif
86#ifdef QCOM_FM_TX_ENABLED
87 { AudioSystem::DEVICE_OUT_FM_TX, AUDIO_DEVICE_OUT_FM_TX },
88#endif
89#ifdef QCOM_VOIP_ENABLED
90 //{ AudioSystem::DEVICE_OUT_DIRECTOUTPUT, AUDIO_DEVICE_OUT_DIRECTOUTPUT },
91#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +000092 /* input devices */
93 { AudioSystem::DEVICE_IN_COMMUNICATION, AUDIO_DEVICE_IN_COMMUNICATION },
94 { AudioSystem::DEVICE_IN_AMBIENT, AUDIO_DEVICE_IN_AMBIENT },
95 { AudioSystem::DEVICE_IN_BUILTIN_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC },
96 { AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET },
97 { AudioSystem::DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET },
98 { AudioSystem::DEVICE_IN_AUX_DIGITAL, AUDIO_DEVICE_IN_AUX_DIGITAL },
99 { AudioSystem::DEVICE_IN_VOICE_CALL, AUDIO_DEVICE_IN_VOICE_CALL },
100 { AudioSystem::DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BACK_MIC },
101 { AudioSystem::DEVICE_IN_DEFAULT, AUDIO_DEVICE_IN_DEFAULT },
102#ifdef QCOM_ANC_HEADSET_ENABLED
103 { AudioSystem::DEVICE_IN_ANC_HEADSET, AUDIO_DEVICE_IN_ANC_HEADSET },
104#endif
105#ifdef QCOM_FM_ENABLED
106 { AudioSystem::DEVICE_IN_FM_RX, AUDIO_DEVICE_IN_FM_RX },
107 { AudioSystem::DEVICE_IN_FM_RX_A2DP, AUDIO_DEVICE_IN_FM_RX_A2DP },
108#endif
109};
110
111static uint32_t convert_audio_device(uint32_t from_device, int from_rev, int to_rev)
112{
113 const uint32_t k_num_devices = sizeof(audio_device_conv_table)/sizeof(uint32_t)/HAL_API_REV_NUM;
114 uint32_t to_device = AUDIO_DEVICE_NONE;
115 uint32_t in_bit = 0;
116
117 if (from_rev != HAL_API_REV_1_0) {
118 in_bit = from_device & AUDIO_DEVICE_BIT_IN;
119 from_device &= ~AUDIO_DEVICE_BIT_IN;
120 }
121
122 while (from_device) {
123 uint32_t i = 31 - __builtin_clz(from_device);
124 uint32_t cur_device = (1 << i) | in_bit;
125
126 for (i = 0; i < k_num_devices; i++) {
127 if (audio_device_conv_table[i][from_rev] == cur_device) {
128 to_device |= audio_device_conv_table[i][to_rev];
129 break;
130 }
131 }
132 from_device &= ~cur_device;
133 }
134 return to_device;
135}
136
137/** audio_stream_out implementation **/
138static uint32_t out_get_sample_rate(const struct audio_stream *stream)
139{
140 const struct qcom_stream_out *out =
141 reinterpret_cast<const struct qcom_stream_out *>(stream);
142 return out->qcom_out->sampleRate();
143}
144
145static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
146{
147 struct qcom_stream_out *out =
148 reinterpret_cast<struct qcom_stream_out *>(stream);
149
150 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
151 /* TODO: implement this */
152 return 0;
153}
154
155static size_t out_get_buffer_size(const struct audio_stream *stream)
156{
157 const struct qcom_stream_out *out =
158 reinterpret_cast<const struct qcom_stream_out *>(stream);
159 return out->qcom_out->bufferSize();
160}
161
162static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
163{
164 const struct qcom_stream_out *out =
165 reinterpret_cast<const struct qcom_stream_out *>(stream);
Arne Coucheron73554f02013-03-28 13:01:31 +0100166 return (audio_channel_mask_t) out->qcom_out->channels();
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000167}
168
169static audio_format_t out_get_format(const struct audio_stream *stream)
170{
171 const struct qcom_stream_out *out =
172 reinterpret_cast<const struct qcom_stream_out *>(stream);
173 return (audio_format_t)out->qcom_out->format();
174}
175
176static int out_set_format(struct audio_stream *stream, audio_format_t format)
177{
178 struct qcom_stream_out *out =
179 reinterpret_cast<struct qcom_stream_out *>(stream);
180 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
181 /* TODO: implement me */
182 return 0;
183}
184
185static int out_standby(struct audio_stream *stream)
186{
187 struct qcom_stream_out *out =
188 reinterpret_cast<struct qcom_stream_out *>(stream);
189 return out->qcom_out->standby();
190}
191
192static int out_dump(const struct audio_stream *stream, int fd)
193{
194 const struct qcom_stream_out *out =
195 reinterpret_cast<const struct qcom_stream_out *>(stream);
196 Vector<String16> args;
197 return out->qcom_out->dump(fd, args);
198}
199
200static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
201{
202 struct qcom_stream_out *out =
203 reinterpret_cast<struct qcom_stream_out *>(stream);
204 int val;
205 String8 s8 = String8(kvpairs);
206 AudioParameter parms = AudioParameter(String8(kvpairs));
207
208 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
209 val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0);
210 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
211 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
212 s8 = parms.toString();
213 }
214
215 return out->qcom_out->setParameters(s8);
216}
217
218static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
219{
220 const struct qcom_stream_out *out =
221 reinterpret_cast<const struct qcom_stream_out *>(stream);
222 String8 s8;
223 int val;
224
225 s8 = out->qcom_out->getParameters(String8(keys));
226
227 AudioParameter parms = AudioParameter(s8);
228 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
229 val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0);
230 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
231 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
232 s8 = parms.toString();
233 }
234
235 return strdup(s8.string());
236}
237
238static uint32_t out_get_latency(const struct audio_stream_out *stream)
239{
240 const struct qcom_stream_out *out =
241 reinterpret_cast<const struct qcom_stream_out *>(stream);
242 return out->qcom_out->latency();
243}
244
245static int out_set_volume(struct audio_stream_out *stream, float left,
246 float right)
247{
248 struct qcom_stream_out *out =
249 reinterpret_cast<struct qcom_stream_out *>(stream);
250 return out->qcom_out->setVolume(left, right);
251}
252
253static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
254 size_t bytes)
255{
256 struct qcom_stream_out *out =
257 reinterpret_cast<struct qcom_stream_out *>(stream);
258 usleep(5);
259 return out->qcom_out->write(buffer, bytes);
260}
261
262static int out_get_render_position(const struct audio_stream_out *stream,
263 uint32_t *dsp_frames)
264{
265 const struct qcom_stream_out *out =
266 reinterpret_cast<const struct qcom_stream_out *>(stream);
267 return out->qcom_out->getRenderPosition(dsp_frames);
268}
269
270static int out_set_observer(const struct audio_stream_out *stream,
271 void *observer)
272{
273 const struct qcom_stream_out *out =
274 reinterpret_cast<const struct qcom_stream_out *>(stream);
275 return out->qcom_out->setObserver(observer);
276}
277
278static int out_get_buffer_info(const struct audio_stream_out *stream,
279 buf_info ** buf)
280{
281 const struct qcom_stream_out *out =
282 reinterpret_cast<const struct qcom_stream_out *>(stream);
283 return out->qcom_out->getBufferInfo(buf);
284}
285
286static int out_is_buffer_available(const struct audio_stream_out *stream,
287 int *isAvail)
288{
289 const struct qcom_stream_out *out =
290 reinterpret_cast<const struct qcom_stream_out *>(stream);
291 return out->qcom_out->isBufferAvailable(isAvail);
292}
293
294static status_t out_start(struct audio_stream_out *stream)
295{
296 struct qcom_stream_out *out =
297 reinterpret_cast<struct qcom_stream_out *>(stream);
298 return out->qcom_out->start();
299}
300
301static status_t out_pause(struct audio_stream_out *stream)
302{
303 struct qcom_stream_out *out =
304 reinterpret_cast<struct qcom_stream_out *>(stream);
305 return out->qcom_out->pause();
306}
307
308static status_t out_flush(struct audio_stream_out *stream)
309{
310 struct qcom_stream_out *out =
311 reinterpret_cast<struct qcom_stream_out *>(stream);
312 return out->qcom_out->flush();
313}
314
315static status_t out_stop(struct audio_stream_out *stream)
316{
317 struct qcom_stream_out *out =
318 reinterpret_cast<struct qcom_stream_out *>(stream);
319 return out->qcom_out->stop();
320}
321
322static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
323{
324 return 0;
325}
326
327static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
328{
329 return 0;
330}
331
332static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
333 int64_t *timestamp)
334{
335 const struct qcom_stream_out *out =
336 reinterpret_cast<const struct qcom_stream_out *>(stream);
337 return out->qcom_out->getNextWriteTimestamp(timestamp);
338}
339
340/** audio_stream_in implementation **/
341static uint32_t in_get_sample_rate(const struct audio_stream *stream)
342{
343 const struct qcom_stream_in *in =
344 reinterpret_cast<const struct qcom_stream_in *>(stream);
345 return in->qcom_in->sampleRate();
346}
347
348static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
349{
350 struct qcom_stream_in *in =
351 reinterpret_cast<struct qcom_stream_in *>(stream);
352
353 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
354 /* TODO: implement this */
355 return 0;
356}
357
358static size_t in_get_buffer_size(const struct audio_stream *stream)
359{
360 const struct qcom_stream_in *in =
361 reinterpret_cast<const struct qcom_stream_in *>(stream);
362 return in->qcom_in->bufferSize();
363}
364
365static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
366{
367 const struct qcom_stream_in *in =
368 reinterpret_cast<const struct qcom_stream_in *>(stream);
Arne Coucheron73554f02013-03-28 13:01:31 +0100369 return (audio_channel_mask_t) in->qcom_in->channels();
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000370}
371
372static audio_format_t in_get_format(const struct audio_stream *stream)
373{
374 const struct qcom_stream_in *in =
375 reinterpret_cast<const struct qcom_stream_in *>(stream);
376 return (audio_format_t)in->qcom_in->format();
377}
378
379static int in_set_format(struct audio_stream *stream, audio_format_t format)
380{
381 struct qcom_stream_in *in =
382 reinterpret_cast<struct qcom_stream_in *>(stream);
383 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
384 /* TODO: implement me */
385 return 0;
386}
387
388static int in_standby(struct audio_stream *stream)
389{
390 struct qcom_stream_in *in = reinterpret_cast<struct qcom_stream_in *>(stream);
391 return in->qcom_in->standby();
392}
393
394static int in_dump(const struct audio_stream *stream, int fd)
395{
396 const struct qcom_stream_in *in =
397 reinterpret_cast<const struct qcom_stream_in *>(stream);
398 Vector<String16> args;
399 return in->qcom_in->dump(fd, args);
400}
401
402static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
403{
404 struct qcom_stream_in *in =
405 reinterpret_cast<struct qcom_stream_in *>(stream);
406 int val;
407 AudioParameter parms = AudioParameter(String8(kvpairs));
408 String8 s8 = String8(kvpairs);
409
410 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
411 val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0);
412 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
413 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
414 s8 = parms.toString();
415 }
416
417 return in->qcom_in->setParameters(s8);
418}
419
420static char * in_get_parameters(const struct audio_stream *stream,
421 const char *keys)
422{
423 const struct qcom_stream_in *in =
424 reinterpret_cast<const struct qcom_stream_in *>(stream);
425 String8 s8;
426 int val;
427
428 s8 = in->qcom_in->getParameters(String8(keys));
429
430 AudioParameter parms = AudioParameter(s8);
431 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
432 val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0);
433 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
434 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
435 s8 = parms.toString();
436 }
437
438 return strdup(s8.string());
439}
440
441static int in_set_gain(struct audio_stream_in *stream, float gain)
442{
443 struct qcom_stream_in *in =
444 reinterpret_cast<struct qcom_stream_in *>(stream);
445 return in->qcom_in->setGain(gain);
446}
447
448static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
449 size_t bytes)
450{
451 struct qcom_stream_in *in =
452 reinterpret_cast<struct qcom_stream_in *>(stream);
453 return in->qcom_in->read(buffer, bytes);
454}
455
456static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
457{
458 struct qcom_stream_in *in =
459 reinterpret_cast<struct qcom_stream_in *>(stream);
460 return in->qcom_in->getInputFramesLost();
461}
462
463static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
464{
465 const struct qcom_stream_in *in =
466 reinterpret_cast<const struct qcom_stream_in *>(stream);
467 return in->qcom_in->addAudioEffect(effect);
468}
469
470static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
471{
472 const struct qcom_stream_in *in =
473 reinterpret_cast<const struct qcom_stream_in *>(stream);
474 return in->qcom_in->removeAudioEffect(effect);
475}
476
477/** audio_hw_device implementation **/
478static inline struct qcom_audio_device * to_ladev(struct audio_hw_device *dev)
479{
480 return reinterpret_cast<struct qcom_audio_device *>(dev);
481}
482
483static inline const struct qcom_audio_device * to_cladev(const struct audio_hw_device *dev)
484{
485 return reinterpret_cast<const struct qcom_audio_device *>(dev);
486}
487
Mike Grissom20204112013-08-06 16:38:39 -0700488static uint32_t adev_get_supported_devices(const struct audio_hw_device *dev)
489{
490 /* XXX: The old AudioHardwareInterface interface is not smart enough to
491* tell us this, so we'll lie and basically tell AF that we support the
492* below input/output devices and cross our fingers. To do things properly,
493* audio hardware interfaces that need advanced features (like this) should
494* convert to the new HAL interface and not use this wrapper. */
495 return (/* OUT */
496 AUDIO_DEVICE_OUT_EARPIECE |
497 AUDIO_DEVICE_OUT_SPEAKER |
498 AUDIO_DEVICE_OUT_WIRED_HEADSET |
499 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
500 AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
501 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
502 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
503 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
504 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
505 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
506 AUDIO_DEVICE_OUT_AUX_DIGITAL |
507 AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
508 AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
509 AUDIO_DEVICE_OUT_USB_ACCESSORY |
510 AUDIO_DEVICE_OUT_USB_DEVICE |
511 AUDIO_DEVICE_OUT_REMOTE_SUBMIX |
512#ifdef QCOM_ANC_HEADSET_ENABLED
513 AUDIO_DEVICE_OUT_ANC_HEADSET |
514 AUDIO_DEVICE_OUT_ANC_HEADPHONE |
515#endif
Mike Grissom20204112013-08-06 16:38:39 -0700516#if defined(QCOM_FM_ENABLED) || defined(STE_FM)
517 AUDIO_DEVICE_OUT_FM |
518 AUDIO_DEVICE_OUT_FM_TX |
519#endif
520 AUDIO_DEVICE_OUT_DEFAULT |
521 /* IN */
522 AUDIO_DEVICE_IN_COMMUNICATION |
523 AUDIO_DEVICE_IN_AMBIENT |
524 AUDIO_DEVICE_IN_BUILTIN_MIC |
525 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
526 AUDIO_DEVICE_IN_WIRED_HEADSET |
527 AUDIO_DEVICE_IN_AUX_DIGITAL |
528 AUDIO_DEVICE_IN_VOICE_CALL |
529 AUDIO_DEVICE_IN_BACK_MIC |
530 AUDIO_DEVICE_IN_REMOTE_SUBMIX |
531 AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
532 AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET |
533 AUDIO_DEVICE_IN_USB_ACCESSORY |
534 AUDIO_DEVICE_IN_USB_DEVICE |
535#ifdef QCOM_ANC_HEADSET_ENABLED
536 AUDIO_DEVICE_IN_ANC_HEADSET |
537#endif
Mike Grissom20204112013-08-06 16:38:39 -0700538#if defined(QCOM_FM_ENABLED) || defined(STE_FM)
539 AUDIO_DEVICE_IN_FM_RX |
540 AUDIO_DEVICE_IN_FM_RX_A2DP |
541#endif
542 AUDIO_DEVICE_IN_DEFAULT);
543}
544
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000545static int adev_init_check(const struct audio_hw_device *dev)
546{
547 const struct qcom_audio_device *qadev = to_cladev(dev);
548
549 return qadev->hwif->initCheck();
550}
551
552static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
553{
554 struct qcom_audio_device *qadev = to_ladev(dev);
555 return qadev->hwif->setVoiceVolume(volume);
556}
557
558static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
559{
560 struct qcom_audio_device *qadev = to_ladev(dev);
561 return qadev->hwif->setMasterVolume(volume);
562}
563
564static int adev_get_master_volume(struct audio_hw_device *dev, float *volume) {
565
566 struct qcom_audio_device *qadev = to_ladev(dev);
567 return qadev->hwif->getMasterVolume(volume);
568}
569
570#ifdef QCOM_FM_ENABLED
571static int adev_set_fm_volume(struct audio_hw_device *dev, float volume)
572{
573 struct qcom_audio_device *qadev = to_ladev(dev);
574 return qadev->hwif->setFmVolume(volume);
575}
576#endif
577
578static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
579{
580 struct qcom_audio_device *qadev = to_ladev(dev);
Arne Coucheron73554f02013-03-28 13:01:31 +0100581 return qadev->hwif->setMode((int)mode);
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000582}
583
584static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
585{
586 struct qcom_audio_device *qadev = to_ladev(dev);
587 return qadev->hwif->setMicMute(state);
588}
589
590static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
591{
592 const struct qcom_audio_device *qadev = to_cladev(dev);
593 return qadev->hwif->getMicMute(state);
594}
595
596static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
597{
598 struct qcom_audio_device *qadev = to_ladev(dev);
599 return qadev->hwif->setParameters(String8(kvpairs));
600}
601
602static char * adev_get_parameters(const struct audio_hw_device *dev,
603 const char *keys)
604{
605 const struct qcom_audio_device *qadev = to_cladev(dev);
606 String8 s8;
607
608 s8 = qadev->hwif->getParameters(String8(keys));
609 return strdup(s8.string());
610}
611
612static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
613 const struct audio_config *config)
614{
615 const struct qcom_audio_device *qadev = to_cladev(dev);
Arne Coucheron73554f02013-03-28 13:01:31 +0100616 uint8_t channelCount = popcount(config->channel_mask);
617 return qadev->hwif->getInputBufferSize(config->sample_rate,config->format,channelCount);
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000618}
619
620
621static int adev_open_output_stream(struct audio_hw_device *dev,
622 audio_io_handle_t handle,
623 audio_devices_t devices,
624 audio_output_flags_t flags,
625 struct audio_config *config,
626 struct audio_stream_out **stream_out)
627{
628 struct qcom_audio_device *qadev = to_ladev(dev);
629 status_t status;
630 struct qcom_stream_out *out;
631 int ret;
632
633 out = (struct qcom_stream_out *)calloc(1, sizeof(*out));
634 if (!out)
635 return -ENOMEM;
636
Arne Coucheron73554f02013-03-28 13:01:31 +0100637 devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000638 status = static_cast<audio_output_flags_t> (flags);
639
Arne Coucheron73554f02013-03-28 13:01:31 +0100640 out->qcom_out = qadev->hwif->openOutputStream(devices, (int *) &config->format,
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000641 &config->channel_mask,
642 &config->sample_rate,
643 &status);
644 if (!out->qcom_out) {
645 ret = status;
646 goto err_open;
647 }
648
649 out->stream.common.get_sample_rate = out_get_sample_rate;
650 out->stream.common.set_sample_rate = out_set_sample_rate;
651 out->stream.common.get_buffer_size = out_get_buffer_size;
652 out->stream.common.get_channels = out_get_channels;
653 out->stream.common.get_format = out_get_format;
654 out->stream.common.set_format = out_set_format;
655 out->stream.common.standby = out_standby;
656 out->stream.common.dump = out_dump;
657 out->stream.common.set_parameters = out_set_parameters;
658 out->stream.common.get_parameters = out_get_parameters;
659 out->stream.common.add_audio_effect = out_add_audio_effect;
660 out->stream.common.remove_audio_effect = out_remove_audio_effect;
661 out->stream.get_latency = out_get_latency;
662 out->stream.set_volume = out_set_volume;
663 out->stream.write = out_write;
664 out->stream.get_render_position = out_get_render_position;
665 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
666 out->stream.start = out_start;
667 out->stream.pause = out_pause;
668 out->stream.flush = out_flush;
669 out->stream.stop = out_stop;
670 out->stream.set_observer = out_set_observer;
671 out->stream.get_buffer_info = out_get_buffer_info;
672 out->stream.is_buffer_available = out_is_buffer_available;
673
674 *stream_out = &out->stream;
675 return 0;
676
677err_open:
678 free(out);
679 *stream_out = NULL;
680 return ret;
681}
682
683static void adev_close_output_stream(struct audio_hw_device *dev,
684 struct audio_stream_out* stream)
685{
686 struct qcom_audio_device *qadev = to_ladev(dev);
687 struct qcom_stream_out *out = reinterpret_cast<struct qcom_stream_out *>(stream);
688
689 qadev->hwif->closeOutputStream(out->qcom_out);
690 free(out);
691}
692
693/** This method creates and opens the audio hardware input stream */
694static int adev_open_input_stream(struct audio_hw_device *dev,
695 audio_io_handle_t handle,
696 audio_devices_t devices,
Arne Coucheron73554f02013-03-28 13:01:31 +0100697 struct audio_config *config,
698 struct audio_stream_in **stream_in)
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000699{
700 struct qcom_audio_device *qadev = to_ladev(dev);
701 status_t status;
702 struct qcom_stream_in *in;
703 int ret;
704
705 in = (struct qcom_stream_in *)calloc(1, sizeof(*in));
706 if (!in)
707 return -ENOMEM;
708
709 devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
710
711 in->qcom_in = qadev->hwif->openInputStream(devices, (int *)&config->format,
712 &config->channel_mask,
713 &config->sample_rate,
714 &status,
715 (AudioSystem::audio_in_acoustics)0);
716 if (!in->qcom_in) {
717 ret = status;
718 goto err_open;
719 }
720
721 in->stream.common.get_sample_rate = in_get_sample_rate;
722 in->stream.common.set_sample_rate = in_set_sample_rate;
723 in->stream.common.get_buffer_size = in_get_buffer_size;
724 in->stream.common.get_channels = in_get_channels;
725 in->stream.common.get_format = in_get_format;
726 in->stream.common.set_format = in_set_format;
727 in->stream.common.standby = in_standby;
728 in->stream.common.dump = in_dump;
729 in->stream.common.set_parameters = in_set_parameters;
730 in->stream.common.get_parameters = in_get_parameters;
731 in->stream.common.add_audio_effect = in_add_audio_effect;
732 in->stream.common.remove_audio_effect = in_remove_audio_effect;
733 in->stream.set_gain = in_set_gain;
734 in->stream.read = in_read;
735 in->stream.get_input_frames_lost = in_get_input_frames_lost;
736
737 *stream_in = &in->stream;
738 return 0;
739
740err_open:
741 free(in);
742 *stream_in = NULL;
743 return ret;
744}
745
746static void adev_close_input_stream(struct audio_hw_device *dev,
747 struct audio_stream_in *stream)
748{
749 struct qcom_audio_device *qadev = to_ladev(dev);
750 struct qcom_stream_in *in =
751 reinterpret_cast<struct qcom_stream_in *>(stream);
752
753 qadev->hwif->closeInputStream(in->qcom_in);
754 free(in);
755}
756
757static int adev_dump(const struct audio_hw_device *dev, int fd)
758{
759 const struct qcom_audio_device *qadev = to_cladev(dev);
760 Vector<String16> args;
761
762 return qadev->hwif->dumpState(fd, args);
763}
764
765static int qcom_adev_close(hw_device_t* device)
766{
767 struct audio_hw_device *hwdev =
768 reinterpret_cast<struct audio_hw_device *>(device);
769 struct qcom_audio_device *qadev = to_ladev(hwdev);
770
771 if (!qadev)
772 return 0;
773
774 if (qadev->hwif)
775 delete qadev->hwif;
776
777 free(qadev);
778 return 0;
779}
780
781static int qcom_adev_open(const hw_module_t* module, const char* name,
782 hw_device_t** device)
783{
784 struct qcom_audio_device *qadev;
785 int ret;
786
787 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
788 return -EINVAL;
789
790 qadev = (struct qcom_audio_device *)calloc(1, sizeof(*qadev));
791 if (!qadev)
792 return -ENOMEM;
793
794 qadev->device.common.tag = HARDWARE_DEVICE_TAG;
795 qadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
796 qadev->device.common.module = const_cast<hw_module_t*>(module);
797 qadev->device.common.close = qcom_adev_close;
798
Mike Grissom20204112013-08-06 16:38:39 -0700799 qadev->device.get_supported_devices = adev_get_supported_devices;
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000800 qadev->device.init_check = adev_init_check;
801 qadev->device.set_voice_volume = adev_set_voice_volume;
802 qadev->device.set_master_volume = adev_set_master_volume;
803 qadev->device.get_master_volume = adev_get_master_volume;
804#ifdef QCOM_FM_ENABLED
805 qadev->device.set_fm_volume = adev_set_fm_volume;
806#endif
807 qadev->device.set_mode = adev_set_mode;
808 qadev->device.set_mic_mute = adev_set_mic_mute;
809 qadev->device.get_mic_mute = adev_get_mic_mute;
810 qadev->device.set_parameters = adev_set_parameters;
811 qadev->device.get_parameters = adev_get_parameters;
812 qadev->device.get_input_buffer_size = adev_get_input_buffer_size;
813 qadev->device.open_output_stream = adev_open_output_stream;
814 qadev->device.close_output_stream = adev_close_output_stream;
815 qadev->device.open_input_stream = adev_open_input_stream;
816 qadev->device.close_input_stream = adev_close_input_stream;
817 qadev->device.dump = adev_dump;
818
819 qadev->hwif = createAudioHardware();
820 if (!qadev->hwif) {
821 ret = -EIO;
822 goto err_create_audio_hw;
823 }
824
825 *device = &qadev->device.common;
826
827 return 0;
828
829err_create_audio_hw:
830 free(qadev);
831 return ret;
832}
833
834static struct hw_module_methods_t qcom_audio_module_methods = {
835 open: qcom_adev_open
836};
837
838struct qcom_audio_module HAL_MODULE_INFO_SYM = {
839 module: {
840 common: {
841 tag: HARDWARE_MODULE_TAG,
Arne Coucheron73554f02013-03-28 13:01:31 +0100842 module_api_version: AUDIO_DEVICE_API_VERSION_1_0,
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000843 hal_api_version: HARDWARE_HAL_API_VERSION,
844 id: AUDIO_HARDWARE_MODULE_ID,
845 name: "QCOM Audio HW HAL",
846 author: "Code Aurora Forum",
847 methods: &qcom_audio_module_methods,
848 dso : NULL,
849 reserved : {0},
850 },
851 },
852};
853
854}; // extern "C"
855
856}; // namespace android_audio_legacy