diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c index 5733e9f5e0cd..3686a20e3ef6 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -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; diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h index baf80c40e6da..6fdb0562f0ba 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h @@ -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 diff --git a/drivers/amlogic/media/common/ge2d/ge2d_main.c b/drivers/amlogic/media/common/ge2d/ge2d_main.c index 721a660d5319..031703b98ac8 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_main.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_main.c @@ -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; } diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index 2f92034b56bf..dc202240f286 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -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) diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index aeea8aa54cbb..7c948a6346af 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -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);