mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
gdc: add a convert function to map dma address [1/1]
PD#SWPL-2157 Problem: gdc module need to get dma address directly Solution: add a convert function to map dma address Verify: g12b Change-Id: I1d40350e4727335d1f69f38caafb1dfe7b0db842 Signed-off-by: Keke Li <keke.li@amlogic.com>
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dma-contiguous.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
#include <linux/of_address.h>
|
||||
#include <api/gdc_api.h>
|
||||
@@ -273,6 +273,216 @@ static void meson_gdc_cache_flush(struct device *dev,
|
||||
dma_sync_single_for_cpu(dev, addr, size, DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
static long meson_gdc_dma_map(struct gdc_dma_cfg *cfg)
|
||||
{
|
||||
long ret = -1;
|
||||
int fd = -1;
|
||||
struct dma_buf *dbuf = NULL;
|
||||
struct dma_buf_attachment *d_att = NULL;
|
||||
struct sg_table *sg = NULL;
|
||||
void *vaddr = NULL;
|
||||
struct device *dev = NULL;
|
||||
enum dma_data_direction dir;
|
||||
|
||||
if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL) {
|
||||
LOG(LOG_ERR, "Error input param");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fd = cfg->fd;
|
||||
dev = cfg->dev;
|
||||
dir = cfg->dir;
|
||||
|
||||
dbuf = dma_buf_get(fd);
|
||||
if (dbuf == NULL) {
|
||||
LOG(LOG_ERR, "Failed to get dma buffer");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
d_att = dma_buf_attach(dbuf, dev);
|
||||
if (d_att == NULL) {
|
||||
LOG(LOG_ERR, "Failed to set dma attach");
|
||||
goto attach_err;
|
||||
}
|
||||
|
||||
sg = dma_buf_map_attachment(d_att, dir);
|
||||
if (sg == NULL) {
|
||||
LOG(LOG_ERR, "Failed to get dma sg");
|
||||
goto map_attach_err;
|
||||
}
|
||||
|
||||
ret = dma_buf_begin_cpu_access(dbuf, dir);
|
||||
if (ret != 0) {
|
||||
LOG(LOG_ERR, "Failed to access dma buff");
|
||||
goto access_err;
|
||||
}
|
||||
|
||||
vaddr = dma_buf_vmap(dbuf);
|
||||
if (vaddr == NULL) {
|
||||
LOG(LOG_ERR, "Failed to vmap dma buf");
|
||||
goto vmap_err;
|
||||
}
|
||||
|
||||
cfg->dbuf = dbuf;
|
||||
cfg->attach = d_att;
|
||||
cfg->vaddr = vaddr;
|
||||
cfg->sg = sg;
|
||||
|
||||
return ret;
|
||||
|
||||
vmap_err:
|
||||
dma_buf_end_cpu_access(dbuf, dir);
|
||||
|
||||
access_err:
|
||||
dma_buf_unmap_attachment(d_att, sg, dir);
|
||||
|
||||
map_attach_err:
|
||||
dma_buf_detach(dbuf, d_att);
|
||||
|
||||
attach_err:
|
||||
dma_buf_put(dbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void meson_gdc_dma_unmap(struct gdc_dma_cfg *cfg)
|
||||
{
|
||||
int fd = -1;
|
||||
struct dma_buf *dbuf = NULL;
|
||||
struct dma_buf_attachment *d_att = NULL;
|
||||
struct sg_table *sg = NULL;
|
||||
void *vaddr = NULL;
|
||||
struct device *dev = NULL;
|
||||
enum dma_data_direction dir;
|
||||
|
||||
if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL
|
||||
|| cfg->dbuf == NULL || cfg->vaddr == NULL
|
||||
|| cfg->attach == NULL || cfg->sg == NULL) {
|
||||
LOG(LOG_ERR, "Error input param");
|
||||
return;
|
||||
}
|
||||
|
||||
fd = cfg->fd;
|
||||
dev = cfg->dev;
|
||||
dir = cfg->dir;
|
||||
dbuf = cfg->dbuf;
|
||||
vaddr = cfg->vaddr;
|
||||
d_att = cfg->attach;
|
||||
sg = cfg->sg;
|
||||
|
||||
dma_buf_vunmap(dbuf, vaddr);
|
||||
|
||||
dma_buf_end_cpu_access(dbuf, dir);
|
||||
|
||||
dma_buf_unmap_attachment(d_att, sg, dir);
|
||||
|
||||
dma_buf_detach(dbuf, d_att);
|
||||
|
||||
dma_buf_put(dbuf);
|
||||
}
|
||||
|
||||
static long meson_gdc_init_dma_addr(struct gdc_settings *gs)
|
||||
{
|
||||
long ret = -1;
|
||||
struct gdc_dma_cfg *dma_cfg = NULL;
|
||||
struct gdc_config *gc = NULL;
|
||||
struct mgdc_fh_s *fh = NULL;
|
||||
|
||||
if (gs == NULL || gs->fh == NULL) {
|
||||
LOG(LOG_ERR, "Error input param\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gc = &gs->gdc_config;
|
||||
fh = gs->fh;
|
||||
|
||||
switch (gc->format) {
|
||||
case NV12:
|
||||
dma_cfg = &fh->y_dma_cfg;
|
||||
memset(dma_cfg, 0, sizeof(*dma_cfg));
|
||||
dma_cfg->dir = DMA_TO_DEVICE;
|
||||
dma_cfg->dev = &fh->gdev->pdev->dev;
|
||||
dma_cfg->fd = gs->y_base_fd;
|
||||
|
||||
ret = meson_gdc_dma_map(dma_cfg);
|
||||
if (ret != 0) {
|
||||
LOG(LOG_ERR, "Failed to get map dma buff");
|
||||
return ret;
|
||||
}
|
||||
|
||||
gs->y_base_addr = virt_to_phys(dma_cfg->vaddr);
|
||||
|
||||
dma_cfg = &fh->uv_dma_cfg;
|
||||
memset(dma_cfg, 0, sizeof(*dma_cfg));
|
||||
dma_cfg->dir = DMA_TO_DEVICE;
|
||||
dma_cfg->dev = &fh->gdev->pdev->dev;
|
||||
dma_cfg->fd = gs->uv_base_fd;
|
||||
|
||||
ret = meson_gdc_dma_map(dma_cfg);
|
||||
if (ret != 0) {
|
||||
LOG(LOG_ERR, "Failed to get map dma buff");
|
||||
return ret;
|
||||
}
|
||||
|
||||
gs->uv_base_addr = virt_to_phys(dma_cfg->vaddr);
|
||||
break;
|
||||
case Y_GREY:
|
||||
dma_cfg = &fh->y_dma_cfg;
|
||||
memset(dma_cfg, 0, sizeof(*dma_cfg));
|
||||
dma_cfg->dir = DMA_TO_DEVICE;
|
||||
dma_cfg->dev = &fh->gdev->pdev->dev;
|
||||
dma_cfg->fd = gs->y_base_fd;
|
||||
|
||||
ret = meson_gdc_dma_map(dma_cfg);
|
||||
if (ret != 0) {
|
||||
LOG(LOG_ERR, "Failed to get map dma buff");
|
||||
return ret;
|
||||
}
|
||||
|
||||
gs->y_base_addr = virt_to_phys(dma_cfg->vaddr);
|
||||
gs->uv_base_addr = 0;
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_ERR, "Error image format");
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void meson_gdc_deinit_dma_addr(struct gdc_settings *gs)
|
||||
{
|
||||
struct gdc_dma_cfg *dma_cfg = NULL;
|
||||
struct gdc_config *gc = NULL;
|
||||
struct mgdc_fh_s *fh = NULL;
|
||||
|
||||
if (gs == NULL || gs->fh == NULL) {
|
||||
LOG(LOG_ERR, "Error input param\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gc = &gs->gdc_config;
|
||||
fh = gs->fh;
|
||||
|
||||
switch (gc->format) {
|
||||
case NV12:
|
||||
dma_cfg = &fh->y_dma_cfg;
|
||||
meson_gdc_dma_unmap(dma_cfg);
|
||||
|
||||
dma_cfg = &fh->uv_dma_cfg;
|
||||
meson_gdc_dma_unmap(dma_cfg);
|
||||
break;
|
||||
case Y_GREY:
|
||||
dma_cfg = &fh->y_dma_cfg;
|
||||
meson_gdc_dma_unmap(dma_cfg);
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_ERR, "Error image format");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static long meson_gdc_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
@@ -404,6 +614,12 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd,
|
||||
gs->fh = fh;
|
||||
|
||||
mutex_lock(&fh->gdev->d_mutext);
|
||||
ret = meson_gdc_init_dma_addr(gs);
|
||||
if (ret != 0) {
|
||||
mutex_unlock(&fh->gdev->d_mutext);
|
||||
LOG(LOG_ERR, "Failed to init dma addr");
|
||||
return ret;
|
||||
}
|
||||
meson_gdc_dma_flush(&fh->gdev->pdev->dev,
|
||||
fh->c_paddr, fh->c_len);
|
||||
ret = gdc_run(gs);
|
||||
@@ -418,6 +634,7 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd,
|
||||
gdc_stop(gs);
|
||||
meson_gdc_cache_flush(&fh->gdev->pdev->dev,
|
||||
fh->o_paddr, fh->o_len);
|
||||
meson_gdc_deinit_dma_addr(gs);
|
||||
mutex_unlock(&fh->gdev->d_mutext);
|
||||
break;
|
||||
case GDC_REQUEST_BUFF:
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define __GDC_API_H__
|
||||
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/dma-direction.h>
|
||||
|
||||
struct gdc_buf_cfg {
|
||||
uint32_t type;
|
||||
@@ -79,6 +80,12 @@ struct gdc_settings {
|
||||
uint32_t y_line_offset,
|
||||
uint32_t uv_line_offset);
|
||||
void *fh;
|
||||
int32_t y_base_fd;
|
||||
union {
|
||||
int32_t uv_base_fd;
|
||||
int32_t u_base_fd;
|
||||
};
|
||||
int32_t v_base_fd;
|
||||
};
|
||||
|
||||
#define GDC_IOC_MAGIC 'G'
|
||||
@@ -104,6 +111,16 @@ enum {
|
||||
FMT_MAX
|
||||
};
|
||||
|
||||
struct gdc_dma_cfg {
|
||||
int fd;
|
||||
void *dev;
|
||||
void *vaddr;
|
||||
struct dma_buf *dbuf;
|
||||
struct dma_buf_attachment *attach;
|
||||
struct sg_table *sg;
|
||||
enum dma_data_direction dir;
|
||||
};
|
||||
|
||||
/**
|
||||
* Configure the output gdc configuration
|
||||
*
|
||||
|
||||
@@ -54,6 +54,8 @@ struct mgdc_fh_s {
|
||||
unsigned long i_len;
|
||||
unsigned long o_len;
|
||||
unsigned long c_len;
|
||||
struct gdc_dma_cfg y_dma_cfg;
|
||||
struct gdc_dma_cfg uv_dma_cfg;
|
||||
};
|
||||
|
||||
irqreturn_t interrupt_handler_next(int irq, void *param);
|
||||
|
||||
Reference in New Issue
Block a user