1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2025-08-04 15:30:24 +00:00
Files
physwizz 99537be4e2 first
2024-03-11 06:53:12 +11:00

1626 lines
41 KiB
C

// SPDX-License-Identifier: GPL-2.0
//
// Copyright (C) 2018 MediaTek Inc.
/* linux include path*/
#if defined(__linux__)
#include <linux/uaccess.h>
#include <sound/pcm.h>
#include <sound/core.h>
#include "mtk-dsp-mem-control.h"
#include "mtk-dsp-common.h"
#include "audio_buf.h"
#include <linux/kprobes.h>
#include <asm/traps.h>
#define AUD_LOG_W(format, args...) snd_printk(format, ##args)
#ifdef CONFIG_SND_VERBOSE_PRINTK
#define AUD_LOG_D(format, args...) snd_printk(format, ##args)
#else
#define AUD_LOG_D(format, args...)
#endif
#endif
#ifdef CFG_AUDIO_SUPPORT
#include <audio_type.h>
#include <audio_ringbuf.h>
#include <dma.h>
#include "audio_hw_reg.h"
#include <dvfs.h>
#endif
#include <audio_ipi_dma.h>
#define AUDIO_BUF_ALIGNEMNT (8)
/* #define RINGBUF_COUNT_CHECK */
/*
* function for get how many data is available
* @return how many data exist
*/
unsigned int RingBuf_getDataCount(const struct RingBuf *RingBuf1)
{
return RingBuf1->datacount;
}
EXPORT_SYMBOL(RingBuf_getDataCount);
/*
*
* function for get hw free space available
* @return how free sapce
*/
unsigned int RingBuf_getFreeSpace(const struct RingBuf *RingBuf1)
{
return RingBuf1->bufLen - RingBuf1->datacount;
}
EXPORT_SYMBOL(RingBuf_getFreeSpace);
/**
* copy count number bytes from ring buffer to buf
* @param buf buffer copy from
* @param RingBuf1 buffer copy to
* @param count number of bytes need to copy
*/
void RingBuf_copyToLinear(char *buf, struct RingBuf *RingBuf1,
unsigned int count)
{
if (count == 0)
return;
if (RingBuf_getDataCount(RingBuf1) < count) {
AUD_LOG_D("RingBuf_getDataCount(RingBuf1) %d < count %d\n",
RingBuf_getDataCount(RingBuf1), count);
return;
}
if (RingBuf1->pRead <= RingBuf1->pWrite) {
memcpy(buf, RingBuf1->pRead, count);
RingBuf1->pRead += count;
if (RingBuf1->pRead >= RingBuf1->pBufEnd)
RingBuf1->pRead -= RingBuf1->bufLen;
} else {
unsigned int r2e = RingBuf1->pBufEnd - RingBuf1->pRead;
if (count <= r2e) {
memcpy(buf, RingBuf1->pRead, count);
RingBuf1->pRead += count;
if (RingBuf1->pRead >= RingBuf1->pBufEnd)
RingBuf1->pRead -= RingBuf1->bufLen;
} else {
memcpy(buf, RingBuf1->pRead, r2e);
memcpy(buf + r2e, RingBuf1->pBufBase, count - r2e);
RingBuf1->pRead = RingBuf1->pBufBase + count - r2e;
}
}
RingBuf1->datacount -= count;
Ringbuf_Check(RingBuf1);
}
/**
* copy count number bytes from buf to RingBuf1
* @param RingBuf1 ring buffer copy from
* @param buf copy to
* @param count number of bytes need to copy
*/
void RingBuf_copyFromLinear(struct RingBuf *RingBuf1, const char *buf,
unsigned int count)
{
int spaceIHave;
char *end = RingBuf1->pBufBase + RingBuf1->bufLen;
/* count buffer data I have */
spaceIHave = RingBuf_getFreeSpace(RingBuf1);
/* if not enough, assert */
/* ASSERT(spaceIHave >= count); */
if (spaceIHave < count) {
AUD_LOG_W("spaceIHave %d < count %d\n", spaceIHave, count);
return;
}
if (RingBuf1->pRead <= RingBuf1->pWrite) {
int w2e = end - RingBuf1->pWrite;
if (count <= w2e) {
memcpy(RingBuf1->pWrite, buf, count);
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= end)
RingBuf1->pWrite -= RingBuf1->bufLen;
} else {
memcpy(RingBuf1->pWrite, buf, w2e);
memcpy(RingBuf1->pBufBase, buf + w2e, count - w2e);
RingBuf1->pWrite = RingBuf1->pBufBase + count - w2e;
}
} else {
memcpy(RingBuf1->pWrite, buf, count);
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= RingBuf1->pBufEnd)
RingBuf1->pWrite -= RingBuf1->bufLen;
}
RingBuf1->datacount += count;
Ringbuf_Check(RingBuf1);
}
/**
* copy ring buffer from RingBufs(source) to RingBuft(target)
* @param RingBuft ring buffer copy to
* @param RingBufs copy from copy from
*/
void RingBuf_copyFromRingBufAll(struct RingBuf *RingBuft,
struct RingBuf *RingBufs)
{
/* if not enough, assert */
/* ASSERT(RingBuf_getFreeSpace(RingBuft) >= */
/* RingBuf_getDataCount(RingBufs)); */
if (RingBuf_getFreeSpace(RingBuft) < RingBuf_getDataCount(RingBufs))
AUD_LOG_D(
"RingBuf_getFreeSpace(RingBuft) %d < RingBuf_getDataCount(RingBufs) %d\n",
RingBuf_getFreeSpace(RingBuft),
RingBuf_getDataCount(RingBufs));
if (RingBufs->pRead <= RingBufs->pWrite) {
RingBuf_copyFromLinear(RingBuft, RingBufs->pRead,
RingBufs->pWrite - RingBufs->pRead);
} else {
RingBuf_copyFromLinear(RingBuft, RingBufs->pRead,
RingBufs->pBufEnd - RingBufs->pRead);
RingBuf_copyFromLinear(RingBuft, RingBufs->pBufBase,
RingBufs->pWrite - RingBufs->pBufBase);
}
RingBufs->pRead = RingBufs->pWrite;
Ringbuf_Check(RingBuft);
Ringbuf_Check(RingBufs);
}
/**
* copy ring buffer from RingBufs(source) to RingBuft(target) with count
* @param RingBuft ring buffer copy to
* @param RingBufs copy from copy from
*/
int RingBuf_copyFromRingBuf(struct RingBuf *RingBuft, struct RingBuf *RingBufs,
unsigned int count)
{
if (count == 0)
return 0;
/* if not enough, assert */
/* ASSERT(RingBuf_getDataCount(RingBufs) >= count && */
/* RingBuf_getFreeSpace(RingBuft) >= count); */
if ((RingBuf_getDataCount(RingBufs) < count) ||
(RingBuf_getFreeSpace(RingBuft) < count)) {
AUD_LOG_D("Space RingBuft %d || Data RingBufs %d < count %d\n",
RingBuf_getFreeSpace(RingBuft),
RingBuf_getDataCount(RingBufs), count);
}
if (RingBufs->pRead <= RingBufs->pWrite) {
RingBuf_copyFromLinear(RingBuft, RingBufs->pRead, count);
RingBufs->pRead += count;
if (RingBufs->pRead >= RingBufs->pBufEnd)
RingBufs->pRead -= RingBufs->bufLen;
} else {
unsigned int r2e = RingBufs->pBufEnd - RingBufs->pRead;
if (r2e >= count) {
RingBuf_copyFromLinear(RingBuft, RingBufs->pRead,
count);
RingBufs->pRead += count;
if (RingBufs->pRead >= RingBufs->pBufEnd)
RingBufs->pRead -= RingBufs->bufLen;
} else {
RingBuf_copyFromLinear(RingBuft, RingBufs->pRead, r2e);
RingBuf_copyFromLinear(RingBuft, RingBufs->pBufBase,
count - r2e);
RingBufs->pRead = RingBufs->pBufBase + count - r2e;
}
}
Ringbuf_Check(RingBuft);
Ringbuf_Check(RingBufs);
return count;
}
/**
* write bytes size of count with value
* @param RingBuf1 ring buffer copy to
* @value put into buffer
* @count bytes ned to put.
*/
void RingBuf_writeDataValue(struct RingBuf *RingBuf1, const char value,
const unsigned int count)
{
if (count == 0)
return;
/* if not enough, assert */
if (RingBuf_getFreeSpace(RingBuf1) < count) {
AUD_LOG_D("RingBuf_getFreeSpace(RingBuf1) %d < count %d\n",
RingBuf_getFreeSpace(RingBuf1), count);
}
if (RingBuf1->pRead <= RingBuf1->pWrite) {
unsigned int w2e = RingBuf1->pBufEnd - RingBuf1->pWrite;
if (count <= w2e) {
memset(RingBuf1->pWrite, value, count);
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= RingBuf1->pBufEnd)
RingBuf1->pWrite -= RingBuf1->bufLen;
} else {
memset(RingBuf1->pWrite, value, w2e);
memset(RingBuf1->pBufBase, value, count - w2e);
RingBuf1->pWrite = RingBuf1->pBufBase + count - w2e;
}
} else {
memset(RingBuf1->pWrite, value, count);
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= RingBuf1->pBufEnd)
RingBuf1->pWrite -= RingBuf1->bufLen;
}
RingBuf1->datacount += count;
}
void RingBuf_update_writeptr(struct RingBuf *RingBuf1, unsigned int count)
{
if (count == 0 || count > RingBuf1->bufLen) {
AUD_LOG_W("%s count[%u] datacount[%d] Len[%d]\n",
__func__, count,
RingBuf1->datacount, RingBuf1->bufLen);
return;
}
if (RingBuf1->pRead <= RingBuf1->pWrite) {
unsigned int w2e = RingBuf1->pBufEnd - RingBuf1->pWrite;
if (count <= w2e) {
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= RingBuf1->pBufEnd)
RingBuf1->pWrite -= RingBuf1->bufLen;
} else {
RingBuf1->pWrite = RingBuf1->pBufBase + count - w2e;
if (RingBuf1->pWrite > RingBuf1->pRead)
RingBuf1->pWrite = RingBuf1->pBufBase;
}
} else {
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= RingBuf1->pBufEnd)
RingBuf1->pWrite -= RingBuf1->bufLen;
}
/* handle buffer overflow*/
if (RingBuf1->datacount + count > RingBuf1->bufLen) {
AUD_LOG_W("%s overflow count[%u] datacount[%d] Len[%d]\n",
__func__, count,
RingBuf1->datacount, RingBuf1->bufLen);
if (RingBuf1->pWrite >= RingBuf1->pRead)
RingBuf1->datacount =
RingBuf1->pWrite - RingBuf1->pRead;
else
RingBuf1->datacount =
RingBuf1->pRead + RingBuf1->bufLen - RingBuf1->pWrite;
} else
RingBuf1->datacount += count;
Ringbuf_Check(RingBuf1);
}
EXPORT_SYMBOL(RingBuf_update_writeptr);
void RingBuf_update_readptr(struct RingBuf *RingBuf1, unsigned int count)
{
if (count == 0 || count > RingBuf1->bufLen) {
#ifdef RINGBUF_COUNT_CHECK
AUD_LOG_W("%s count[%u] datacount[%d] Len[%d]\n",
__func__, count,
RingBuf1->datacount, RingBuf1->bufLen);
#endif
return;
}
if (RingBuf1->pRead <= RingBuf1->pWrite) {
RingBuf1->pRead += count;
if (RingBuf1->pRead >= RingBuf1->pBufEnd)
RingBuf1->pRead -= RingBuf1->bufLen;
} else {
unsigned int r2e = RingBuf1->pBufEnd - RingBuf1->pRead;
if (count <= r2e) {
RingBuf1->pRead += count;
if (RingBuf1->pRead >= RingBuf1->pBufEnd)
RingBuf1->pRead -= RingBuf1->bufLen;
} else {
RingBuf1->pRead = RingBuf1->pBufBase + count - r2e;
if (RingBuf1->pRead >= RingBuf1->pBufEnd)
RingBuf1->pRead -= RingBuf1->bufLen;
}
}
/* handle buffer underflow*/
if (count > RingBuf1->datacount) {
#ifdef RINGBUF_COUNT_CHECK
AUD_LOG_W("%s underflow count %u datacount %d Len %d\n",
__func__, count,
RingBuf1->datacount, RingBuf1->bufLen);
#endif
if (RingBuf1->pWrite >= RingBuf1->pRead)
RingBuf1->datacount =
RingBuf1->pWrite - RingBuf1->pRead;
else
RingBuf1->datacount =
RingBuf1->pRead + RingBuf1->bufLen - RingBuf1->pWrite;
} else
RingBuf1->datacount -= count;
Ringbuf_Check(RingBuf1);
}
void RingBuf_Bridge_update_writeptr(struct ringbuf_bridge *RingBuf1,
const unsigned int count)
{
if (count == 0)
return;
#ifdef RINGBUF_COUNT_CHECK
if (RingBuf1->datacount + count > RingBuf1->bufLen) {
AUD_LOG_W("datacount %llu count %u bufLen %llu\n",
RingBuf1->datacount, count,
RingBuf1->bufLen);
AUD_ASSERT(0);
}
#endif
if (RingBuf1->pRead <= RingBuf1->pWrite) {
unsigned int w2e = RingBuf1->pBufEnd - RingBuf1->pWrite;
if (count <= w2e) {
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= RingBuf1->pBufEnd)
RingBuf1->pWrite -= RingBuf1->bufLen;
} else {
RingBuf1->pWrite = RingBuf1->pBufBase + count - w2e;
if (RingBuf1->pWrite > RingBuf1->pRead)
RingBuf1->pWrite = RingBuf1->pBufBase;
}
} else {
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= RingBuf1->pBufEnd)
RingBuf1->pWrite -= RingBuf1->bufLen;
}
Ringbuf_Bridge_Check(RingBuf1);
}
EXPORT_SYMBOL(RingBuf_Bridge_update_writeptr);
void RingBuf_Bridge_update_readptr(struct ringbuf_bridge *RingBuf1,
const unsigned int count)
{
if (count == 0)
return;
if (RingBuf1->pRead <= RingBuf1->pWrite) {
RingBuf1->pRead += count;
if (RingBuf1->pRead >= RingBuf1->pBufEnd)
RingBuf1->pRead -= RingBuf1->pBufBase;
} else {
unsigned int r2e = RingBuf1->pBufEnd - RingBuf1->pRead;
if (count <= r2e) {
RingBuf1->pRead += count;
if (RingBuf1->pRead >= RingBuf1->pBufEnd)
RingBuf1->pRead -= RingBuf1->pBufBase;
} else {
RingBuf1->pRead = RingBuf1->pBufBase + count - r2e;
if (RingBuf1->pRead >= RingBuf1->pBufEnd)
RingBuf1->pRead -= RingBuf1->bufLen;
}
}
Ringbuf_Bridge_Check(RingBuf1);
}
void dump_audio_dsp_dram(struct audio_dsp_dram *dsp_dram)
{
AUD_LOG_D(
"%s dsp_dram vir_addr = %p va_addr = 0x%llx phy_addr =0x%llx size=%llu\n",
__func__, dsp_dram->vir_addr, dsp_dram->va_addr,
dsp_dram->phy_addr, dsp_dram->size);
}
EXPORT_SYMBOL(dump_audio_dsp_dram);
#if defined(__linux__)
int release_snd_dmabuffer(struct snd_dma_buffer *dma_buffer)
{
dma_buffer->area = NULL;
dma_buffer->addr = 0;
dma_buffer->bytes = 0;
return 0;
}
/* wrap dsp dram to dma_buffer */
int dsp_dram_to_snd_dmabuffer(struct audio_dsp_dram *dsp_dram,
struct snd_dma_buffer *dma_buffer)
{
if (dsp_dram == NULL)
return -1;
if (dma_buffer == NULL)
return -1;
dma_buffer->area = dsp_dram->vir_addr;
dma_buffer->addr = dsp_dram->phy_addr;
dma_buffer->bytes = dsp_dram->size;
return 0;
}
/* wrap snd_dma_buffer to audio_hw_buffer */
int snd_dmabuffer_to_audio_ring_buffer(struct snd_dma_buffer *dma_buffer,
struct RingBuf *audio_ring_buf)
{
int ret = 0;
if (dma_buffer == NULL || audio_ring_buf == NULL)
return -1;
if (dma_buffer->area == NULL) {
AUD_LOG_D("%s ma_buffer->area == NULL", __func__);
return -1;
}
if (dma_buffer->bytes == 0) {
AUD_LOG_D("%s ma_buffer->bytes == 0", __func__);
return -1;
}
audio_ring_buf->bufLen = dma_buffer->bytes;
audio_ring_buf->pBufBase = dma_buffer->area;
audio_ring_buf->pBufEnd = dma_buffer->area + dma_buffer->bytes - 1;
audio_ring_buf->pWrite = audio_ring_buf->pBufBase;
audio_ring_buf->pRead = audio_ring_buf->pBufBase;
return ret;
}
int snd_dmabuffer_to_audio_ring_buffer_bridge(
struct snd_dma_buffer *dma_buffer,
struct ringbuf_bridge *audio_ring_buf_brideg)
{
int ret = 0;
if (dma_buffer == NULL || audio_ring_buf_brideg == NULL)
return -1;
if (dma_buffer->area == NULL) {
AUD_LOG_D("%s ma_buffer->area == NULL", __func__);
return -1;
}
if (dma_buffer->bytes == 0) {
AUD_LOG_D("%s ma_buffer->bytes == 0", __func__);
return -1;
}
audio_ring_buf_brideg->bufLen = dma_buffer->bytes;
audio_ring_buf_brideg->pBufBase = dma_buffer->addr;
audio_ring_buf_brideg->pBufEnd =
dma_buffer->addr + dma_buffer->bytes - 1;
audio_ring_buf_brideg->pWrite = audio_ring_buf_brideg->pBufBase;
audio_ring_buf_brideg->pRead = audio_ring_buf_brideg->pBufBase;
return ret;
}
int set_audiobuffer_threshold(struct audio_hw_buffer *audio_hwbuf,
struct snd_pcm_substream *substream)
{
int ret = 0;
if (audio_hwbuf == NULL) {
AUD_LOG_D("%s audio_hwbuf == NULL", __func__);
return -1;
}
audio_hwbuf->aud_buffer.start_threshold =
substream->runtime->start_threshold;
audio_hwbuf->aud_buffer.stop_threshold =
substream->runtime->stop_threshold;
audio_hwbuf->aud_buffer.period_size = substream->runtime->period_size;
audio_hwbuf->aud_buffer.period_count = substream->runtime->periods;
return ret;
}
int set_afe_audio_pcmbuf(struct audio_hw_buffer *audio_hwbuf,
struct snd_pcm_substream *substream)
{
int ret = 0;
ret = init_ring_buf_bridge(
&audio_hwbuf->aud_buffer.buf_bridge,
(unsigned long long)substream->runtime->dma_addr,
substream->runtime->dma_bytes);
return ret;
}
int set_audiobuffer_attribute(struct audio_hw_buffer *audio_hwbuf,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
int direction)
{
int ret = 0;
if (audio_hwbuf == NULL) {
AUD_LOG_D("%s audio_hwbuf == NULL", __func__);
return -1;
}
audio_hwbuf->aud_buffer.buffer_attr.direction = direction;
if (params == NULL)
return 0;
audio_hwbuf->aud_buffer.buffer_attr.channel = params_channels(params);
audio_hwbuf->aud_buffer.buffer_attr.format = params_format(params);
audio_hwbuf->aud_buffer.buffer_attr.rate = params_rate(params);
return ret;
}
void RingBuf_copyFromUserLinear(struct RingBuf *RingBuf1, void __user *buf,
unsigned int count)
{
int spaceIHave, ret;
char *end = RingBuf1->pBufBase + RingBuf1->bufLen;
/* count buffer data I have */
spaceIHave = RingBuf_getFreeSpace(RingBuf1);
/* if not enough, assert */
/* ASSERT(spaceIHave >= count); */
if (spaceIHave < count) {
AUD_LOG_W("spaceIHave %d < count %d\n", spaceIHave, count);
return;
}
if (RingBuf1->pRead <= RingBuf1->pWrite) {
int w2e = end - RingBuf1->pWrite;
if (count <= w2e) {
ret = copy_from_user(RingBuf1->pWrite, buf, count);
if (ret)
AUD_LOG_D("%s copy_from_user fail line %d\n",
__func__, __LINE__);
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= end)
RingBuf1->pWrite -= RingBuf1->bufLen;
} else {
ret = copy_from_user(RingBuf1->pWrite, buf, w2e);
if (ret)
AUD_LOG_D("%s copy_from_user fail line %d\n",
__func__, __LINE__);
ret = copy_from_user(RingBuf1->pBufBase, buf + w2e,
count - w2e);
if (ret)
AUD_LOG_D("%s copy_from_user fail line %d\n",
__func__, __LINE__);
RingBuf1->pWrite = RingBuf1->pBufBase + count - w2e;
}
} else {
ret = copy_from_user(RingBuf1->pWrite, buf, count);
if (ret)
AUD_LOG_D("%s copy_from_user fail line %d\n",
__func__, __LINE__);
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= RingBuf1->pBufEnd)
RingBuf1->pWrite -= RingBuf1->bufLen;
}
RingBuf1->datacount += count;
}
EXPORT_SYMBOL(RingBuf_copyFromUserLinear);
void ringbuf_copyto_user_linear(void __user *buf, struct RingBuf *RingBuf1,
unsigned int count)
{
int ret = 0;
if (count == 0)
return;
if (RingBuf_getDataCount(RingBuf1) < count) {
AUD_LOG_D("RingBuf_getDataCount(RingBuf1) %d < count %d\n",
RingBuf_getDataCount(RingBuf1), count);
return;
}
if (RingBuf1->pRead <= RingBuf1->pWrite) {
ret = copy_to_user(buf, RingBuf1->pRead, count);
if (ret)
AUD_LOG_D("%s copy_to_user fail line %d\n",
__func__, __LINE__);
RingBuf1->pRead += count;
if (RingBuf1->pRead >= RingBuf1->pBufEnd)
RingBuf1->pRead -= RingBuf1->bufLen;
} else {
unsigned int r2e = RingBuf1->pBufEnd - RingBuf1->pRead;
if (count <= r2e) {
ret = copy_to_user(buf, RingBuf1->pRead, count);
if (ret)
AUD_LOG_D("%s copy_to_user fail line %d\n",
__func__, __LINE__);
RingBuf1->pRead += count;
if (RingBuf1->pRead >= RingBuf1->pBufEnd)
RingBuf1->pRead -= RingBuf1->bufLen;
} else {
ret = copy_to_user(buf, RingBuf1->pRead, r2e);
if (ret)
AUD_LOG_D("%s copy_to_user fail line %d\n",
__func__, __LINE__);
ret = copy_to_user(buf + r2e,
RingBuf1->pBufBase,
count - r2e);
if (ret)
AUD_LOG_D("%s copy_to_user fail line %d\n",
__func__, __LINE__);
RingBuf1->pRead = RingBuf1->pBufBase + count - r2e;
}
}
RingBuf1->datacount -= count;
Ringbuf_Check(RingBuf1);
}
#endif
int init_ring_buf(struct RingBuf *buf, char *vaaddr, int size)
{
if (buf == NULL) {
AUD_LOG_D("%s buf == NULL\n", __func__);
return -1;
} else if (vaaddr == NULL) {
AUD_LOG_D("%s vaaddr == NULL\n", __func__);
return -1;
} else if (size == 0) {
AUD_LOG_D("%s size == 0\n", __func__);
return -1;
}
buf->pBufBase = vaaddr;
buf->pBufEnd = buf->pBufBase + size;
buf->pRead = vaaddr;
buf->pWrite = vaaddr;
buf->bufLen = size;
buf->datacount = 0;
return 0;
}
int init_ring_buf_bridge(struct ringbuf_bridge *buf_bridge,
unsigned long long paaddr, int size)
{
if (buf_bridge == NULL) {
AUD_LOG_D("%s buf_bridge == NULL\n", __func__);
return -1;
} else if (paaddr == 0) {
AUD_LOG_D("%s paaddr == NULL\n", __func__);
return -1;
} else if (size == 0) {
AUD_LOG_D("%s size == 0\n", __func__);
return -1;
}
buf_bridge->pBufBase = paaddr;
buf_bridge->pBufEnd = buf_bridge->pBufBase + size;
buf_bridge->pRead = paaddr;
buf_bridge->pWrite = paaddr;
buf_bridge->bufLen = size;
buf_bridge->datacount = 0;
return 0;
}
void RingBuf_Bridge_Reset(struct ringbuf_bridge *RingBuf1)
{
if (RingBuf1 == NULL)
return;
RingBuf1->pRead = RingBuf1->pBufBase;
RingBuf1->pWrite = RingBuf1->pBufBase;
RingBuf1->datacount = 0;
}
int RingBuf_Bridge_Clear(struct ringbuf_bridge *RingBuf1)
{
if (RingBuf1 == NULL)
return -1;
if (RingBuf1->pBufBase != 0 && RingBuf1->pBufEnd != 0) {
RingBuf1->pBufBase = 0;
RingBuf1->pBufEnd = 0;
RingBuf1->pRead = 0;
RingBuf1->pWrite = 0;
RingBuf1->bufLen = 0;
RingBuf1->datacount = 0;
}
return 0;
}
bool is_ringbuf_clear(struct RingBuf *ring_buf)
{
if (ring_buf == NULL) {
AUD_LOG_W("%s() ring_buf NULL\n", __func__);
return false;
}
if (ring_buf->pBufBase == 0 ||
ring_buf->pBufEnd == 0 ||
ring_buf->pWrite == 0 ||
ring_buf->pRead == 0 ||
ring_buf->bufLen == 0)
return true;
return false;
}
bool is_ringbuf_bridge_clear(struct ringbuf_bridge *ring_buf)
{
if (ring_buf == NULL) {
AUD_LOG_W("%s() ring_buf bridge NULL\n", __func__);
return false;
}
if (ring_buf->pBufBase == 0 ||
ring_buf->pBufEnd == 0 ||
ring_buf->pWrite == 0 ||
ring_buf->pRead == 0 ||
ring_buf->bufLen == 0)
return true;
return false;
}
/* check if ringbur read write pointer*/
void Ringbuf_Bridge_Check(struct ringbuf_bridge *buf_bridge)
{
if (buf_bridge->pRead > buf_bridge->pBufBase + buf_bridge->bufLen) {
dump_rbuf_bridge(buf_bridge);
#if defined(__linux__)
dump_stack();
#endif
AUD_ASSERT(0);
}
if (buf_bridge->pWrite > buf_bridge->pBufBase + buf_bridge->bufLen) {
dump_rbuf_bridge(buf_bridge);
#if defined(__linux__)
dump_stack();
#endif
AUD_ASSERT(0);
}
if (buf_bridge->pWrite < buf_bridge->pBufBase) {
dump_rbuf_bridge(buf_bridge);
#if defined(__linux__)
dump_stack();
#endif
AUD_ASSERT(0);
}
if (buf_bridge->pRead < buf_bridge->pBufBase) {
dump_rbuf_bridge(buf_bridge);
#if defined(__linux__)
dump_stack();
#endif
AUD_ASSERT(0);
}
}
/* check if ringbur read write pointer */
void Ringbuf_Check(struct RingBuf *RingBuf1)
{
if (RingBuf1->pRead == RingBuf1->pWrite) {
#ifdef RINGBUF_COUNT_CHECK
if (RingBuf1->datacount != 0 && RingBuf1->datacount
!= RingBuf1->bufLen) {
dump_ring_bufinfo(RingBuf1);
#if defined(__linux__)
dump_stack();
#endif
AUD_ASSERT(0);
}
#endif
} else if (RingBuf1->pWrite > RingBuf1->pRead) {
#ifdef RINGBUF_COUNT_CHECK
if ((RingBuf1->pWrite - RingBuf1->pRead)
!= RingBuf1->datacount) {
dump_ring_bufinfo(RingBuf1);
#if defined(__linux__)
dump_stack();
#endif
AUD_ASSERT(0);
}
#endif
} else if (RingBuf1->pRead > RingBuf1->pWrite) {
#ifdef RINGBUF_COUNT_CHECK
if ((RingBuf1->bufLen - (RingBuf1->pRead - RingBuf1->pWrite))
!= RingBuf1->datacount) {
dump_ring_bufinfo(RingBuf1);
#if defined(__linux__)
dump_stack();
#endif
AUD_ASSERT(0);
}
#endif
}
if (RingBuf1->pWrite < RingBuf1->pBufBase ||
RingBuf1->pWrite > RingBuf1->pBufEnd) {
dump_rbuf(RingBuf1);
#if defined(__linux__)
dump_stack();
#endif
AUD_ASSERT(0);
}
if (RingBuf1->pRead < RingBuf1->pBufBase ||
RingBuf1->pRead > RingBuf1->pBufEnd) {
dump_rbuf(RingBuf1);
#if defined(__linux__)
dump_stack();
#endif
AUD_ASSERT(0);
}
if (RingBuf1->datacount < 0) {
dump_ring_bufinfo(RingBuf1);
#if defined(__linux__)
dump_stack();
#endif
AUD_ASSERT(0);
}
}
void RingBuf_Reset(struct RingBuf *RingBuf1)
{
if (RingBuf1 == NULL)
return;
/* clear ringbuufer data*/
memset(RingBuf1->pBufBase, 0, RingBuf1->bufLen);
RingBuf1->pRead = RingBuf1->pBufBase;
RingBuf1->pWrite = RingBuf1->pBufBase;
RingBuf1->datacount = 0;
}
EXPORT_SYMBOL(RingBuf_Reset);
int RingBuf_Clear(struct RingBuf *RingBuf1)
{
if (RingBuf1 == NULL)
return -1;
if (RingBuf1->pBufBase != NULL && RingBuf1->pBufEnd != NULL) {
/* clear ringbuufer data*/
memset(RingBuf1->pBufBase, 0, RingBuf1->bufLen);
RingBuf1->pBufBase = NULL;
RingBuf1->pBufEnd = NULL;
RingBuf1->pRead = NULL;
RingBuf1->pWrite = NULL;
RingBuf1->bufLen = 0;
}
return 0;
}
EXPORT_SYMBOL(RingBuf_Clear);
int clear_audiobuffer_hw(struct audio_hw_buffer *audio_hwbuf)
{
int ret = 0;
if (audio_hwbuf == NULL)
return -1;
RingBuf_Bridge_Reset(&audio_hwbuf->aud_buffer.buf_bridge);
return ret;
}
EXPORT_SYMBOL(clear_audiobuffer_hw);
int reset_audiobuffer(struct audio_buffer *audio_buf)
{
int ret = 0;
if (audio_buf == NULL)
return -1;
audio_buf->period_size = 0;
audio_buf->start_threshold = 0;
audio_buf->stop_threshold = 0;
RingBuf_Bridge_Reset(&audio_buf->buf_bridge);
return ret;
}
int reset_audiobuffer_hw(struct audio_hw_buffer *audio_hwbuf)
{
int ret = 0;
struct audio_buffer *audio_buf = &audio_hwbuf->aud_buffer;
if (audio_hwbuf == NULL) {
AUD_LOG_D("%s audio_hwbuf == NULL", __func__);
return -1;
}
audio_hwbuf->hw_buffer = 0;
audio_hwbuf->audio_memiftype = 0;
audio_hwbuf->irq_num = 0;
ret = reset_audiobuffer(audio_buf);
return ret;
}
int set_audiobuffer_hw(struct audio_hw_buffer *audio_hwbuf, int hw_buffer)
{
int ret = 0;
if (audio_hwbuf == NULL) {
AUD_LOG_D("%s audio_hwbuf == NULL", __func__);
return -1;
}
audio_hwbuf->hw_buffer = hw_buffer;
return ret;
}
EXPORT_SYMBOL(set_audiobuffer_hw);
int set_audiobuffer_memorytype(struct audio_hw_buffer *audio_hwbuf,
int memory_type)
{
int ret = 0;
if (audio_hwbuf == NULL) {
AUD_LOG_D("%s audio_hwbuf == NULL", __func__);
return -1;
}
audio_hwbuf->memory_type = memory_type;
return ret;
}
EXPORT_SYMBOL(set_audiobuffer_memorytype);
int set_audiobuffer_audio_memiftype(struct audio_hw_buffer *audio_hwbuf,
int audio_memiftype)
{
int ret = 0;
if (audio_hwbuf == NULL) {
AUD_LOG_D("%s audio_hwbuf == NULL", __func__);
return -1;
}
audio_hwbuf->audio_memiftype = audio_memiftype;
return ret;
}
int set_audiobuffer_audio_irq_num(struct audio_hw_buffer *audio_hwbuf,
int irq_num)
{
int ret = 0;
if (audio_hwbuf == NULL) {
AUD_LOG_D("%s audio_hwbuf == NULL", __func__);
return -1;
}
audio_hwbuf->irq_num = irq_num;
return ret;
}
int sync_ringbuf_readidx(struct RingBuf *task_ring_buf,
struct ringbuf_bridge *buf_bridge)
{
unsigned int datacount = 0;
char *readidx = NULL;
if (task_ring_buf == NULL) {
AUD_LOG_W("%s task_ring_buf == NULL", __func__);
return -1;
} else if (buf_bridge == NULL) {
AUD_LOG_W("%s buf_bridge == NULL", __func__);
return -1;
}
if (is_ringbuf_clear(task_ring_buf)) {
dump_rbuf_s("sync ringbuf readidx, rbuf is clear",
task_ring_buf);
return -1;
}
if (is_ringbuf_bridge_clear(buf_bridge)) {
dump_rbuf_bridge_s("sync ringbuf readidx, rbuf_bridge is clear",
buf_bridge);
return -1;
}
/* buffer empty */
if (task_ring_buf->pRead == task_ring_buf->pWrite &&
task_ring_buf->datacount == 0) {
AUD_LOG_W("%s task_ring_buf empty", __func__);
return -1;
}
readidx = task_ring_buf->pBufBase +
(buf_bridge->pRead - buf_bridge->pBufBase);
if (readidx >= task_ring_buf->pRead)
datacount = readidx - task_ring_buf->pRead;
else
datacount = task_ring_buf->bufLen -
(task_ring_buf->pRead - readidx);
#ifdef RINGBUF_COUNT_CHECK
if (datacount == 0 || datacount == task_ring_buf->bufLen) {
dump_rbuf_s(__func__, task_ring_buf);
dump_rbuf_bridge_s(__func__, buf_bridge);
}
#endif
RingBuf_update_readptr(task_ring_buf, datacount);
Ringbuf_Check(task_ring_buf);
Ringbuf_Bridge_Check(buf_bridge);
return 0;
}
EXPORT_SYMBOL(sync_ringbuf_readidx);
int sync_ringbuf_writeidx(struct RingBuf *task_ring_buf,
struct ringbuf_bridge *buf_bridge)
{
unsigned int datacount = 0;
char *writeidx = NULL;
if (task_ring_buf == NULL) {
AUD_LOG_D("%s task_ring_buf == NULL", __func__);
return -1;
} else if (buf_bridge == NULL) {
AUD_LOG_D("%s buf_bridge == NULL", __func__);
return -1;
}
if (is_ringbuf_clear(task_ring_buf)) {
dump_rbuf_s("sync ringbuf writeidx, rbuf is clear",
task_ring_buf);
return -1;
}
if (is_ringbuf_bridge_clear(buf_bridge)) {
dump_rbuf_bridge_s("sync ringbuf writeidx, rbuf_bridge is clear",
buf_bridge);
return -1;
}
/* buffer full */
if (task_ring_buf->pRead == task_ring_buf->pWrite &&
task_ring_buf->datacount == task_ring_buf->bufLen) {
AUD_LOG_D("%s task_ring_buf full datacount[%d]\n",
__func__, task_ring_buf->datacount);
}
writeidx = task_ring_buf->pBufBase +
(buf_bridge->pWrite - buf_bridge->pBufBase);
if (writeidx >= task_ring_buf->pWrite)
datacount = writeidx - task_ring_buf->pWrite;
else
datacount = task_ring_buf->bufLen -
(task_ring_buf->pWrite - writeidx);
RingBuf_update_writeptr(task_ring_buf, datacount);
Ringbuf_Check(task_ring_buf);
Ringbuf_Bridge_Check(buf_bridge);
return 0;
}
int sync_bridge_ringbuf_readidx(struct ringbuf_bridge *buf_bridge,
struct RingBuf *task_ring_buf)
{
if (task_ring_buf == NULL) {
AUD_LOG_D("%s task_ring_buf == NULL\n", __func__);
return -1;
} else if (buf_bridge == NULL) {
AUD_LOG_D("%s buf_bridge == NULL\n", __func__);
return -1;
}
buf_bridge->pRead = buf_bridge->pBufBase +
(task_ring_buf->pRead - task_ring_buf->pBufBase);
Ringbuf_Check(task_ring_buf);
Ringbuf_Bridge_Check(buf_bridge);
return 0;
}
int sync_bridge_ringbuf_writeidx(struct ringbuf_bridge *buf_bridge,
struct RingBuf *task_ring_buf)
{
if (task_ring_buf == NULL) {
AUD_LOG_D("%s task_ring_buf == NULL\n", __func__);
return -1;
} else if (buf_bridge == NULL) {
AUD_LOG_D("%s buf_bridge == NULL\n", __func__);
return -1;
}
/* buffer full */
if (buf_bridge->pRead == buf_bridge->pWrite &&
buf_bridge->datacount == buf_bridge->bufLen) {
AUD_LOG_D("%s buffer full\n", __func__);
}
buf_bridge->pWrite = buf_bridge->pBufBase +
(task_ring_buf->pWrite - task_ring_buf->pBufBase);
Ringbuf_Check(task_ring_buf);
Ringbuf_Bridge_Check(buf_bridge);
return 0;
}
void dump_rbuf_bridge(struct ringbuf_bridge *ring_buffer_bridge)
{
if (ring_buffer_bridge == NULL)
return;
#if defined(__linux__)
pr_info("%s pBufBase = 0x%llx pBufEnd = 0x%llx pRead = 0x%llx pWrite = 0x%llx bufLen=%llu readidx = 0x%llx writeidx = 0x%llx\n",
__func__, ring_buffer_bridge->pBufBase,
ring_buffer_bridge->pBufEnd, ring_buffer_bridge->pRead,
ring_buffer_bridge->pWrite, ring_buffer_bridge->bufLen,
(ring_buffer_bridge->pRead - ring_buffer_bridge->pBufBase),
(ring_buffer_bridge->pWrite - ring_buffer_bridge->pBufBase)
);
#else
AUD_LOG_D("%s Base = 0x%llx End = 0x%llx bufLen=%llu\n",
__func__, ring_buffer_bridge->pBufBase,
ring_buffer_bridge->pBufEnd,
ring_buffer_bridge->bufLen
);
AUD_LOG_D("R= 0x%llx W= 0x%llx ridx = %llu widx = %llu\n",
ring_buffer_bridge->pRead,
ring_buffer_bridge->pWrite,
(ring_buffer_bridge->pRead - ring_buffer_bridge->pBufBase),
(ring_buffer_bridge->pWrite - ring_buffer_bridge->pBufBase)
);
#endif
}
void dump_rbuf_bridge_s(const char *appendingstring,
struct ringbuf_bridge *ring_buffer_bridge)
{
if (ring_buffer_bridge == NULL)
return;
#if defined(__linux__)
pr_info("%s %s pBufBase = 0x%llx pBufEnd = 0x%llx pRead = 0x%llx pWrite = 0x%llx bufLen=%llu readidx = 0x%llx writeidx = 0x%llx datacount= %llu\n",
appendingstring, __func__, ring_buffer_bridge->pBufBase,
ring_buffer_bridge->pBufEnd, ring_buffer_bridge->pRead,
ring_buffer_bridge->pWrite, ring_buffer_bridge->bufLen,
(ring_buffer_bridge->pRead - ring_buffer_bridge->pBufBase),
(ring_buffer_bridge->pWrite - ring_buffer_bridge->pBufBase),
ring_buffer_bridge->datacount
);
#else
AUD_LOG_D("%s %s Base = 0x%llx End = 0x%llx bufLen=%llu\n",
appendingstring, __func__, ring_buffer_bridge->pBufBase,
ring_buffer_bridge->pBufEnd,
ring_buffer_bridge->bufLen
);
AUD_LOG_D("R= 0x%x W= 0x%x ridx = 0x%x widx = 0x%x\n",
ring_buffer_bridge->pRead,
ring_buffer_bridge->pWrite,
(ring_buffer_bridge->pRead - ring_buffer_bridge->pBufBase),
(ring_buffer_bridge->pWrite - ring_buffer_bridge->pBufBase)
);
#endif
}
void dump_rbuf(struct RingBuf *ring_buffer)
{
if (ring_buffer == NULL)
return;
#if defined(__linux__)
pr_info("%s Base[%px] End[%px] R[%px] w[%px] Len[%d] count[%d]\n",
__func__,
ring_buffer->pBufBase,
ring_buffer->pBufEnd,
ring_buffer->pRead,
ring_buffer->pWrite,
ring_buffer->bufLen,
ring_buffer->datacount);
#else
AUD_LOG_D("%s Base[%p] End[%p] R[%p] w[%p] Len[%d] count[%d]\n",
__func__,
ring_buffer->pBufBase,
ring_buffer->pBufEnd,
ring_buffer->pRead,
ring_buffer->pWrite,
ring_buffer->bufLen,
ring_buffer->datacount);
#endif
}
void dump_rbuf_s(const char *appendingstring, struct RingBuf *ring_buffer)
{
if (ring_buffer == NULL)
return;
#if defined(__linux__)
pr_info("%s %s Base[%px] End[%px] R[%px] w[%px] Len[%d] count[%d]\n",
appendingstring, __func__,
ring_buffer->pBufBase,
ring_buffer->pBufEnd,
ring_buffer->pRead,
ring_buffer->pWrite,
ring_buffer->bufLen,
ring_buffer->datacount);
#else
AUD_LOG_D("%s %s Base[%p] End[%p] R[%p] w[%p] Len[%d] count[%d]\n",
appendingstring, __func__,
ring_buffer->pBufBase,
ring_buffer->pBufEnd,
ring_buffer->pRead,
ring_buffer->pWrite,
ring_buffer->bufLen,
ring_buffer->datacount);
#endif
}
EXPORT_SYMBOL(dump_rbuf_s);
void dump_buf_attr(struct buf_attr bufattr)
{
AUD_LOG_D("%s format = %d rate = %d channel = %d\n", __func__,
bufattr.format, bufattr.rate, bufattr.channel);
}
void dump_audio_buffer(struct audio_buffer *audio_buf)
{
if (audio_buf == NULL)
return;
AUD_LOG_D(
"%s period_size = %d start_threshold = %d stop_threshold = %d\n",
__func__,
audio_buf->period_size,
audio_buf->start_threshold,
audio_buf->stop_threshold);
dump_rbuf_bridge(&audio_buf->buf_bridge);
dump_buf_attr(audio_buf->buffer_attr);
}
void dump_audio_hwbuffer(struct audio_hw_buffer *audio_hwbuf)
{
if (audio_hwbuf == NULL)
return;
#if defined(__linux__)
pr_info(
"%s hw_buffer = %d audio_memiftype = %d irq_num = %d memory_type = %d",
__func__, audio_hwbuf->hw_buffer,
audio_hwbuf->audio_memiftype,
audio_hwbuf->irq_num,
audio_hwbuf->memory_type);
#else
AUD_LOG_D(
"%s hw_buffer = %d audio_memiftype = %d irq_num = %d memory_type = %d",
__func__, audio_hwbuf->hw_buffer,
audio_hwbuf->audio_memiftype,
audio_hwbuf->irq_num,
audio_hwbuf->memory_type);
#endif
dump_audio_buffer(&audio_hwbuf->aud_buffer);
}
EXPORT_SYMBOL(dump_audio_hwbuffer);
void dump_ring_bufinfo(struct RingBuf *buf)
{
#if defined(__linux__)
pr_info(
"pBufBase = %px pBufEnd = %px pread = %px write = %px DataCount = %u freespace = %u\n",
buf->pBufBase, buf->pBufEnd, buf->pRead, buf->pWrite,
RingBuf_getDataCount(buf), RingBuf_getFreeSpace(buf));
#else
AUD_LOG_D(
"pBufBase = %p pBufEnd = %p pread = %p p write = %p DataCount = %u freespace = %u\n",
buf->pBufBase, buf->pBufEnd, buf->pRead, buf->pWrite,
RingBuf_getDataCount(buf), RingBuf_getFreeSpace(buf));
#endif
}
#ifdef CFG_AUDIO_SUPPORT
int Get_dma_channel_memid(unsigned int mem_id)
{
int dma_id;
switch (mem_id) {
case MP3_MEM_ID:
dma_id = MP3_DMA_ID;
break;
case OPENDSP_MEM_ID:
dma_id = OPENDSP_DMA_ID;
break;
case SMART_PA_MEM_ID:
dma_id = SMART_PA_DMA_ID;
break;
case PLAYBACK_MEM_ID:
dma_id = PLAYBACK_DMA_ID;
break;
case PRIMARY_MEM_ID:
dma_id = PRIMARY_DMA_ID;
break;
case CAPTURE_UL1_MEM_ID:
dma_id = CAPTURE_UL1_DMA_ID;
break;
case DEEPBUFFER_MEM_ID:
dma_id = DEEPBUFFER_DMA_ID;
break;
case VOIP_MEM_ID:
dma_id = VOIP_DMA_ID;
break;
case USB_AUDIO_MEM_ID:
dma_id = USB_AUDIO_DMA_ID;
break;
case EFFECT_MEM_ID:
dma_id = EFFECT_DMA_ID;
break;
default:
AUD_LOG_D("%s not suppoer mem_id %d\n", __func__, mem_id);
dma_id = -1;
break;
}
return dma_id;
}
static int dma_length_fourbyte(unsigned int len, unsigned int dst_addr,
unsigned int src_addr)
{
if (len % 4 || dst_addr % 4 || src_addr % 4)
return 0; /* config can't four byte */
else
return 1;
}
int aud_dma_transaction_wrap(unsigned int dst_addr, unsigned int src_addr,
unsigned int len, uint8_t IsDram, int mem_id)
{
DMA_RESULT ret = 0;
int dma_channel = Get_dma_channel_memid(mem_id);
#ifdef CFG_VCORE_DVFS_SUPPORT
if (IsDram)
dvfs_enable_DRAM_resource(mem_id);
#endif
if (dma_length_fourbyte(len, dst_addr, src_addr) == 0) {
unsigned int need_add = 4 - (dst_addr % 4);
ret = scp_dma_transaction(dst_addr + need_add, src_addr, len,
dma_channel, NO_RESERVED);
memmove((void *)dst_addr, (void *)(dst_addr + need_add), len);
} else
ret = scp_dma_transaction(dst_addr,
src_addr,
len,
dma_channel,
NO_RESERVED);
#ifdef CFG_VCORE_DVFS_SUPPORT
if (IsDram)
dvfs_disable_DRAM_resource(mem_id);
#endif
return ret;
}
static void dma_memcpy(const char *target, const char *source, size_t count,
uint8_t Dramplaystate, int mem_id)
{
if (count == 0 || target == source) { /* nothing to do */
return;
}
if (Dramplaystate == 0) { /* sram */
aud_dma_transaction_wrap((unsigned int)target,
(unsigned int)source, count, false,
mem_id);
} else { /* dram */
aud_dma_transaction_wrap((unsigned int)target,
(unsigned int)source, count, true,
mem_id);
}
}
/**
* copy ring buffer from RingBufs(source) to RingBuft(target) with count
* @param RingBuft ring buffer copy to
* @param RingBufs copy from copy from
*/
int RingBuf_copyFromRingBuf_dma(struct RingBuf *RingBuft,
struct RingBuf *RingBufs, unsigned int count,
uint8_t IsDram, int mem_id)
{
if (count == 0)
return 0;
if ((RingBuf_getDataCount(RingBufs) < count) ||
(RingBuf_getFreeSpace(RingBuft) < count)) {
AUD_LOG_D("Space RingBuft %d || Data RingBufs %d < count %d\n",
RingBuf_getFreeSpace(RingBuft),
RingBuf_getDataCount(RingBufs), count);
return 0;
}
if (RingBufs->pRead <= RingBufs->pWrite) {
RingBuf_copyFromLinear_dma(RingBuft, RingBufs->pRead, count,
IsDram, mem_id);
RingBufs->pRead += count;
if (RingBufs->pRead >= RingBufs->pBufEnd)
RingBufs->pRead -= RingBufs->bufLen;
} else {
unsigned int r2e = RingBufs->pBufEnd - RingBufs->pRead;
if (r2e >= count) {
RingBuf_copyFromLinear_dma(RingBuft, RingBufs->pRead,
count, IsDram, mem_id);
RingBufs->pRead += count;
if (RingBufs->pRead >= RingBufs->pBufEnd)
RingBufs->pRead -= RingBufs->bufLen;
} else {
RingBuf_copyFromLinear_dma(RingBuft, RingBufs->pRead,
r2e, IsDram, mem_id);
RingBuf_copyFromLinear_dma(RingBuft, RingBufs->pBufBase,
count - r2e, IsDram, mem_id);
RingBufs->pRead = RingBufs->pBufBase + count - r2e;
}
}
RingBufs->datacount += count;
Ringbuf_Check(RingBuft);
Ringbuf_Check(RingBufs);
return count;
}
void RingBuf_copyToLinear_dma(char *buf, struct RingBuf *RingBuf1,
unsigned int count, uint8_t IsDram, int mem_id)
{
if (count == 0)
return;
/* if not enough, assert */
/* ASSERT(RingBuf_getDataCount(RingBuf1) >= count); */
if (RingBuf_getDataCount(RingBuf1) < count)
AUD_LOG_D("datacount(RingBuf1) %d < count %d\n",
RingBuf_getDataCount(RingBuf1), count);
if (RingBuf1->pRead <= RingBuf1->pWrite) {
dma_memcpy(buf, RingBuf1->pRead, count, IsDram, mem_id);
RingBuf1->pRead += count;
} else {
unsigned int r2e = RingBuf1->pBufEnd - RingBuf1->pRead;
if (count <= r2e) {
dma_memcpy(buf, RingBuf1->pRead, count, IsDram, mem_id);
RingBuf1->pRead += count;
if (RingBuf1->pRead >= RingBuf1->pBufEnd)
RingBuf1->pRead -= RingBuf1->bufLen;
} else {
dma_memcpy(buf, RingBuf1->pRead, r2e, IsDram, mem_id);
dma_memcpy(buf + r2e, RingBuf1->pBufBase, count - r2e,
IsDram, mem_id);
RingBuf1->pRead = RingBuf1->pBufBase + count - r2e;
}
}
RingBuf1->datacount -= count;
Ringbuf_Check(RingBuf1);
}
/**
* copy ring buffer from RingBufs(source) to RingBuft(target)
* @param RingBuft ring buffer copy to
* @param RingBufs copy from copy from
*/
void RingBuf_copyFromRingBufAll_dma(struct RingBuf *RingBuft,
struct RingBuf *RingBufs, uint8_t IsDram,
int mem_id)
{
/* if not enough, assert */
/* ASSERT(RingBuf_getFreeSpace(RingBuft) >= */
/* RingBuf_getDataCount(RingBufs)); */
if (RingBuf_getFreeSpace(RingBuft) < RingBuf_getDataCount(RingBufs))
AUD_LOG_D(
"RingBuf_getFreeSpace(RingBuft) %d < RingBuf_getDataCount(RingBufs) %d\n",
RingBuf_getFreeSpace(RingBuft),
RingBuf_getDataCount(RingBufs));
if (RingBufs->pRead <= RingBufs->pWrite) {
RingBuf_copyFromLinear_dma(RingBuft, RingBufs->pRead,
RingBufs->pWrite - RingBufs->pRead,
IsDram, mem_id);
} else {
RingBuf_copyFromLinear_dma(RingBuft, RingBufs->pRead,
RingBufs->pBufEnd - RingBufs->pRead,
IsDram, mem_id);
RingBuf_copyFromLinear_dma(
RingBuft, RingBufs->pBufBase,
RingBufs->pWrite - RingBufs->pBufBase, IsDram, mem_id);
}
RingBufs->pRead = RingBufs->pWrite;
Ringbuf_Check(RingBuft);
Ringbuf_Check(RingBufs);
}
void RingBuf_copyFromLinear_dma(struct RingBuf *RingBuf1, const char *buf,
unsigned int count, uint8_t IsDram, int mem_id)
{
int spaceIHave;
char *end = RingBuf1->pBufBase + RingBuf1->bufLen;
/* count buffer data I have */
spaceIHave = RingBuf_getFreeSpace(RingBuf1);
/* if not enough, assert */
/* ASSERT(spaceIHave >= count); */
if (spaceIHave < count) {
AUD_LOG_D("spaceIHave %d < count %d\n", spaceIHave, count);
return;
}
if (RingBuf1->pRead <= RingBuf1->pWrite) {
int w2e = end - RingBuf1->pWrite;
if (count <= w2e) {
dma_memcpy(RingBuf1->pWrite, buf, count, IsDram,
mem_id);
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= end)
RingBuf1->pWrite -= RingBuf1->bufLen;
} else {
dma_memcpy(RingBuf1->pWrite, buf, w2e, IsDram, mem_id);
dma_memcpy(RingBuf1->pBufBase, buf + w2e, count - w2e,
IsDram, mem_id);
RingBuf1->pWrite = RingBuf1->pBufBase + count - w2e;
}
} else {
dma_memcpy(RingBuf1->pWrite, buf, count, IsDram, mem_id);
RingBuf1->pWrite += count;
if (RingBuf1->pWrite >= RingBuf1->pBufEnd)
RingBuf1->pWrite -= RingBuf1->bufLen;
}
RingBuf1->datacount += count;
Ringbuf_Check(RingBuf1);
}
static inline unsigned int get_sram_addr(unsigned int phyAdd)
{
return (phyAdd -
AFE_INTERNAL_SRAM_PHY_BASE +
AFE_INTERNAL_SRAM_MAP_BASE);
}
/* using ringbuf_bridge and map to ringbuf */
int RingBuf_Map_RingBuf_bridge(struct ringbuf_bridge *buf_bridge,
struct RingBuf *pRingBuf)
{
uint64_t phyaddr;
if (buf_bridge == NULL) {
AUD_LOG_D("%s buf_bridge == NULL\n", __func__);
return -1;
}
if (pRingBuf == NULL) {
AUD_LOG_D("%s RingBuf == NULL\n", __func__);
return -1;
}
phyaddr = buf_bridge->pBufBase;
if (phyaddr > 0x20000000)
pRingBuf->pBufBase = (char *)ap_to_scp(phyaddr);
else
pRingBuf->pBufBase = (char *)get_sram_addr((uint32_t)phyaddr);
pRingBuf->bufLen = buf_bridge->bufLen;
pRingBuf->pBufEnd = pRingBuf->pBufBase + pRingBuf->bufLen;
pRingBuf->pRead = pRingBuf->pBufBase;
pRingBuf->pWrite = pRingBuf->pBufBase;
pRingBuf->datacount = buf_bridge->datacount;
return 0;
}
#endif