diff options
author | PixelBot AutoMerger <android-nexus-securitybot@system.gserviceaccount.com> | 2023-09-24 18:56:31 -0700 |
---|---|---|
committer | Pindar Yang <pindaryang@google.com> | 2023-09-25 06:43:07 +0000 |
commit | cf1ea7b7acb7db1ef24aafde7edaba9b751ea98f (patch) | |
tree | 1743b409668b3f9bd40ce76fd786e13b4e96479d | |
parent | 88d2aee3ebaee9f71daa00165df87ab165630e9d (diff) | |
parent | c9dd2fed370952e9b995322dfb29a2f74f0e57f4 (diff) | |
download | aoc-cf1ea7b7acb7db1ef24aafde7edaba9b751ea98f.tar.gz |
Merge android13-gs-pixel-5.10-udc-qpr1 into android13-gs-pixel-5.10-24Q1android-u-qpr2-beta-1_r0.6android-u-qpr2-beta-1_r0.5android-u-qpr2-beta-1_r0.4android-u-qpr2-beta-1_r0.3android-u-qpr2-beta-1_r0.2android-u-qpr2-beta-1_r0.1
Bug: 300854197
SBMerger: 558810260
Change-Id: Ia0c91cabf4df69e46de4f00dda6b062ec38a5e40
Signed-off-by: SecurityBot <android-nexus-securitybot@system.gserviceaccount.com>
-rw-r--r-- | alsa/aoc_alsa.h | 8 | ||||
-rw-r--r-- | alsa/aoc_alsa_incall.c | 32 | ||||
-rw-r--r-- | alsa/aoc_alsa_pcm.c | 65 | ||||
-rw-r--r-- | alsa/aoc_alsa_voip.c | 17 |
4 files changed, 90 insertions, 32 deletions
diff --git a/alsa/aoc_alsa.h b/alsa/aoc_alsa.h index a9c30ab..9272bbb 100644 --- a/alsa/aoc_alsa.h +++ b/alsa/aoc_alsa.h @@ -196,7 +196,8 @@ enum aec_ref_source { BT_PLAYBACK, NUM_AEC_REF_SOURCE }; -enum { INCALL_CAPTURE_OFF = 0, INCALL_CAPTURE_UL, INCALL_CAPTURE_DL, INCALL_CAPTURE_UL_DL }; +enum { INCALL_CAPTURE_OFF = 0, INCALL_CAPTURE_UL, INCALL_CAPTURE_DL, INCALL_CAPTURE_UL_DL, + INCALL_CAPTURE_3MIC }; enum { NONBLOCKING = 0, BLOCKING = 1 }; enum { STOP = 0, START }; enum { PLAYBACK_MODE, VOICE_TX_MODE, VOICE_RX_MODE, HAPTICS_MODE, OFFLOAD_MODE }; @@ -300,11 +301,15 @@ struct aoc_alsa_stream { int params_rate; /* Sampling rate */ int pcm_format_width; /* Number of bits */ bool pcm_float_fmt; /* Floating point */ + bool reused_for_voip; struct vm_area_struct *vma; /* for MMAP */ unsigned int period_size; unsigned int buffer_size; unsigned int pos; + unsigned int prev_pos; + unsigned int pos_delta; + unsigned long prev_buffer_cnt; unsigned long hw_ptr_base; /* read/write pointers in ring buffer */ unsigned long prev_consumed; int n_overflow; @@ -326,6 +331,7 @@ void aoc_timer_restart(struct aoc_alsa_stream *alsa_stream); void aoc_timer_stop(struct aoc_alsa_stream *alsa_stream); void aoc_timer_stop_sync(struct aoc_alsa_stream *alsa_stream); void aoc_pcm_period_work_handler(struct work_struct *work); +bool aoc_pcm_update_pos(struct aoc_alsa_stream *alsa_stream, unsigned long consumed); int snd_aoc_new_ctl(struct aoc_chip *chip); int snd_aoc_new_pcm(struct aoc_chip *chip); diff --git a/alsa/aoc_alsa_incall.c b/alsa/aoc_alsa_incall.c index 56a1ac7..29e1bbd 100644 --- a/alsa/aoc_alsa_incall.c +++ b/alsa/aoc_alsa_incall.c @@ -77,14 +77,10 @@ static enum hrtimer_restart aoc_incall_hifi_irq_process(struct aoc_alsa_stream * } alsa_stream->prev_consumed = consumed; - /* Update the pcm pointer */ - if (unlikely(alsa_stream->n_overflow)) { - alsa_stream->pos = (consumed + 0x100000000 * alsa_stream->n_overflow - - alsa_stream->hw_ptr_base) % - alsa_stream->buffer_size; - } else { - alsa_stream->pos = (consumed - alsa_stream->hw_ptr_base) % alsa_stream->buffer_size; - } + if (!aoc_pcm_update_pos(alsa_stream, consumed)) + return HRTIMER_RESTART; + + alsa_stream->prev_pos = alsa_stream->pos; /* Do not queue a work if the cancel_work is active */ if (atomic_read(&alsa_stream->cancel_work_active) > 0 @@ -216,6 +212,7 @@ static int snd_aoc_pcm_open(struct snd_soc_component *component, aoc_ring_bytes_written(dev->service, AOC_UP); alsa_stream->prev_consumed = alsa_stream->hw_ptr_base; alsa_stream->n_overflow = 0; + alsa_stream->prev_buffer_cnt = 0; err = aoc_audio_open(alsa_stream); if (err != 0) { @@ -242,6 +239,10 @@ static int snd_aoc_pcm_open(struct snd_soc_component *component, /* TODO: refactor needed on mapping between device number and entrypoint */ alsa_stream->entry_point_idx = (idx == 7) ? HAPTICS : idx; + if (rtd->dai_link->id == IDX_INCALL_CAP0_TX && + chip->incall_capture_state[0] == INCALL_CAPTURE_3MIC) { + alsa_stream->reused_for_voip = true; + } mutex_unlock(&chip->audio_mutex); return 0; @@ -322,6 +323,12 @@ static int snd_aoc_pcm_close(struct snd_soc_component *component, */ chip->opened &= ~(1 << alsa_stream->idx); + if (alsa_stream->reused_for_voip) { + /* Userspace should only select one EP for VoIP capture and one EP for + * VoIP playback. + */ + teardown_voipcall(alsa_stream); + } mutex_unlock(&chip->audio_mutex); return 0; @@ -409,11 +416,14 @@ static int snd_aoc_pcm_prepare(struct snd_soc_component *component, alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream); alsa_stream->period_size = snd_pcm_lib_period_bytes(substream); alsa_stream->pos = 0; + alsa_stream->prev_pos = 0; + alsa_stream->pos_delta = 0; alsa_stream->hw_ptr_base = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? aoc_ring_bytes_read(dev->service, AOC_DOWN) : aoc_ring_bytes_written(dev->service, AOC_UP); alsa_stream->prev_consumed = alsa_stream->hw_ptr_base; alsa_stream->n_overflow = 0; + alsa_stream->prev_buffer_cnt = 0; dev_dbg(component->dev, "pcm prepare: hw_ptr_base = %lu\n", alsa_stream->hw_ptr_base); @@ -421,6 +431,12 @@ static int snd_aoc_pcm_prepare(struct snd_soc_component *component, alsa_stream->buffer_size, alsa_stream->period_size, alsa_stream->pos, runtime->frame_bits); + if (alsa_stream->reused_for_voip) { + /* Userspace should only select one EP for VoIP capture and one EP for + * VoIP playback. + */ + prepare_voipcall(alsa_stream); + } mutex_unlock(&chip->audio_mutex); return 0; } diff --git a/alsa/aoc_alsa_pcm.c b/alsa/aoc_alsa_pcm.c index 157d265..14fbf12 100644 --- a/alsa/aoc_alsa_pcm.c +++ b/alsa/aoc_alsa_pcm.c @@ -133,6 +133,39 @@ void aoc_timer_stop_sync(struct aoc_alsa_stream *alsa_stream) } } +bool aoc_pcm_update_pos(struct aoc_alsa_stream *alsa_stream, unsigned long consumed) +{ + unsigned long buffer_cnt; + + /* Update the pcm pointer */ + if (unlikely(alsa_stream->n_overflow)) { + alsa_stream->pos = (consumed + 0x100000000 * alsa_stream->n_overflow - + alsa_stream->hw_ptr_base) % + alsa_stream->buffer_size; + buffer_cnt = (consumed + 0x100000000 * alsa_stream->n_overflow - + alsa_stream->hw_ptr_base) / alsa_stream->buffer_size; + } else { + alsa_stream->pos = (consumed - alsa_stream->hw_ptr_base) % alsa_stream->buffer_size; + buffer_cnt = (consumed - alsa_stream->hw_ptr_base) / alsa_stream->buffer_size; + } + + /* Update hw_ptr if the consumed data is equal to or bigger than one period */ + if (buffer_cnt == alsa_stream->prev_buffer_cnt) + alsa_stream->pos_delta = alsa_stream->pos - alsa_stream->prev_pos; + else { + alsa_stream->pos_delta = (alsa_stream->pos + alsa_stream->buffer_size * + (buffer_cnt - alsa_stream->prev_buffer_cnt)) - + alsa_stream->prev_pos; + if ((buffer_cnt - alsa_stream->prev_buffer_cnt) != 1) + pr_warn("idx(%d): buffer_cnt %ld, prev_buffer_cnt %ld, pos_delta = %d\n", + alsa_stream->idx, buffer_cnt, alsa_stream->prev_buffer_cnt, + alsa_stream->pos_delta); + alsa_stream->prev_buffer_cnt = buffer_cnt; + } + + return (alsa_stream->pos_delta >= alsa_stream->period_size) ? true : false; +} + /* Hardware definition * TODO: different pcm may have different hardware setup, * considering deep buffer and compressed offload buffer @@ -198,14 +231,10 @@ static enum hrtimer_restart aoc_pcm_irq_process(struct aoc_alsa_stream *alsa_str } alsa_stream->prev_consumed = consumed; - /* Update the pcm pointer */ - if (unlikely(alsa_stream->n_overflow)) { - alsa_stream->pos = (consumed + 0x100000000 * alsa_stream->n_overflow - - alsa_stream->hw_ptr_base) % - alsa_stream->buffer_size; - } else { - alsa_stream->pos = (consumed - alsa_stream->hw_ptr_base) % alsa_stream->buffer_size; - } + if (!aoc_pcm_update_pos(alsa_stream, consumed)) + return HRTIMER_RESTART; + + alsa_stream->prev_pos = alsa_stream->pos; /* Do not queue a work if the cancel_work is active */ if (atomic_read(&alsa_stream->cancel_work_active) > 0 || alsa_stream->pcm_period_wq == NULL) @@ -343,6 +372,7 @@ static int snd_aoc_pcm_open(struct snd_soc_component *component, aoc_ring_bytes_written(dev->service, AOC_UP); alsa_stream->prev_consumed = alsa_stream->hw_ptr_base; alsa_stream->n_overflow = 0; + alsa_stream->prev_buffer_cnt = 0; err = aoc_audio_open(alsa_stream); if (err != 0) { @@ -558,24 +588,29 @@ static int snd_aoc_pcm_prepare(struct snd_soc_component *component, alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream); alsa_stream->period_size = snd_pcm_lib_period_bytes(substream); alsa_stream->pos = 0; + alsa_stream->prev_pos = 0; + alsa_stream->pos_delta = 0; alsa_stream->hw_ptr_base = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? aoc_ring_bytes_read(dev->service, AOC_DOWN) : aoc_ring_bytes_written(dev->service, AOC_UP); alsa_stream->prev_consumed = alsa_stream->hw_ptr_base; alsa_stream->n_overflow = 0; + alsa_stream->prev_buffer_cnt = 0; pr_debug("pcm prepare: hw_ptr_base = %lu\n", alsa_stream->hw_ptr_base); pr_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n", alsa_stream->buffer_size, alsa_stream->period_size, alsa_stream->pos, runtime->frame_bits); - /* Advance the write ptr in the DRAM ring buffer for mmap-based playback */ - if (alsa_stream->stream_type == MMAPED && - alsa_stream->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - avail = aoc_ring_bytes_available_to_write(dev->service, AOC_DOWN); - if (!aoc_service_advance_write_index(dev->service, AOC_DOWN, avail)) { - dev_err(&(dev->dev), "ERR: in advancing pcm playback writer ptr\n"); - } + if (alsa_stream->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { + alsa_stream->stream_type = MMAPED; + /* Advance the write ptr in the DRAM ring buffer for mmap-based playback */ + avail = aoc_ring_bytes_available_to_write(dev->service, AOC_DOWN); + if (!aoc_service_advance_write_index(dev->service, AOC_DOWN, avail)) + dev_err(&(dev->dev), "ERR: in advancing pcm playback writer ptr\n"); + } else + alsa_stream->stream_type = NORMAL; } out: diff --git a/alsa/aoc_alsa_voip.c b/alsa/aoc_alsa_voip.c index f6200dd..f9f85ba 100644 --- a/alsa/aoc_alsa_voip.c +++ b/alsa/aoc_alsa_voip.c @@ -76,14 +76,10 @@ static enum hrtimer_restart aoc_voip_irq_process(struct aoc_alsa_stream *alsa_st } alsa_stream->prev_consumed = consumed; - /* Update the pcm pointer */ - if (unlikely(alsa_stream->n_overflow)) { - alsa_stream->pos = (consumed + 0x100000000 * alsa_stream->n_overflow - - alsa_stream->hw_ptr_base) % - alsa_stream->buffer_size; - } else { - alsa_stream->pos = (consumed - alsa_stream->hw_ptr_base) % alsa_stream->buffer_size; - } + if (!aoc_pcm_update_pos(alsa_stream, consumed)) + return HRTIMER_RESTART; + + alsa_stream->prev_pos = alsa_stream->pos; /* Do not queue a work if the cancel_work is active */ if (atomic_read(&alsa_stream->cancel_work_active) > 0 @@ -212,6 +208,7 @@ static int snd_aoc_pcm_open(struct snd_soc_component *component, aoc_ring_bytes_written(dev->service, AOC_UP); alsa_stream->prev_consumed = alsa_stream->hw_ptr_base; alsa_stream->n_overflow = 0; + alsa_stream->prev_buffer_cnt = 0; err = aoc_audio_open(alsa_stream); if (err != 0) { @@ -400,11 +397,15 @@ static int snd_aoc_pcm_prepare(struct snd_soc_component *component, alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream); alsa_stream->period_size = snd_pcm_lib_period_bytes(substream); alsa_stream->pos = 0; + alsa_stream->prev_pos = 0; + alsa_stream->pos_delta = 0; + alsa_stream->hw_ptr_base = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? aoc_ring_bytes_written(dev->service, AOC_DOWN) : aoc_ring_bytes_written(dev->service, AOC_UP); alsa_stream->prev_consumed = alsa_stream->hw_ptr_base; alsa_stream->n_overflow = 0; + alsa_stream->prev_buffer_cnt = 0; pr_notice("Start voip call\n"); err = prepare_voipcall(alsa_stream); |