summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMisael Lopez Cruz2014-06-03 13:08:09 -0500
committerGerrit Code Review2014-06-03 18:17:24 -0500
commit8bbadc3eca1667ff59e7981cae9573fbd51c62a4 (patch)
tree34e847edc424c6cacfb5c9947af83493d189dc2c
parent3da8567243ec8a5d46581f9e5642a1a105471a6c (diff)
downloaddevice-ti-jacinto6evm-8bbadc3eca1667ff59e7981cae9573fbd51c62a4.tar.gz
device-ti-jacinto6evm-8bbadc3eca1667ff59e7981cae9573fbd51c62a4.tar.xz
device-ti-jacinto6evm-8bbadc3eca1667ff59e7981cae9573fbd51c62a4.zip
audio: Legacy: BT SCO voice call support
The Bluetooth SCO voice call has the following data flow: Uplink: +----------- SRC -----------+ | | McASP7 McASP3 | | Bluetooth Mic Downlink: +----------- SRC -----------+ | | McASP7 McASP3 | | Bluetooth Speaker The voice call uses the ALSA PCM devices that are normally used by the primary output and input. The primary output is switched to a null/dummy sink when the voice call starts, and switched back to the ALSA devices when the call ends. The null/dummy sink consumes the data at the same rate than an actual PCM device does, but does not render anything to an output device (e.g. speaker). Change-Id: I63a41de96c4ed34b60aab9240d10ad83c06c69ac Signed-off-by: Misael Lopez Cruz <misael.lopez@ti.com>
-rw-r--r--audio/legacy/audio_hw.c531
-rw-r--r--audio/mixer_paths.xml7
2 files changed, 514 insertions, 24 deletions
diff --git a/audio/legacy/audio_hw.c b/audio/legacy/audio_hw.c
index d25fedf..e54ee45 100644
--- a/audio/legacy/audio_hw.c
+++ b/audio/legacy/audio_hw.c
@@ -44,6 +44,12 @@
44/* yet another definition of ARRAY_SIZE macro) */ 44/* yet another definition of ARRAY_SIZE macro) */
45#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) 45#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
46 46
47/*
48 * additional space in resampler buffer allowing for extra samples to be returned
49 * by speex resampler when sample rates ratio is not an integer
50 */
51#define RESAMPLER_HEADROOM_FRAMES 10
52
47/* buffer_remix: functor for doing in-place buffer manipulations. 53/* buffer_remix: functor for doing in-place buffer manipulations.
48 * 54 *
49 * NB. When remix_func is called, the memory at `buf` must be at least 55 * NB. When remix_func is called, the memory at `buf` must be at least
@@ -56,10 +62,34 @@ struct buffer_remix {
56 size_t out_chans; /* number of output channels */ 62 size_t out_chans; /* number of output channels */
57}; 63};
58 64
65struct j6_voice_stream {
66 struct j6_audio_device *dev;
67 struct pcm *pcm_in;
68 struct pcm *pcm_out;
69 struct pcm_config in_config;
70 struct pcm_config out_config;
71 struct resampler_itfe *resampler;
72 struct resampler_buffer_provider buf_provider;
73 struct buffer_remix *remix;
74 pthread_t thread;
75 int16_t *in_buffer;
76 int16_t *out_buffer;
77 size_t in_frames;
78 size_t out_frames;
79 size_t frame_size;
80 char *name;
81};
82
83struct j6_voice {
84 struct j6_voice_stream ul;
85 struct j6_voice_stream dl;
86};
87
59struct j6_audio_device { 88struct j6_audio_device {
60 struct audio_hw_device device; 89 struct audio_hw_device device;
61 struct j6_stream_in *in; 90 struct j6_stream_in *in;
62 struct j6_stream_out *out; 91 struct j6_stream_out *out;
92 struct j6_voice voice;
63 struct audio_route *route; 93 struct audio_route *route;
64 audio_devices_t in_device; 94 audio_devices_t in_device;
65 audio_devices_t out_device; 95 audio_devices_t out_device;
@@ -67,7 +97,10 @@ struct j6_audio_device {
67 unsigned int card; 97 unsigned int card;
68 unsigned int in_port; 98 unsigned int in_port;
69 unsigned int out_port; 99 unsigned int out_port;
100 unsigned int bt_port;
70 bool mic_mute; 101 bool mic_mute;
102 bool in_call;
103 audio_mode_t mode;
71}; 104};
72 105
73struct j6_stream_in { 106struct j6_stream_in {
@@ -93,6 +126,7 @@ struct j6_stream_out {
93 struct j6_audio_device *dev; 126 struct j6_audio_device *dev;
94 struct pcm_config config; 127 struct pcm_config config;
95 struct pcm *pcm; 128 struct pcm *pcm;
129 struct timespec last;
96 pthread_mutex_t lock; 130 pthread_mutex_t lock;
97 bool standby; 131 bool standby;
98 int64_t written; /* total frames written, not cleared when entering standby */ 132 int64_t written; /* total frames written, not cleared when entering standby */
@@ -113,8 +147,8 @@ static const char *supported_cards[] = {
113 AUDIO_DEVICE_OUT_DEFAULT) 147 AUDIO_DEVICE_OUT_DEFAULT)
114 148
115#define CAPTURE_SAMPLE_RATE 44100 149#define CAPTURE_SAMPLE_RATE 44100
116#define CAPTURE_PERIOD_SIZE 320 150#define CAPTURE_PERIOD_SIZE 960
117#define CAPTURE_PERIOD_COUNT 2 151#define CAPTURE_PERIOD_COUNT 4
118#define CAPTURE_BUFFER_SIZE (CAPTURE_PERIOD_SIZE * CAPTURE_PERIOD_COUNT) 152#define CAPTURE_BUFFER_SIZE (CAPTURE_PERIOD_SIZE * CAPTURE_PERIOD_COUNT)
119 153
120#define PLAYBACK_SAMPLE_RATE 44100 154#define PLAYBACK_SAMPLE_RATE 44100
@@ -122,6 +156,11 @@ static const char *supported_cards[] = {
122#define PLAYBACK_PERIOD_COUNT 4 156#define PLAYBACK_PERIOD_COUNT 4
123#define PLAYBACK_BUFFER_SIZE (PLAYBACK_PERIOD_SIZE * PLAYBACK_PERIOD_COUNT) 157#define PLAYBACK_BUFFER_SIZE (PLAYBACK_PERIOD_SIZE * PLAYBACK_PERIOD_COUNT)
124 158
159#define BT_SAMPLE_RATE 8000
160#define BT_PERIOD_SIZE 160
161#define BT_PERIOD_COUNT 4
162#define BT_BUFFER_SIZE (BT_PERIOD_SIZE * BT_PERIOD_COUNT)
163
125struct pcm_config pcm_config_capture = { 164struct pcm_config pcm_config_capture = {
126 .channels = 2, 165 .channels = 2,
127 .rate = CAPTURE_SAMPLE_RATE, 166 .rate = CAPTURE_SAMPLE_RATE,
@@ -143,6 +182,27 @@ struct pcm_config pcm_config_playback = {
143 .avail_min = PLAYBACK_PERIOD_SIZE, 182 .avail_min = PLAYBACK_PERIOD_SIZE,
144}; 183};
145 184
185struct pcm_config pcm_config_bt_in = {
186 .channels = 2,
187 .rate = BT_SAMPLE_RATE,
188 .format = PCM_FORMAT_S16_LE,
189 .period_size = BT_PERIOD_SIZE,
190 .period_count = BT_PERIOD_COUNT,
191 .start_threshold = 1,
192 .stop_threshold = BT_BUFFER_SIZE,
193};
194
195struct pcm_config pcm_config_bt_out = {
196 .channels = 2,
197 .rate = BT_SAMPLE_RATE,
198 .format = PCM_FORMAT_S16_LE,
199 .period_size = BT_PERIOD_SIZE,
200 .period_count = BT_PERIOD_COUNT,
201 .start_threshold = BT_BUFFER_SIZE / 2,
202 .stop_threshold = BT_BUFFER_SIZE,
203 .avail_min = BT_PERIOD_SIZE,
204};
205
146static int find_supported_card(void) 206static int find_supported_card(void)
147{ 207{
148 char name[256] = ""; 208 char name[256] = "";
@@ -174,6 +234,8 @@ static int find_supported_card(void)
174 return card; 234 return card;
175} 235}
176 236
237static void do_out_standby(struct j6_stream_out *out);
238
177/* must be called with device lock held */ 239/* must be called with device lock held */
178static void select_input_device(struct j6_audio_device *adev) 240static void select_input_device(struct j6_audio_device *adev)
179{ 241{
@@ -259,6 +321,362 @@ static int setup_stereo_to_mono_input_remix(struct j6_stream_in *in)
259 return 0; 321 return 0;
260} 322}
261 323
324/*
325 * Implementation of buffer_remix::remix_func that duplicates the first
326 * channel into the rest of channels in the frame without doing any other
327 * processing. It assumes data in 16-bits, but it's not explicitly checked
328 */
329static void mono_remix(struct buffer_remix *data, void *buf, size_t frames)
330{
331 int16_t *buffer = (int16_t*)buf;
332 size_t i;
333
334 ALOGVV("mono_remix() remix=%p buf=%p frames=%u", data, buf, frames);
335
336 if (frames == 0)
337 return;
338
339 /* duplicate first channel into the rest of channels in the frame */
340 while (frames--) {
341 for (i = 1; i < data->out_chans; i++)
342 buffer[i] = buffer[0];
343 buffer += data->out_chans;
344 }
345}
346
347static int setup_mono_input_remix(struct j6_voice_stream *stream)
348{
349 ALOGV("setup_mono_input_remix() %s stream", stream->name);
350
351 struct buffer_remix *br = (struct buffer_remix *)malloc(sizeof(struct buffer_remix));
352 if (!br)
353 return -ENOMEM;
354
355 br->remix_func = mono_remix;
356 br->sample_size = sizeof(int16_t);
357 br->in_chans = stream->in_config.channels;
358 br->out_chans = stream->out_config.channels;
359 stream->remix = br;
360
361 return 0;
362}
363
364static int voice_get_next_buffer(struct resampler_buffer_provider *buffer_provider,
365 struct resampler_buffer* buffer)
366{
367 struct j6_voice_stream *stream;
368 int ret;
369
370 if (buffer_provider == NULL || buffer == NULL) {
371 ALOGE("voice_get_next_buffer() invalid buffer/provider");
372 return -EINVAL;
373 }
374
375 stream = (struct j6_voice_stream *)((char *)buffer_provider -
376 offsetof(struct j6_voice_stream, buf_provider));
377
378 if (stream->pcm_in == NULL) {
379 buffer->raw = NULL;
380 buffer->frame_count = 0;
381 return -ENODEV;
382 }
383
384 if (buffer->frame_count > stream->in_frames) {
385 ALOGW("voice_get_next_buffer() %s unexpected frame count %u, "
386 "buffer was allocated for %u frames",
387 stream->name, buffer->frame_count, stream->in_frames);
388 buffer->frame_count = stream->in_frames;
389 }
390
391 ret = pcm_read(stream->pcm_in, stream->in_buffer,
392 buffer->frame_count * stream->frame_size);
393 if (ret) {
394 ALOGE("voice_get_next_buffer() failed to read %s: %s",
395 stream->name, pcm_get_error(stream->pcm_in));
396 buffer->raw = NULL;
397 buffer->frame_count = 0;
398 return ret;
399 }
400
401 buffer->i16 = stream->in_buffer;
402
403 return ret;
404}
405
406static void voice_release_buffer(struct resampler_buffer_provider *buffer_provider,
407 struct resampler_buffer* buffer)
408{
409}
410
411static void *voice_thread_func(void *arg)
412{
413 struct j6_voice_stream *stream = (struct j6_voice_stream *)arg;
414 struct j6_audio_device *adev = stream->dev;
415 struct timespec now;
416 size_t frames = stream->out_frames;
417 uint32_t periods = 0;
418 uint32_t avail;
419 bool in_steady = false;
420 bool out_steady = false;
421 int ret = 0;
422
423 pcm_start(stream->pcm_in);
424
425 memset(stream->out_buffer, 0, stream->out_frames * stream->frame_size);
426
427 while (adev->in_call) {
428 if (out_steady) {
429 if (in_steady) {
430 stream->resampler->resample_from_provider(stream->resampler,
431 stream->out_buffer,
432 &frames);
433 } else {
434 ret = pcm_get_htimestamp(stream->pcm_in, &avail, &now);
435 if (!ret && (avail > 0)) {
436 in_steady = true;
437 continue;
438 }
439 }
440 } else if (++periods == stream->out_config.period_count) {
441 out_steady = true;
442 }
443
444 if (stream->remix)
445 stream->remix->remix_func(stream->remix, stream->out_buffer, frames);
446
447 ret = pcm_write(stream->pcm_out, stream->out_buffer,
448 frames * stream->frame_size);
449 if (ret) {
450 ALOGE("voice_thread_func() failed to write %s: %s",
451 stream->name, pcm_get_error(stream->pcm_out));
452 usleep((frames * 1000000) / stream->out_config.rate);
453 }
454 }
455
456 return (void*)ret;
457}
458
459static void voice_stream_exit(struct j6_voice_stream *stream)
460{
461 if (stream->resampler) {
462 release_resampler(stream->resampler);
463 stream->resampler = NULL;
464 }
465
466 if (stream->pcm_out) {
467 pcm_close(stream->pcm_out);
468 stream->pcm_out = NULL;
469 }
470
471 if (stream->pcm_in) {
472 pcm_close(stream->pcm_in);
473 stream->pcm_in = NULL;
474 }
475
476 if (stream->in_buffer) {
477 free(stream->in_buffer);
478 stream->in_buffer = NULL;
479 stream->in_frames = 0;
480 }
481
482 if (stream->out_buffer) {
483 free(stream->out_buffer);
484 stream->out_buffer = NULL;
485 stream->out_frames = 0;
486 }
487
488 if (stream->remix) {
489 free(stream->remix);
490 stream->remix = NULL;
491 }
492
493 if (stream->name) {
494 free(stream->name);
495 stream->name = NULL;
496 }
497}
498
499static int voice_stream_init(struct j6_voice_stream *stream,
500 unsigned int in_port,
501 unsigned int out_port,
502 bool needs_mono_remix)
503{
504 struct j6_audio_device *adev = stream->dev;
505 int ret;
506
507 stream->buf_provider.get_next_buffer = voice_get_next_buffer;
508 stream->buf_provider.release_buffer = voice_release_buffer;
509 ret = create_resampler(stream->in_config.rate,
510 stream->out_config.rate,
511 2,
512 RESAMPLER_QUALITY_DEFAULT,
513 &stream->buf_provider,
514 &stream->resampler);
515 if (ret) {
516 ALOGE("voice_stream_init() failed to create %s resampler %d", stream->name, ret);
517 return ret;
518 }
519
520 stream->pcm_in = pcm_open(adev->card, in_port, PCM_IN, &stream->in_config);
521 stream->pcm_out = pcm_open(adev->card, out_port, PCM_OUT, &stream->out_config);
522
523 if (!pcm_is_ready(stream->pcm_in) || !pcm_is_ready(stream->pcm_out)) {
524 ALOGE("voice_stream_init() failed to open pcm %s devices", stream->name);
525 voice_stream_exit(stream);
526 return -ENODEV;
527 }
528
529 stream->frame_size = pcm_frames_to_bytes(stream->pcm_in, 1);
530
531 /* out_buffer will store the resampled data */
532 stream->out_frames = stream->out_config.period_size;
533 stream->out_buffer = malloc(stream->out_frames * stream->frame_size);
534
535 /* in_buffer will store the frames recorded from the PCM device */
536 stream->in_frames = (stream->out_frames * stream->in_config.rate) / stream->out_config.rate +
537 RESAMPLER_HEADROOM_FRAMES;
538 stream->in_buffer = malloc(stream->in_frames * stream->frame_size);
539
540 if (!stream->in_buffer || !stream->out_buffer) {
541 ALOGE("voice_stream_init() failed to allocate %s buffers", stream->name);
542 voice_stream_exit(stream);
543 return -ENOMEM;
544 }
545
546 if (needs_mono_remix) {
547 ret = setup_mono_input_remix(stream);
548 if (ret) {
549 ALOGE("voice_stream_init() failed to setup mono remix %d", ret);
550 voice_stream_exit(stream);
551 return ret;
552 }
553 } else {
554 stream->remix = NULL;
555 }
556
557 return 0;
558}
559
560static int enter_voice_call(struct j6_audio_device *adev)
561{
562 struct j6_voice *voice = &adev->voice;
563 int ret;
564
565 ALOGI("enter_voice_call() entering bluetooth voice call");
566
567 audio_route_apply_path(adev->route, "BT SCO Master");
568 audio_route_update_mixer(adev->route);
569
570 /* Let the primary output switch to a dummy sink */
571 if (adev->out)
572 do_out_standby(adev->out);
573
574 /* Uplink: Mic (44.1kHz) -> BT (8kHz) */
575 voice->ul.name = strdup("UL");
576 voice->ul.in_config = pcm_config_capture;
577 voice->ul.out_config = pcm_config_bt_out;
578 voice->ul.dev = adev;
579 ret = voice_stream_init(&voice->ul, adev->in_port, adev->bt_port, false);
580 if (ret) {
581 ALOGE("enter_voice_call() failed to init uplink %d", ret);
582 goto err_ul_init;
583 }
584
585 /* Downlink: BT (8kHz) -> HP/Spk (44.1kHz) */
586 voice->dl.name = strdup("DL");
587 voice->dl.in_config = pcm_config_bt_in;
588 voice->dl.out_config = pcm_config_playback;
589 voice->dl.dev = adev;
590 ret = voice_stream_init(&voice->dl, adev->bt_port, adev->out_port, true);
591 if (ret) {
592 ALOGE("enter_voice_call() failed to init downlink %d", ret);
593 goto err_dl_init;
594 }
595
596 adev->in_call = true;
597
598 /* Create uplink thread: Mic -> BT */
599 ret = pthread_create(&voice->ul.thread, NULL, voice_thread_func, &voice->ul);
600 if (ret) {
601 ALOGE("enter_voice_call() failed to create uplink thread %d", ret);
602 adev->in_call = false;
603 goto err_ul_thread;
604 }
605
606 /* Create downlink thread: BT -> HP/Spk */
607 ret = pthread_create(&voice->dl.thread, NULL, voice_thread_func, &voice->dl);
608 if (ret) {
609 ALOGE("enter_voice_call() failed to create downlink thread %d", ret);
610 adev->in_call = false;
611 goto err_dl_thread;
612 }
613
614 return 0;
615
616 err_dl_thread:
617 pthread_join(voice->ul.thread, NULL);
618 err_ul_thread:
619 voice_stream_exit(&voice->ul);
620 err_dl_init:
621 voice_stream_exit(&voice->dl);
622 err_ul_init:
623 audio_route_reset_path(adev->route, "BT SCO Master");
624 audio_route_update_mixer(adev->route);
625
626 return ret;
627}
628
629static void leave_voice_call(struct j6_audio_device *adev)
630{
631 struct j6_voice *voice = &adev->voice;
632 struct j6_voice_stream *ul = &voice->ul;
633 struct j6_voice_stream *dl = &voice->dl;
634 void *ret;
635
636 ALOGI("leave_voice_call() leaving bluetooth voice call");
637
638 adev->in_call = false;
639
640 /*
641 * The PCM ports used for Bluetooth are slaves and they can lose the
642 * BCLK and FSYNC while still active. That leads to blocking read() and
643 * write() calls, which is prevented by switching the clock source to
644 * an internal one and explicitly stopping both ports for the new source
645 * to take effect at kernel level
646 */
647 audio_route_reset_path(adev->route, "BT SCO Master");
648 audio_route_update_mixer(adev->route);
649 if (ul->pcm_out)
650 pcm_stop(ul->pcm_out);
651 if (dl->pcm_in)
652 pcm_stop(dl->pcm_in);
653
654 pthread_join(voice->dl.thread, &ret);
655 pthread_join(voice->ul.thread, &ret);
656
657 voice_stream_exit(&voice->dl);
658 voice_stream_exit(&voice->ul);
659
660 /* Let the primary output switch back to its ALSA PCM device */
661 if (adev->out)
662 do_out_standby(adev->out);
663}
664
665static uint32_t time_diff(struct timespec t1, struct timespec t0)
666{
667 struct timespec temp;
668
669 if ((t1.tv_nsec - t0.tv_nsec) < 0) {
670 temp.tv_sec = t1.tv_sec - t0.tv_sec-1;
671 temp.tv_nsec = 1000000000UL + t1.tv_nsec - t0.tv_nsec;
672 } else {
673 temp.tv_sec = t1.tv_sec - t0.tv_sec;
674 temp.tv_nsec = t1.tv_nsec - t0.tv_nsec;
675 }
676
677 return (temp.tv_sec * 1000000UL + temp.tv_nsec / 1000);
678}
679
262/* audio HAL functions */ 680/* audio HAL functions */
263 681
264static uint32_t out_get_sample_rate(const struct audio_stream *stream) 682static uint32_t out_get_sample_rate(const struct audio_stream *stream)
@@ -324,9 +742,13 @@ static void do_out_standby(struct j6_stream_out *out)
324 struct j6_audio_device *adev = out->dev; 742 struct j6_audio_device *adev = out->dev;
325 743
326 if (!out->standby) { 744 if (!out->standby) {
327 ALOGI("do_out_standby() close card %u port %u", adev->card, adev->out_port); 745 if (adev->mode != AUDIO_MODE_IN_CALL) {
328 pcm_close(out->pcm); 746 ALOGI("do_out_standby() close card %u port %u", adev->card, adev->out_port);
329 out->pcm = NULL; 747 pcm_close(out->pcm);
748 out->pcm = NULL;
749 } else {
750 ALOGI("do_out_standby() close dummy card");
751 }
330 out->standby = true; 752 out->standby = true;
331 } 753 }
332} 754}
@@ -411,10 +833,13 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
411{ 833{
412 struct j6_stream_out *out = (struct j6_stream_out *)(stream); 834 struct j6_stream_out *out = (struct j6_stream_out *)(stream);
413 struct j6_audio_device *adev = out->dev; 835 struct j6_audio_device *adev = out->dev;
836 struct timespec now;
414 const size_t frame_size = audio_stream_frame_size(&stream->common); 837 const size_t frame_size = audio_stream_frame_size(&stream->common);
415 const size_t frames = bytes / frame_size; 838 const size_t frames = bytes / frame_size;
416 uint32_t rate = out->config.rate; 839 uint32_t rate = out->config.rate;
417 uint32_t write_usecs = frames * 1000000 / rate; 840 uint32_t write_usecs = frames * 1000000 / rate;
841 uint32_t diff_usecs;
842 int ret = 0;
418 843
419 ALOGVV("out_write() stream=%p buffer=%p size=%u/%u time=%u usecs", 844 ALOGVV("out_write() stream=%p buffer=%p size=%u/%u time=%u usecs",
420 out, buffer, frames, rate, write_usecs); 845 out, buffer, frames, rate, write_usecs);
@@ -423,18 +848,27 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
423 pthread_mutex_lock(&out->lock); 848 pthread_mutex_lock(&out->lock);
424 849
425 if (out->standby) { 850 if (out->standby) {
426 select_output_device(adev); 851 if (!adev->in_call) {
852 select_output_device(adev);
427 853
428 ALOGI("out_write() open card %u port %u", adev->card, adev->out_port); 854 ALOGI("out_write() open card %u port %u", adev->card, adev->out_port);
429 out->pcm = pcm_open(adev->card, adev->out_port, PCM_OUT | PCM_MMAP, &out->config); 855 out->pcm = pcm_open(adev->card, adev->out_port, PCM_OUT, &out->config);
430 if (!pcm_is_ready(out->pcm)) { 856 if (!pcm_is_ready(out->pcm)) {
431 ALOGE("out_write() failed to open pcm out: %s", pcm_get_error(out->pcm)); 857 ALOGE("out_write() failed to open pcm out: %s", pcm_get_error(out->pcm));
432 pcm_close(out->pcm); 858 pcm_close(out->pcm);
433 out->pcm = NULL; 859 out->pcm = NULL;
860 ret = -ENODEV;
861 }
862 } else {
863 ALOGI("out_write() open dummy port");
864 clock_gettime(CLOCK_REALTIME, &out->last);
865 }
866
867 if (ret) {
434 usleep(write_usecs); /* limits the rate of error messages */ 868 usleep(write_usecs); /* limits the rate of error messages */
435 pthread_mutex_unlock(&out->lock); 869 pthread_mutex_unlock(&out->lock);
436 pthread_mutex_unlock(&adev->lock); 870 pthread_mutex_unlock(&adev->lock);
437 return -ENODEV; 871 return ret;
438 } 872 }
439 873
440 out->standby = false; 874 out->standby = false;
@@ -442,10 +876,19 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
442 876
443 pthread_mutex_unlock(&adev->lock); 877 pthread_mutex_unlock(&adev->lock);
444 878
445 int ret = pcm_mmap_write(out->pcm, buffer, bytes); 879 if (!adev->in_call) {
446 if (ret) { 880 ret = pcm_write(out->pcm, buffer, bytes);
447 ALOGE("out_write() failed to write audio data %d", ret); 881 if (ret) {
448 usleep(write_usecs); /* limits the rate of error messages */ 882 ALOGE("out_write() failed to write audio data %d", ret);
883 usleep(write_usecs); /* limits the rate of error messages */
884 }
885 } else {
886 clock_gettime(CLOCK_REALTIME, &now);
887 diff_usecs = time_diff(now, out->last);
888 if (write_usecs > diff_usecs)
889 usleep(write_usecs - diff_usecs);
890
891 clock_gettime(CLOCK_REALTIME, &out->last);
449 } 892 }
450 893
451 out->written += frames; 894 out->written += frames;
@@ -481,18 +924,27 @@ static int out_get_presentation_position(const struct audio_stream_out *stream,
481 uint64_t *frames, struct timespec *timestamp) 924 uint64_t *frames, struct timespec *timestamp)
482{ 925{
483 struct j6_stream_out *out = (struct j6_stream_out *)(stream); 926 struct j6_stream_out *out = (struct j6_stream_out *)(stream);
927 struct j6_audio_device *adev = out->dev;
928 int64_t signed_frames = -1;
484 size_t avail; 929 size_t avail;
485 int ret = -1; 930 int ret = -1;
486 931
487 pthread_mutex_lock(&out->lock); 932 pthread_mutex_lock(&out->lock);
488 933
489 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) { 934 if (!adev->in_call) {
490 int64_t signed_frames = out->written - pcm_get_buffer_size(out->pcm) + avail; 935 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
491 /* It would be unusual for this value to be negative, but check just in case ... */ 936 signed_frames = out->written - pcm_get_buffer_size(out->pcm) + avail;
492 if (signed_frames >= 0) {
493 *frames = signed_frames;
494 ret = 0;
495 } 937 }
938 } else {
939 clock_gettime(CLOCK_REALTIME, timestamp);
940 signed_frames = out->written +
941 (time_diff(*timestamp, out->last) * out->config.rate) / 1000000;
942 }
943
944 /* It would be unusual for this value to be negative, but check just in case ... */
945 if (signed_frames >= 0) {
946 *frames = signed_frames;
947 ret = 0;
496 } 948 }
497 949
498 pthread_mutex_unlock(&out->lock); 950 pthread_mutex_unlock(&out->lock);
@@ -921,9 +1373,37 @@ static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
921 1373
922static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) 1374static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
923{ 1375{
1376 struct j6_audio_device *adev = (struct j6_audio_device *)dev;
1377 struct j6_stream_out *out = adev->out;
1378 int ret = 0;
1379
924 ALOGV("adev_set_mode() mode=0x%08x", mode); 1380 ALOGV("adev_set_mode() mode=0x%08x", mode);
925 1381
926 return 0; 1382 pthread_mutex_lock(&adev->lock);
1383 pthread_mutex_lock(&out->lock);
1384
1385 if (adev->mode == mode) {
1386 ALOGV("adev_set_mode() already in mode=0x%08x", mode);
1387 goto out;
1388 }
1389
1390 if (mode == AUDIO_MODE_IN_CALL) {
1391 ret = enter_voice_call(adev);
1392 if (ret) {
1393 ALOGE("adev_set_mode() failed to initialize voice call %d", ret);
1394 goto out;
1395 }
1396 } else {
1397 leave_voice_call(adev);
1398 }
1399
1400 adev->mode = mode;
1401
1402out:
1403 pthread_mutex_unlock(&out->lock);
1404 pthread_mutex_unlock(&adev->lock);
1405
1406 return ret;
927} 1407}
928 1408
929static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) 1409static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
@@ -1156,7 +1636,10 @@ static int adev_open(const hw_module_t* module, const char* name,
1156 adev->card = find_supported_card(); 1636 adev->card = find_supported_card();
1157 adev->in_port = 0; 1637 adev->in_port = 0;
1158 adev->out_port = 0; 1638 adev->out_port = 0;
1639 adev->bt_port = 2;
1159 adev->mic_mute = false; 1640 adev->mic_mute = false;
1641 adev->in_call = false;
1642 adev->mode = AUDIO_MODE_NORMAL;
1160 1643
1161 adev->route = audio_route_init(adev->card, NULL); 1644 adev->route = audio_route_init(adev->card, NULL);
1162 if (!adev->route) { 1645 if (!adev->route) {
diff --git a/audio/mixer_paths.xml b/audio/mixer_paths.xml
index 06419be..09949fa 100644
--- a/audio/mixer_paths.xml
+++ b/audio/mixer_paths.xml
@@ -75,4 +75,11 @@
75<ctl name="J3C Line Playback Switch" value="1" /> 75<ctl name="J3C Line Playback Switch" value="1" />
76<ctl name="J3C PCM Playback Volume" value="127" /> 76<ctl name="J3C PCM Playback Volume" value="127" />
77 77
78<!-- Bluetooth -->
79<ctl name="Bluetooth Mode" value="Slave" />
80
81<path name="BT SCO Master">
82 <ctl name="Bluetooth Mode" value="Master" />
83</path>
84
78</mixer> 85</mixer>