From 2ea06d398df00e4383e0f538b4443cc3f471dba6 Mon Sep 17 00:00:00 2001 From: millerliang Date: Wed, 6 Oct 2021 23:23:53 +0800 Subject: aoc/alsa: return the heap address for mmap use cases Some applications may stop the mmap stream but not close it. Audio HAL will fail to get the dma-buf fd at the next stream, then it will fall back to use the shared mode fd(/dev/snd). Since AoC hooks the ring buffer address to the dma-buf heap address, we return the same heap address in pcm mmap function for mmap playback and capture use cases. Bug:198963233 Test: 1. b/199285450#comment1, test_steal_exclusive -c0 2. OboeTester Signed-off-by: millerliang Change-Id: I61d6e041507a385eb9f36d4a773f6751b542ada9 --- alsa/aoc_alsa_pcm.c | 15 +++++++++++---- aoc.c | 30 ++++++++++++++++++++++++++++++ aoc.h | 2 ++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/alsa/aoc_alsa_pcm.c b/alsa/aoc_alsa_pcm.c index 908f908..5cbd12f 100644 --- a/alsa/aoc_alsa_pcm.c +++ b/alsa/aoc_alsa_pcm.c @@ -607,16 +607,23 @@ static int snd_aoc_pcm_mmap(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = substream->runtime; struct aoc_alsa_stream *alsa_stream = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; size_t ring_size; int err; phys_addr_t aoc_ring_base; + aoc_direction dir; + + dir = ((alsa_stream->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + AOC_DOWN : AOC_UP); - if (alsa_stream->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + /* return the heap base address for MMAP playback and capture */ + if (is_aaudio_mmaped_service(rtd->dai_link->name)) { aoc_ring_base = - aoc_service_ring_base_phys_addr(alsa_stream->dev, AOC_DOWN, &ring_size); - else + aoc_get_heap_base_phys_addr(alsa_stream->dev, dir, &ring_size); + } else { aoc_ring_base = - aoc_service_ring_base_phys_addr(alsa_stream->dev, AOC_UP, &ring_size); + aoc_service_ring_base_phys_addr(alsa_stream->dev, dir, &ring_size); + } alsa_stream->vma = vma; diff --git a/aoc.c b/aoc.c index 0983597..5a13f55 100644 --- a/aoc.c +++ b/aoc.c @@ -903,6 +903,36 @@ phys_addr_t aoc_service_ring_base_phys_addr(struct aoc_service_dev *dev, aoc_dir } EXPORT_SYMBOL_GPL(aoc_service_ring_base_phys_addr); +phys_addr_t aoc_get_heap_base_phys_addr(struct aoc_service_dev *dev, aoc_direction dir, + size_t *out_size) +{ + const struct device *parent; + struct aoc_prvdata *prvdata; + aoc_service *service; + phys_addr_t audio_heap_base; + + if (!dev) + return -EINVAL; + + parent = dev->dev.parent; + prvdata = dev_get_drvdata(parent); + + service = service_at_index(prvdata, dev->service_index); + + if (out_size) + *out_size = aoc_service_ring_size(service, dir); + + if (dir == AOC_DOWN) + audio_heap_base = prvdata->audio_playback_heap_base; + else + audio_heap_base = prvdata->audio_capture_heap_base; + + pr_debug("Get heap address(phy):%llx\n", audio_heap_base); + + return audio_heap_base; +} +EXPORT_SYMBOL_GPL(aoc_get_heap_base_phys_addr); + bool aoc_service_flush_read_data(struct aoc_service_dev *dev) { const struct device *parent; diff --git a/aoc.h b/aoc.h index 506e7df..cfcf011 100644 --- a/aoc.h +++ b/aoc.h @@ -41,6 +41,8 @@ struct aoc_service_dev { phys_addr_t aoc_service_ring_base_phys_addr(struct aoc_service_dev *dev, aoc_direction dir, size_t *out_size); +phys_addr_t aoc_get_heap_base_phys_addr(struct aoc_service_dev *dev, aoc_direction dir, + size_t *out_size); ssize_t aoc_service_read(struct aoc_service_dev *dev, uint8_t *buffer, size_t count, bool block); ssize_t aoc_service_read_timeout(struct aoc_service_dev *dev, uint8_t *buffer, -- cgit v1.2.3