diff options
author | millerliang <millerliang@google.com> | 2021-10-06 23:23:53 +0800 |
---|---|---|
committer | Miller Liang <millerliang@google.com> | 2021-10-13 16:24:42 +0000 |
commit | 2ea06d398df00e4383e0f538b4443cc3f471dba6 (patch) | |
tree | cd6cd749eaf8c9aa5883dbadb3235fd6db3c36a7 | |
parent | 07596de8fb03884e88855660209e4089ca95cd01 (diff) | |
download | aoc-2ea06d398df00e4383e0f538b4443cc3f471dba6.tar.gz |
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 <millerliang@google.com>
Change-Id: I61d6e041507a385eb9f36d4a773f6751b542ada9
-rw-r--r-- | alsa/aoc_alsa_pcm.c | 15 | ||||
-rw-r--r-- | aoc.c | 30 | ||||
-rw-r--r-- | 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; @@ -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; @@ -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, |