kernel_samsung_a34x-permissive/sound/soc/mediatek/common/mtk-mmap-ion.c

200 lines
4.2 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0
//
// mtk-mmap-ion.c -- Mediatek Audio MMAP Get ION Buffer
//
// Copyright (c) 2017 MediaTek Inc.
// Author: Kai Chieh Chuang <kaichieh.chuang@mediatek.com>
#include <linux/io.h>
#include <linux/module.h>
#include "mtk-mmap-ion.h"
#include "ion_drv.h"
#include "ion_priv.h"
#include "ion.h"
#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT)
static struct ion_client *ion_client;
static struct ion_handle *dl_ion_handle;
static struct ion_handle *ul_ion_handle;
static unsigned long dl_phy_addr;
static unsigned long ul_phy_addr;
static void *dl_vir_addr;
static void *ul_vir_addr;
static size_t dl_size;
static size_t ul_size;
static int dl_fd;
static int ul_fd;
int mtk_free_ion_buffer(struct ion_handle *handle, int *fd,
unsigned long *phy_addr, void **vir_addr,
size_t *size)
{
pr_debug("+%s()\n", __func__);
if (*vir_addr != NULL && handle != NULL)
ion_unmap_kernel(ion_client, handle);
if (handle != NULL)
ion_free(ion_client, handle);
handle = NULL;
*vir_addr = NULL;
*fd = 0;
*phy_addr = 0;
*size = 0;
pr_debug("-%s()\n", __func__);
return 0;
}
int mtk_alloc_ion_buffer(struct ion_handle *handle, int *fd,
unsigned long *phy_addr, void **vir_addr,
size_t *size)
{
int ret = 0;
pr_debug("+%s()\n", __func__);
// alloc handler
pr_debug("%s(), ion_alloc\n", __func__);
handle = ion_alloc(ion_client, MMAP_BUFFER_SIZE, 0,
ION_HEAP_CARVEOUT_MASK, 0);
if (IS_ERR(handle)) {
pr_debug("%s, DL ion_alloc fail %p\n", __func__, handle);
handle = NULL;
goto exit;
}
// get physical addr & size
pr_debug("%s(), ion_phys\n", __func__);
ret = ion_phys(ion_client, handle, phy_addr, size);
if (ret != 0) {
pr_debug("%s, ion_phys fail, ret %d\n", __func__, ret);
goto exit;
}
// get fd
pr_debug("%s(), ion_share_dma_buf_fd\n", __func__);
*fd = ion_share_dma_buf_fd(ion_client, handle);
if (*fd <= 0) {
pr_debug("ion_share_dma_buf_fd fail, fd %d\n", *fd);
goto exit;
}
// get virtual addr
pr_debug("%s(), ion_map_kernel\n", __func__);
*vir_addr = ion_map_kernel(ion_client, handle);
if (*vir_addr == NULL) {
pr_debug("%s, ion_map_kernel fail\n", __func__);
goto exit;
}
pr_debug("-%s(), handle %p, addr %p, phy_addr %ld, size %zu, fd %d\n",
__func__, handle, *vir_addr, *phy_addr, *size, *fd);
return 0;
exit:
mtk_free_ion_buffer(handle, fd, phy_addr, vir_addr, size);
pr_debug("-%s(), fail\n", __func__);
return -1;
}
int mtk_get_ion_buffer(void)
{
int ret;
pr_debug("+%s()\n", __func__);
if (ion_client != NULL) {
pr_debug("mtk_get_ion free+\n");
mtk_free_ion_buffer(dl_ion_handle, &dl_fd, &dl_phy_addr,
&dl_vir_addr, &dl_size);
mtk_free_ion_buffer(ul_ion_handle, &ul_fd, &ul_phy_addr,
&ul_vir_addr, &ul_size);
ion_client_destroy(ion_client);
ion_client = NULL;
pr_debug("mtk_get_ion free-\n");
}
// create client
ion_client = ion_client_create(g_ion_device, "AAudioMMAP");
if (PTR_RET(ion_client) != 0) {
pr_debug("%s, ion_client_create fail, device %p, client %p\n",
__func__, g_ion_device, ion_client);
goto exit;
}
pr_debug("+%s(), mtk_alloc_ion_buffer for DL\n", __func__);
ret = mtk_alloc_ion_buffer(dl_ion_handle, &dl_fd, &dl_phy_addr,
&dl_vir_addr, &dl_size);
if (ret != 0)
goto exit;
pr_debug("+%s(), mtk_alloc_ion_buffer for UL\n", __func__);
ret = mtk_alloc_ion_buffer(ul_ion_handle, &ul_fd, &ul_phy_addr,
&ul_vir_addr, &ul_size);
if (ret != 0) {
mtk_free_ion_buffer(dl_ion_handle, &dl_fd, &dl_phy_addr,
&dl_vir_addr, &dl_size);
goto exit;
}
pr_debug("-%s()\n", __func__);
return 0;
exit:
if (ion_client != NULL) {
ion_client_destroy(ion_client);
ion_client = NULL;
}
pr_debug("-%s(), fail\n", __func__);
return -1;
}
int mtk_get_mmap_dl_fd(void)
{
return dl_fd;
}
int mtk_get_mmap_ul_fd(void)
{
return ul_fd;
}
void mtk_get_mmap_dl_buffer(unsigned long *phy_addr, void **vir_addr)
{
*phy_addr = dl_phy_addr;
*vir_addr = dl_vir_addr;
}
void mtk_get_mmap_ul_buffer(unsigned long *phy_addr, void **vir_addr)
{
*phy_addr = ul_phy_addr;
*vir_addr = ul_vir_addr;
}
MODULE_DESCRIPTION("Mediatek Smart Phone PCM Operation");
MODULE_AUTHOR("Kai Chieh Chuang <kaichieh.chuang@mediatek.com>");
MODULE_LICENSE("GPL v2");