kernel_samsung_a34x-permissive/sound/soc/mediatek/scp_spk/mtk-scp-spk-mem-control.c

290 lines
8 KiB
C
Raw Permalink Normal View History

// SPDX-License-Identifier: GPL-2.0
//
// Copyright (C) 2018 MediaTek Inc.
#include "mtk-scp-spk-mem-control.h"
#include "mtk-scp-spk-common.h"
#include "mtk-base-afe.h"
#include "mtk-base-scp-spk.h"
#include "mtk-afe-fe-dai.h"
#include "audio_buf.h"
#include <sound/soc.h>
#include <linux/device.h>
#include <linux/compat.h>
#include <linux/io.h>
#include "scp_helper.h"
#include "scp_ipi.h"
#include "audio_ipi_platform.h"
#include "mtk-sram-manager.h"
#include "mtk-scp-spk-platform-mem-control.h"
#include "audio_spkprotect_msg_id.h"
static struct audio_dsp_dram scp_spk_reserved_mem;
static struct audio_dsp_dram scp_spk_iv_tcm_buf;
int mtk_scp_spk_reserved_dram_init(void)
{
struct mtk_base_scp_spk *scp_spk = get_scp_spk_base();
struct audio_dsp_dram *dump_resv_mem =
&scp_spk->spk_dump.dump_resv_mem;
scp_spk_reserved_mem.phy_addr =
scp_get_reserve_mem_phys(SPK_PROTECT_MEM_ID);
scp_spk_reserved_mem.vir_addr =
(unsigned char *)scp_get_reserve_mem_virt(SPK_PROTECT_MEM_ID);
scp_spk_reserved_mem.size =
scp_get_reserve_mem_size(SPK_PROTECT_MEM_ID);
if (!scp_spk_reserved_mem.phy_addr) {
pr_err("%s(), scp_spk_reserved_mem phy_addr error\n");
return -1;
}
if (!scp_spk_reserved_mem.vir_addr) {
pr_err("%s(), scp_spk_reserved_mem vir_addr error\n");
return -1;
}
if (!scp_spk_reserved_mem.size) {
pr_err("%s(), scp_spk_reserved_mem size error\n");
return -1;
}
memset_io((void *)scp_spk_reserved_mem.vir_addr, 0,
scp_spk_reserved_mem.size);
dump_resv_mem->phy_addr =
scp_get_reserve_mem_phys(SPK_PROTECT_DUMP_MEM_ID);
dump_resv_mem->vir_addr =
(unsigned char *)scp_get_reserve_mem_virt
(SPK_PROTECT_DUMP_MEM_ID);
dump_resv_mem->size =
scp_get_reserve_mem_size(SPK_PROTECT_DUMP_MEM_ID);
if (!dump_resv_mem->phy_addr) {
pr_err("%s(), dump_resv_mem phy_addr error\n");
return -1;
}
if (!dump_resv_mem->vir_addr) {
pr_err("%s(), dump_resv_mem vir_addr error\n");
return -1;
}
if (!dump_resv_mem->size) {
pr_err("%s(), dump_resv_mem size error\n");
return -1;
}
memset_io((void *)dump_resv_mem->vir_addr, 0,
dump_resv_mem->size);
dev_info(scp_spk->dev,
"%s(), reserved dram: pa %p, va %p, size 0x%x, reserved dump dram: pa %p, va %p, size 0x%x\n",
__func__,
scp_spk_reserved_mem.phy_addr,
scp_spk_reserved_mem.vir_addr,
scp_spk_reserved_mem.size,
dump_resv_mem->phy_addr,
dump_resv_mem->vir_addr,
dump_resv_mem->size);
return 0;
}
int mtk_scp_spk_allocate_tcm_iv_buf(void)
{
struct mtk_base_scp_spk *scp_spk = get_scp_spk_base();
struct mtk_base_scp_spk_mem *spk_mem = &scp_spk->spk_mem;
struct ipi_msg_t ipi_msg;
int ret = 0;
memset((void *)&ipi_msg, 0, sizeof(struct ipi_msg_t));
ret = audio_send_ipi_msg(&ipi_msg,
TASK_SCENE_SPEAKER_PROTECTION,
AUDIO_IPI_LAYER_TO_DSP,
AUDIO_IPI_MSG_ONLY,
AUDIO_IPI_MSG_NEED_ACK,
SPK_PROTECT_GET_TCM_BUF,
0, 0, NULL);
if (ret < 0) {
dev_err(scp_spk->dev, "%s(), send error:%d\n",
__func__, ret);
return -1;
}
if (ipi_msg.param1) {
scp_spk_iv_tcm_buf.phy_addr =
SCP_TCM_PHY_ADDR + ipi_msg.param1;
scp_spk_iv_tcm_buf.vir_addr =
(unsigned char *)(SCP_TCM + ipi_msg.param1);
scp_spk_iv_tcm_buf.size = ipi_msg.param2;
dev_info(scp_spk->dev,
"%s(), spk tcm iv pa:0x%x, va:0x%x, bytes:%d, SCP_TCM:0x%x, ipi_msg.param1:0x%x\n",
__func__,
scp_spk_iv_tcm_buf.phy_addr,
scp_spk_iv_tcm_buf.vir_addr,
scp_spk_iv_tcm_buf.size, SCP_TCM, ipi_msg.param1);
spk_mem->is_iv_buf_in_tcm = true;
} else {
dev_info(scp_spk->dev,
"%s(), not support\n", __func__);
spk_mem->is_iv_buf_in_tcm = false;
}
return 0;
}
int mtk_scp_spk_free_mem(struct snd_pcm_substream *substream,
struct mtk_base_afe *afe)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
int id = rtd->cpu_dai->id;
struct mtk_base_afe_memif *memif = &afe->memif[id];
struct mtk_base_scp_spk *scp_spk = get_scp_spk_base();
struct mtk_base_scp_spk_mem *spk_mem = &scp_spk->spk_mem;
dev_info(scp_spk->dev, "%s(), %s\n", __func__, memif->data->name);
if (id == get_scp_spk_memif_id(SCP_SPK_DL_DAI_ID)) {
spk_mem->spk_dl_memif_id = -1;
reset_audio_dma_buf(&spk_mem->spk_dl_dma_buf);
} else if (id == get_scp_spk_memif_id(SCP_SPK_IV_DAI_ID)) {
spk_mem->spk_iv_memif_id = -1;
reset_audio_dma_buf(&spk_mem->spk_iv_dma_buf);
} else if (id == get_scp_spk_memif_id(SCP_SPK_MDUL_DAI_ID)) {
spk_mem->spk_md_ul_memif_id = -1;
reset_audio_dma_buf(&spk_mem->spk_md_ul_dma_buf);
} else {
dev_err(scp_spk->dev, "%s(), wrong memif id\n");
return -EINVAL;
}
if (memif->using_sram) {
memif->using_sram = 0;
mtk_audio_sram_free(afe->sram, substream);
} else {
if (afe->release_dram_resource)
afe->release_dram_resource(afe->dev);
}
return 0;
}
EXPORT_SYMBOL_GPL(mtk_scp_spk_free_mem);
void mtk_scp_spk_allocate_platform_buf(unsigned int size,
dma_addr_t *phys_addr,
unsigned char **virt_addr)
{
struct mtk_base_scp_spk *scp_spk = get_scp_spk_base();
struct mtk_base_scp_spk_mem *spk_mem = &scp_spk->spk_mem;
spk_mem->platform_dma_buf.addr = scp_spk_reserved_mem.phy_addr;
spk_mem->platform_dma_buf.area = scp_spk_reserved_mem.vir_addr;
spk_mem->platform_dma_buf.bytes = size;
memset_io(spk_mem->platform_dma_buf.area, 0,
spk_mem->platform_dma_buf.bytes);
*phys_addr = spk_mem->platform_dma_buf.addr;
*virt_addr = spk_mem->platform_dma_buf.area;
dev_info(scp_spk->dev,
"%s(), spk platform VA:0x%p, PA:0x%lx, size:%d\n",
__func__,
spk_mem->platform_dma_buf.area,
spk_mem->platform_dma_buf.addr,
spk_mem->platform_dma_buf.bytes);
}
int mtk_scp_spk_allocate_mem(struct snd_pcm_substream *substream,
dma_addr_t *phys_addr, unsigned char **virt_addr,
unsigned int size,
snd_pcm_format_t format,
struct mtk_base_afe *afe)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct mtk_base_scp_spk *scp_spk = get_scp_spk_base();
struct mtk_base_scp_spk_mem *spk_mem = &scp_spk->spk_mem;
int id = rtd->cpu_dai->id;
struct mtk_base_afe_memif *memif = &afe->memif[id];
struct snd_dma_buffer *spk_dma_buf = NULL;
int buf_offset;
int ret;
if (id == get_scp_spk_memif_id(SCP_SPK_DL_DAI_ID)) {
spk_dma_buf = &spk_mem->spk_dl_dma_buf;
spk_mem->spk_dl_memif_id = id;
buf_offset = SPK_BUF_OFFSET;
} else if (id == get_scp_spk_memif_id(SCP_SPK_IV_DAI_ID)) {
spk_dma_buf = &spk_mem->spk_iv_dma_buf;
spk_mem->spk_iv_memif_id = id;
buf_offset = SPK_BUF_OFFSET * 2;
} else if (id == get_scp_spk_memif_id(SCP_SPK_MDUL_DAI_ID)) {
spk_dma_buf = &spk_mem->spk_md_ul_dma_buf;
spk_mem->spk_md_ul_memif_id = id;
buf_offset = 0;
} else {
dev_err(scp_spk->dev, "%s(), wrong memif id\n");
return -EINVAL;
}
spk_dma_buf->bytes = size;
if (mtk_audio_sram_allocate(afe->sram,
&spk_dma_buf->addr,
&spk_dma_buf->area,
spk_dma_buf->bytes,
substream,
format, false) == 0) {
memif->using_sram = 1;
} else {
memif->using_sram = 0;
if (id == get_scp_spk_memif_id(SCP_SPK_IV_DAI_ID) &&
spk_mem->is_iv_buf_in_tcm) {
spk_dma_buf->addr =
scp_spk_iv_tcm_buf.phy_addr;
spk_dma_buf->area =
scp_spk_iv_tcm_buf.vir_addr;
spk_dma_buf->bytes =
scp_spk_iv_tcm_buf.size;
goto BYPASS_RSVED_MEM_ALLOCATE;
}
spk_dma_buf->addr =
scp_spk_reserved_mem.phy_addr + buf_offset;
spk_dma_buf->area =
scp_spk_reserved_mem.vir_addr + buf_offset;
}
memset_io(spk_dma_buf->area, 0, spk_dma_buf->bytes);
BYPASS_RSVED_MEM_ALLOCATE:
/* set memif addr */
ret = mtk_memif_set_addr(afe, id,
spk_dma_buf->area,
spk_dma_buf->addr,
spk_dma_buf->bytes);
if (ret) {
dev_err(afe->dev, "%s(), error, id %d, set addr, ret %d\n",
__func__, id, ret);
return ret;
}
dev_info(scp_spk->dev,
"%s(), %s, spk VA:0x%p, spk PA:0x%lx, size:%d, iv buf in tcm:%d\n",
__func__, memif->data->name,
spk_dma_buf->area,
spk_dma_buf->addr,
spk_dma_buf->bytes,
spk_mem->is_iv_buf_in_tcm);
if (memif->using_sram == 0 && afe->request_dram_resource)
afe->request_dram_resource(afe->dev);
return 0;
}
EXPORT_SYMBOL_GPL(mtk_scp_spk_allocate_mem);