mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
ge2d: add ioctl to attach/detach [1/1]
PD#SWPL-33277 Problem: reduce cache invalidate actions while doing bulk actions to improve the performance Solution: add ioctl to attach/detach dma fd Verify: on sm1/w400 Change-Id: Iea8fae9e483ff70044da748c78d8641c52a0c65d Signed-off-by: Cao Jian <jian.cao@amlogic.com> Signed-off-by: chunlong.cao <chunlong.cao@amlogic.com>
This commit is contained in:
@@ -626,32 +626,11 @@ int ge2d_dma_buffer_get_phys(struct aml_dma_buffer *buffer,
|
||||
dma_sync_sg_for_cpu(cfg->dev, sg_table->sgl,
|
||||
sg_table->nents, cfg->dir);
|
||||
}
|
||||
ge2d_dma_buffer_unmap(cfg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ge2d_dma_buffer_unmap_info(struct aml_dma_buffer *buffer,
|
||||
struct aml_dma_cfg *cfg)
|
||||
{
|
||||
int i, found = 0;
|
||||
|
||||
if (cfg == NULL || (cfg->fd < 0)) {
|
||||
pr_err("%s: error input param\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < AML_MAX_DMABUF; i++) {
|
||||
if (buffer->gd_buffer[i].alloc) {
|
||||
if (cfg->dbuf == buffer->gd_buffer[i].dbuf) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
ge2d_dma_buffer_unmap(cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg)
|
||||
{
|
||||
int fd = -1;
|
||||
|
||||
@@ -78,8 +78,10 @@ int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg);
|
||||
void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg);
|
||||
int ge2d_dma_buffer_get_phys(struct aml_dma_buffer *buffer,
|
||||
struct aml_dma_cfg *cfg, unsigned long *addr);
|
||||
int ge2d_dma_buffer_unmap_info(struct aml_dma_buffer *buffer,
|
||||
struct aml_dma_cfg *cfg);
|
||||
void ge2d_dma_buffer_dma_flush(struct device *dev, int fd);
|
||||
void ge2d_dma_buffer_cache_flush(struct device *dev, int fd);
|
||||
int ge2d_ioctl_attach_dma_fd(struct ge2d_context_s *wq,
|
||||
struct ge2d_dmabuf_attach_s *dma_attach);
|
||||
void ge2d_ioctl_detach_dma_fd(struct ge2d_context_s *wq,
|
||||
enum ge2d_data_type_e data_type);
|
||||
#endif
|
||||
|
||||
@@ -219,6 +219,7 @@ static ssize_t log_level_store(struct class *cla,
|
||||
static int ge2d_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ge2d_context_s *context = NULL;
|
||||
int i;
|
||||
|
||||
/* we create one ge2d workqueue for this file handler. */
|
||||
context = create_ge2d_work_queue();
|
||||
@@ -226,6 +227,14 @@ static int ge2d_open(struct inode *inode, struct file *file)
|
||||
ge2d_log_err("can't create work queue\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* reset dms_used flag */
|
||||
for (i = 0; i < MAX_PLANE; i++) {
|
||||
context->config.src_dma_cfg[i].dma_used[i] = 0;
|
||||
context->config.src2_dma_cfg[i].dma_used[i] = 0;
|
||||
context->config.dst_dma_cfg[i].dma_used[i] = 0;
|
||||
}
|
||||
|
||||
file->private_data = context;
|
||||
atomic_inc(&ge2d_device.open_count);
|
||||
|
||||
@@ -447,6 +456,8 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
#endif
|
||||
int cap_mask = 0;
|
||||
int index = 0, dma_fd;
|
||||
enum ge2d_data_type_e data_type;
|
||||
struct ge2d_dmabuf_attach_s attatch;
|
||||
void __user *argp = (void __user *)args;
|
||||
|
||||
context = (struct ge2d_context_s *)filp->private_data;
|
||||
@@ -794,6 +805,22 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case GE2D_ATTACH_DMA_FD:
|
||||
ret = copy_from_user(&attatch, argp,
|
||||
sizeof(struct ge2d_dmabuf_attach_s));
|
||||
if (ret < 0) {
|
||||
pr_err("Error user param\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case GE2D_DETACH_DMA_FD:
|
||||
ret = copy_from_user(&data_type, argp,
|
||||
sizeof(enum ge2d_data_type_e));
|
||||
if (ret < 0) {
|
||||
pr_err("Error user param\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case GE2D_CONFIG_OLD:
|
||||
case GE2D_CONFIG_EX_OLD:
|
||||
case GE2D_SRCCOLORKEY_OLD:
|
||||
@@ -1027,6 +1054,12 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
case GE2D_SYNC_CPU:
|
||||
ge2d_buffer_cache_flush(dma_fd);
|
||||
break;
|
||||
case GE2D_ATTACH_DMA_FD:
|
||||
ge2d_ioctl_attach_dma_fd(context, &attatch);
|
||||
break;
|
||||
case GE2D_DETACH_DMA_FD:
|
||||
ge2d_ioctl_detach_dma_fd(context, data_type);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -124,7 +124,6 @@ static const int default_ge2d_color_lut[] = {
|
||||
|
||||
static int ge2d_buffer_get_phys(struct aml_dma_cfg *cfg,
|
||||
unsigned long *addr);
|
||||
static int ge2d_buffer_unmap(struct aml_dma_cfg *cfg);
|
||||
|
||||
static void ge2d_pre_init(void)
|
||||
{
|
||||
@@ -386,7 +385,7 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq)
|
||||
struct ge2d_queue_item_s *pitem;
|
||||
unsigned int mask = 0x1;
|
||||
struct list_head *head = &wq->work_queue, *pos;
|
||||
int ret = 0, i = 0;
|
||||
int ret = 0;
|
||||
unsigned int block_mode;
|
||||
int timeout = 0;
|
||||
|
||||
@@ -418,6 +417,10 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* do power on/off every process, all setting should be updated */
|
||||
if (ge2d_meson_dev.has_self_pwr)
|
||||
pitem->config.update_flag = UPDATE_ALL;
|
||||
|
||||
do {
|
||||
cfg = &pitem->config;
|
||||
ge2d_log_dbg("secure mode:%d\n", cfg->mem_sec);
|
||||
@@ -479,27 +482,6 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq)
|
||||
pos = pos->next;
|
||||
list_move_tail(&pitem->list, &wq->free_queue);
|
||||
spin_unlock(&wq->lock);
|
||||
/* if dma buf detach it */
|
||||
for (i = 0; i < MAX_PLANE; i++) {
|
||||
if (pitem->config.src_dma_cfg[i].dma_used) {
|
||||
ge2d_buffer_unmap((struct aml_dma_cfg *
|
||||
)pitem->config.src_dma_cfg[i].dma_cfg);
|
||||
pitem->config.src_dma_cfg[i].dma_used = 0;
|
||||
kfree(pitem->config.src_dma_cfg[i].dma_cfg);
|
||||
}
|
||||
if (pitem->config.src2_dma_cfg[i].dma_used) {
|
||||
ge2d_buffer_unmap((struct aml_dma_cfg *
|
||||
)pitem->config.src2_dma_cfg[i].dma_cfg);
|
||||
pitem->config.src2_dma_cfg[i].dma_used = 0;
|
||||
kfree(pitem->config.src2_dma_cfg[i].dma_cfg);
|
||||
}
|
||||
if (pitem->config.dst_dma_cfg[i].dma_used) {
|
||||
ge2d_buffer_unmap((struct aml_dma_cfg *
|
||||
)pitem->config.dst_dma_cfg[i].dma_cfg);
|
||||
pitem->config.dst_dma_cfg[i].dma_used = 0;
|
||||
kfree(pitem->config.dst_dma_cfg[i].dma_cfg);
|
||||
}
|
||||
}
|
||||
/* if block mode (cmd) */
|
||||
if (block_mode) {
|
||||
pitem->cmd.wait_done_flag = 0;
|
||||
@@ -552,7 +534,7 @@ struct ge2d_canvas_cfg_s *ge2d_wq_get_canvas_cfg(struct ge2d_context_s *wq,
|
||||
canvas_cfg = &wq->config.dst_canvas_cfg[plane_id];
|
||||
break;
|
||||
default:
|
||||
ge2d_log_err("wrong data_type\n");
|
||||
ge2d_log_err("%s, wrong data_type\n", __func__);
|
||||
break;
|
||||
}
|
||||
return canvas_cfg;
|
||||
@@ -575,7 +557,7 @@ struct ge2d_dma_cfg_s *ge2d_wq_get_dma_cfg(struct ge2d_context_s *wq,
|
||||
dma_cfg = &wq->config.dst_dma_cfg[plane_id];
|
||||
break;
|
||||
default:
|
||||
ge2d_log_err("wrong data_type\n");
|
||||
ge2d_log_err("%s, wrong data_type\n", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1105,14 +1087,13 @@ static int build_ge2d_addr_config_dma(
|
||||
ge2d_log_dbg("build_ge2d_addr_config_dma bpp_value=%d\n",
|
||||
bpp_value);
|
||||
if (plane) {
|
||||
if (plane[0].shared_fd) {
|
||||
if (plane[0].shared_fd > 0) {
|
||||
struct ge2d_dma_cfg_s *cfg = NULL;
|
||||
struct aml_dma_cfg *dma_cfg = NULL;
|
||||
|
||||
cfg = ge2d_wq_get_dma_cfg(context, data_type, 0);
|
||||
if (!cfg)
|
||||
return -1;
|
||||
cfg->dma_used = 1;
|
||||
dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL);
|
||||
dma_cfg->fd = plane[0].shared_fd;
|
||||
dma_cfg->dev = &(ge2d_manager.pdev->dev);
|
||||
@@ -1121,8 +1102,25 @@ static int build_ge2d_addr_config_dma(
|
||||
ret = ge2d_buffer_get_phys(dma_cfg, &addr_temp);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
kfree(dma_cfg);
|
||||
plane[0].addr += addr_temp;
|
||||
} else if (plane[0].shared_fd == DMA_FD_ATTACHED) {
|
||||
struct ge2d_dma_cfg_s *cfg = NULL;
|
||||
struct aml_dma_cfg *dma_cfg = NULL;
|
||||
|
||||
cfg = ge2d_wq_get_dma_cfg(context, data_type, 0);
|
||||
if (!cfg)
|
||||
return -1;
|
||||
if (!cfg->dma_cfg) {
|
||||
ge2d_log_err("%s, dma_cfg is null\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dma_cfg = (struct aml_dma_cfg *)cfg->dma_cfg;
|
||||
plane[0].addr += sg_phys(dma_cfg->sg->sgl);
|
||||
}
|
||||
plane[0].addr += addr_temp;
|
||||
|
||||
if (plane[0].addr) {
|
||||
*addr = plane[0].addr;
|
||||
*stride = plane[0].w * bpp_value;
|
||||
@@ -1234,7 +1232,7 @@ static int build_ge2d_config_ex_dma(struct ge2d_context_s *context,
|
||||
for (i = 0; i < MAX_PLANE; i++) {
|
||||
/* multi-src_planes */
|
||||
canvas_set = 0;
|
||||
if (plane[i].shared_fd) {
|
||||
if (plane[i].shared_fd > 0) {
|
||||
struct ge2d_dma_cfg_s *cfg = NULL;
|
||||
struct aml_dma_cfg *dma_cfg = NULL;
|
||||
|
||||
@@ -1242,7 +1240,6 @@ static int build_ge2d_config_ex_dma(struct ge2d_context_s *context,
|
||||
data_type, i);
|
||||
if (!cfg)
|
||||
return -1;
|
||||
cfg->dma_used = 1;
|
||||
dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL);
|
||||
if (!dma_cfg)
|
||||
return ret;
|
||||
@@ -1253,8 +1250,27 @@ static int build_ge2d_config_ex_dma(struct ge2d_context_s *context,
|
||||
ret = ge2d_buffer_get_phys(dma_cfg, &addr);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
kfree(dma_cfg);
|
||||
plane[i].addr = addr;
|
||||
canvas_set = 1;
|
||||
} else if (plane[i].shared_fd == DMA_FD_ATTACHED) {
|
||||
struct ge2d_dma_cfg_s *cfg = NULL;
|
||||
struct aml_dma_cfg *dma_cfg = NULL;
|
||||
|
||||
cfg = ge2d_wq_get_dma_cfg(context,
|
||||
data_type, i);
|
||||
if (!cfg)
|
||||
return -1;
|
||||
if (!cfg->dma_cfg) {
|
||||
ge2d_log_err("%s, dma_cfg is null\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dma_cfg = (struct aml_dma_cfg *)cfg->dma_cfg;
|
||||
plane[i].addr = sg_phys(dma_cfg->sg->sgl);
|
||||
canvas_set = 1;
|
||||
ret = 0;
|
||||
} else if (plane[i].addr) {
|
||||
plane[i].addr += plane[0].addr;
|
||||
canvas_set = 1;
|
||||
@@ -2028,15 +2044,9 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context,
|
||||
unsigned int src_addr = 0, src2_addr = 0, dst_addr = 0;
|
||||
unsigned int src_stride = 0, src2_stride = 0, dst_stride = 0;
|
||||
struct config_para_ex_ion_s *ge2d_config;
|
||||
int i;
|
||||
unsigned int *stride_custom;
|
||||
|
||||
ge2d_config = &(ge2d_config_mem->_ge2d_config_ex);
|
||||
/* reset dms_used flag */
|
||||
for (i = 0; i < MAX_PLANE; i++) {
|
||||
context->config.src_dma_cfg[i].dma_used = 0;
|
||||
context->config.src2_dma_cfg[i].dma_used = 0;
|
||||
context->config.dst_dma_cfg[i].dma_used = 0;
|
||||
}
|
||||
/* setup src and dst */
|
||||
switch (ge2d_config->src_para.mem_type) {
|
||||
case CANVAS_OSD0:
|
||||
@@ -2444,9 +2454,89 @@ static int ge2d_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr)
|
||||
return ge2d_dma_buffer_get_phys(ge2d_manager.buffer, cfg, addr);
|
||||
}
|
||||
|
||||
static int ge2d_buffer_unmap(struct aml_dma_cfg *cfg)
|
||||
int ge2d_ioctl_attach_dma_fd(struct ge2d_context_s *wq,
|
||||
struct ge2d_dmabuf_attach_s *dma_attach)
|
||||
{
|
||||
return ge2d_dma_buffer_unmap_info(ge2d_manager.buffer, cfg);
|
||||
int ret = -1;
|
||||
enum dma_data_direction dir;
|
||||
int dma_fd, i;
|
||||
|
||||
if (!dma_attach) {
|
||||
ge2d_log_err("dma_attach is null\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_PLANE; i++) {
|
||||
dma_fd = dma_attach->dma_fd[i];
|
||||
if (dma_fd > 0) {
|
||||
struct ge2d_dma_cfg_s *cfg = NULL;
|
||||
struct aml_dma_cfg *dma_cfg = NULL;
|
||||
|
||||
cfg = ge2d_wq_get_dma_cfg(wq,
|
||||
dma_attach->data_type, i);
|
||||
if (!cfg)
|
||||
return -1;
|
||||
cfg->dma_used[i] = 1;
|
||||
dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL);
|
||||
if (!dma_cfg) {
|
||||
ge2d_log_err("%s, kzalloc error\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
cfg->dma_cfg = dma_cfg;
|
||||
|
||||
switch (dma_attach->data_type) {
|
||||
case AML_GE2D_SRC:
|
||||
dir = DMA_TO_DEVICE;
|
||||
break;
|
||||
case AML_GE2D_SRC2:
|
||||
dir = DMA_TO_DEVICE;
|
||||
break;
|
||||
case AML_GE2D_DST:
|
||||
dir = DMA_FROM_DEVICE;
|
||||
break;
|
||||
default:
|
||||
ge2d_log_err("%s, data_type %d error\n",
|
||||
__func__, dma_attach->data_type);
|
||||
dir = DMA_BIDIRECTIONAL;
|
||||
break;
|
||||
}
|
||||
dma_cfg->fd = dma_fd;
|
||||
dma_cfg->dev = &ge2d_manager.pdev->dev;
|
||||
dma_cfg->dir = dir;
|
||||
|
||||
ret = ge2d_dma_buffer_map(dma_cfg);
|
||||
if (ret < 0) {
|
||||
kfree(dma_cfg);
|
||||
pr_err("gdc_dma_buffer_map failed i=%d\n", i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ge2d_ioctl_detach_dma_fd(struct ge2d_context_s *wq,
|
||||
enum ge2d_data_type_e data_type)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_PLANE; i++) {
|
||||
struct ge2d_dma_cfg_s *cfg = NULL;
|
||||
struct aml_dma_cfg *dma_cfg = NULL;
|
||||
|
||||
cfg = ge2d_wq_get_dma_cfg(wq, data_type, i);
|
||||
if (!cfg)
|
||||
return;
|
||||
|
||||
dma_cfg = cfg->dma_cfg;
|
||||
if (dma_cfg && cfg->dma_used[i]) {
|
||||
ge2d_dma_buffer_unmap(dma_cfg);
|
||||
|
||||
cfg->dma_used[i] = 0;
|
||||
kfree(dma_cfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ge2d_context_s *create_ge2d_work_queue(void)
|
||||
|
||||
@@ -369,6 +369,9 @@ enum ge2d_memtype_s {
|
||||
#define UPDATE_SCALE_COEF 0x20
|
||||
#define UPDATE_ALL 0x3f
|
||||
|
||||
/* Indicates that dma fd has been attatched using ioctl GE2D_ATTACH_DMA_FD */
|
||||
#define DMA_FD_ATTACHED (-2)
|
||||
|
||||
struct rectangle_s {
|
||||
int x; /* X coordinate of its top-left point */
|
||||
int y; /* Y coordinate of its top-left point */
|
||||
@@ -638,7 +641,7 @@ struct ge2d_canvas_cfg_s {
|
||||
};
|
||||
|
||||
struct ge2d_dma_cfg_s {
|
||||
int dma_used;
|
||||
int dma_used[MAX_PLANE];
|
||||
void *dma_cfg;
|
||||
};
|
||||
|
||||
@@ -1095,6 +1098,12 @@ struct ge2d_dmabuf_exp_s {
|
||||
unsigned int flags;
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct ge2d_dmabuf_attach_s {
|
||||
int dma_fd[MAX_PLANE];
|
||||
enum ge2d_data_type_e data_type;
|
||||
};
|
||||
|
||||
/* end of ge2d dma buffer define */
|
||||
|
||||
enum {
|
||||
@@ -1181,6 +1190,10 @@ extern struct ge2d_device_data_s ge2d_meson_dev;
|
||||
#define GE2D_SYNC_DEVICE _IOW(GE2D_IOC_MAGIC, 0x08, int)
|
||||
#define GE2D_SYNC_CPU _IOW(GE2D_IOC_MAGIC, 0x09, int)
|
||||
|
||||
#define GE2D_ATTACH_DMA_FD \
|
||||
_IOW(GE2D_IOC_MAGIC, 0x0a, struct ge2d_dmabuf_attach_s)
|
||||
#define GE2D_DETACH_DMA_FD _IOW(GE2D_IOC_MAGIC, 0x0b, enum ge2d_data_type_e)
|
||||
|
||||
extern void ge2d_set_src1_data(struct ge2d_src1_data_s *cfg);
|
||||
extern void ge2d_set_src1_gen(struct ge2d_src1_gen_s *cfg);
|
||||
extern void ge2d_set_src2_dst_data(struct ge2d_src2_dst_data_s *cfg);
|
||||
|
||||
Reference in New Issue
Block a user