From cf99c5724aecc3c90f185e5609fef65e9ff87ac3 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Tue, 2 Apr 2019 17:08:28 +0800 Subject: [PATCH] gdc: add gdc multi plane fd support [1/1] PD#SWPL-7421 Problem: gdc output not support multi plane fd Solution: add gdc multi plane fd support Verify: Verfied on G12B-W400 Change-Id: I898c027f068f92af5101fe65487baf1dfbec7c35 Signed-off-by: Pengcheng Chen ge2d: add ge2d multi plane fd support [2/2] PD#SWPL-7421 Problem: ge2d not support multi plane fd Solution: add ge2d multi plane fd support Verify: Verfied on G12B-W400 Change-Id: Ia8a529833d5c53a70eaa2094f8110635e4f184c1 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/common/ge2d/ge2d_wq.c | 234 ++++---- drivers/amlogic/media/gdc/app/gdc_module.c | 668 ++++++++++++++++++--- drivers/amlogic/media/gdc/inc/api/gdc_api.h | 9 + drivers/amlogic/media/gdc/inc/gdc/gdc_config.h | 7 +- drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c | 35 +- include/linux/amlogic/media/ge2d/ge2d.h | 8 +- 6 files changed, 738 insertions(+), 223 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index d55c4c4..6be65f7 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -301,7 +301,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; + int ret = 0, i = 0; unsigned int block_mode; int timeout = 0; if (wq->ge2d_request_exit) @@ -390,23 +390,25 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq) list_move_tail(&pitem->list, &wq->free_queue); spin_unlock(&wq->lock); /* if dma buf detach it */ - if (pitem->config.src_dma_cfg.dma_used) { - ge2d_dma_buffer_unmap((struct aml_dma_cfg * - )pitem->config.src_dma_cfg.dma_cfg); - pitem->config.src_dma_cfg.dma_used = 0; - kfree(pitem->config.src_dma_cfg.dma_cfg); - } - if (pitem->config.src2_dma_cfg.dma_used) { - ge2d_dma_buffer_unmap((struct aml_dma_cfg * - )pitem->config.src2_dma_cfg.dma_cfg); - pitem->config.src2_dma_cfg.dma_used = 0; - kfree(pitem->config.src2_dma_cfg.dma_cfg); - } - if (pitem->config.dst_dma_cfg.dma_used) { - ge2d_dma_buffer_unmap((struct aml_dma_cfg * - )pitem->config.dst_dma_cfg.dma_cfg); - pitem->config.dst_dma_cfg.dma_used = 0; - kfree(pitem->config.dst_dma_cfg.dma_cfg); + for (i = 0; i < MAX_PLANE; i++) { + if (pitem->config.src_dma_cfg[i].dma_used) { + ge2d_dma_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_dma_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_dma_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); + } } pitem = (struct ge2d_queue_item_s *)pos; } while (pos != head); @@ -425,19 +427,20 @@ static irqreturn_t ge2d_wq_handle(int irq_number, void *para) } struct ge2d_dma_cfg_s *ge2d_wq_get_dma_cfg(struct ge2d_context_s *wq, - unsigned int data_type) + unsigned int data_type, + unsigned int plane_id) { struct ge2d_dma_cfg_s *dma_cfg = NULL; switch (data_type) { case AML_GE2D_SRC: - dma_cfg = &wq->config.src_dma_cfg; + dma_cfg = &wq->config.src_dma_cfg[plane_id]; break; case AML_GE2D_SRC2: - dma_cfg = &wq->config.src2_dma_cfg; + dma_cfg = &wq->config.src2_dma_cfg[plane_id]; break; case AML_GE2D_DST: - dma_cfg = &wq->config.dst_dma_cfg; + dma_cfg = &wq->config.dst_dma_cfg[plane_id]; break; default: ge2d_log_err("wrong data_type\n"); @@ -1046,7 +1049,7 @@ static int build_ge2d_addr_config_dma( struct ge2d_dma_cfg_s *cfg = NULL; struct aml_dma_cfg *dma_cfg = NULL; - cfg = ge2d_wq_get_dma_cfg(context, data_type); + cfg = ge2d_wq_get_dma_cfg(context, data_type, 0); if (!cfg) return -1; cfg->dma_used = 1; @@ -1146,70 +1149,49 @@ static int build_ge2d_config_ex_ion(struct config_planes_ion_s *plane, unsigned int *r_offset) { int bpp_value = bpp(format); - int ret = -1; + int ret = -1, i; unsigned long addr; size_t len; bpp_value /= 8; index &= 0xff; + *canvas_index = 0; if (plane) { - if (plane[0].shared_fd) { + for (i = 0; i < MAX_PLANE; i++) { + /* multi-src_planes */ + if (plane[i].shared_fd) { #ifdef CONFIG_AMLOGIC_ION ret = meson_ion_share_fd_to_phys(ge2d_ion_client, - plane[0].shared_fd, &addr, &len); + plane[i].shared_fd, &addr, &len); if (ret != 0) return ret; #else - return ret; -#endif - plane[0].addr += addr; - *canvas_index = index; - *r_offset += 1; -#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS - canvas_config(index++, plane[0].addr, - plane[0].w * bpp_value, - plane[0].h, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); -#endif - ret = 0; - } - /* multi-src_planes */ - if (plane[1].addr) { - plane[1].addr += plane[0].addr; - *canvas_index |= index << 8; - *r_offset += 1; -#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS - canvas_config(index++, plane[1].addr, - plane[1].w * bpp_value, - plane[1].h, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); + return ret; #endif - } - if (plane[2].addr) { - plane[2].addr += plane[0].addr; - *canvas_index |= index << 16; - *r_offset += 1; + plane[i].addr = addr; + *canvas_index |= index << (8 * i); + *r_offset += 1; #ifdef CONFIG_AMLOGIC_MEDIA_CANVAS - canvas_config(index++, plane[2].addr, - plane[2].w * bpp_value, - plane[2].h, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); + canvas_config(index++, plane[i].addr, + plane[i].w * bpp_value, + plane[i].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); #endif - } - if (plane[3].addr) { - plane[3].addr += plane[0].addr; - *canvas_index |= index << 24; - *r_offset += 1; + ret = 0; + } else if (plane[i].addr) { + plane[i].addr += plane[0].addr; + *canvas_index |= index << (8 * i); + *r_offset += 1; #ifdef CONFIG_AMLOGIC_MEDIA_CANVAS - canvas_config(index++, plane[3].addr, - plane[3].w * bpp_value, - plane[3].h, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); + canvas_config(index++, plane[i].addr, + plane[i].w * bpp_value, + plane[i].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); #endif + ret = 0; + } } } return ret; @@ -1224,77 +1206,56 @@ static int build_ge2d_config_ex_dma(struct ge2d_context_s *context, unsigned int data_type) { int bpp_value = bpp(format); - int ret = -1; + int ret = -1, i; unsigned long addr; bpp_value /= 8; index &= 0xff; + *canvas_index = 0; if (plane) { - if (plane[0].shared_fd) { - struct ge2d_dma_cfg_s *cfg = NULL; - struct aml_dma_cfg *dma_cfg = NULL; - - cfg = ge2d_wq_get_dma_cfg(context, data_type); - 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); - dma_cfg->dir = dir; - cfg->dma_cfg = dma_cfg; - ret = ge2d_dma_buffer_get_phys(dma_cfg, &addr); - if (ret != 0) - return ret; - - plane[0].addr += addr; - *canvas_index = index; - *r_offset += 1; -#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS - canvas_config(index++, plane[0].addr, - plane[0].w * bpp_value, - plane[0].h, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); -#endif - ret = 0; - } - /* multi-src_planes */ - if (plane[1].addr) { - plane[1].addr += plane[0].addr; - *canvas_index |= index << 8; - *r_offset += 1; -#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS - canvas_config(index++, plane[1].addr, - plane[1].w * bpp_value, - plane[1].h, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); -#endif - } - if (plane[2].addr) { - plane[2].addr += plane[0].addr; - *canvas_index |= index << 16; - *r_offset += 1; + for (i = 0; i < MAX_PLANE; i++) { + /* multi-src_planes */ + if (plane[i].shared_fd) { + 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; + cfg->dma_used = 1; + dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL); + if (!dma_cfg) + return ret; + dma_cfg->fd = plane[i].shared_fd; + dma_cfg->dev = &(ge2d_manager.pdev->dev); + dma_cfg->dir = dir; + cfg->dma_cfg = dma_cfg; + ret = ge2d_dma_buffer_get_phys(dma_cfg, &addr); + if (ret != 0) + return ret; + plane[i].addr = addr; + *canvas_index |= index << (8 * i); + *r_offset += 1; #ifdef CONFIG_AMLOGIC_MEDIA_CANVAS - canvas_config(index++, plane[2].addr, - plane[2].w * bpp_value, - plane[2].h, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); + canvas_config(index++, plane[i].addr, + plane[i].w * bpp_value, + plane[i].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); #endif - } - if (plane[3].addr) { - plane[3].addr += plane[0].addr; - *canvas_index |= index << 24; - *r_offset += 1; + } else if (plane[i].addr) { + plane[i].addr += plane[0].addr; + *canvas_index |= index << (8 * i); + *r_offset += 1; #ifdef CONFIG_AMLOGIC_MEDIA_CANVAS - canvas_config(index++, plane[3].addr, - plane[3].w * bpp_value, - plane[3].h, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); + canvas_config(index++, plane[i].addr, + plane[i].w * bpp_value, + plane[i].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); #endif + } } } return ret; @@ -2068,8 +2029,15 @@ 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; 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: diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index 4b40847..9506df6 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -543,6 +543,12 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } + if (gs_ex->input_buffer.plane_number < 1 || + gs_ex->input_buffer.plane_number > 3) { + gdc_log(LOG_ERR, "%s, plane_number=%d invalid\n", + __func__, gs_ex->input_buffer.plane_number); + return -EINVAL; + } switch (gc->format) { case NV12: @@ -555,13 +561,13 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, - "dma import input fd %d failed\n", + "dma import input fd %d err\n", gs_ex->input_buffer.y_base_fd); return -EINVAL; } ret = meson_gdc_set_input_addr(addr, gdc_cmd); if (ret != 0) { - gdc_log(LOG_ERR, "set input addr failed\n"); + gdc_log(LOG_ERR, "set input addr err\n"); return -EINVAL; } gdc_log(LOG_INFO, "1 plane get input addr=%x\n", @@ -577,7 +583,7 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, - "dma import input fd %d failed\n", + "dma import input fd %d err\n", gs_ex->input_buffer.y_base_fd); return -EINVAL; } @@ -592,7 +598,7 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, - "dma import input fd %d failed\n", + "dma import input fd %d err\n", gs_ex->input_buffer.uv_base_fd); return -EINVAL; } @@ -600,13 +606,96 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, meson_gdc_dma_flush(&fh->gdev->pdev->dev, gdc_cmd->uv_base_addr, gc->input_y_stride * gc->input_height / 2); - gdc_log(LOG_INFO, "2 plane get input addr=%x\n", + gdc_log(LOG_INFO, "2 plane get input y_addr=%x\n", gdc_cmd->y_base_addr); - gdc_log(LOG_INFO, "2 plane get input addr=%x\n", + gdc_log(LOG_INFO, "2 plane get input uv_addr=%x\n", gdc_cmd->uv_base_addr); } break; + case YV12: + case YUV444_P: + if (gs_ex->input_buffer.plane_number == 1) { + cfg = &fh->dma_cfg.input_cfg_plane1; + cfg->fd = gs_ex->input_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d err\n", + gs_ex->input_buffer.y_base_fd); + return -EINVAL; + } + ret = meson_gdc_set_input_addr(addr, gdc_cmd); + if (ret != 0) { + gdc_log(LOG_ERR, "set input addr err\n"); + return -EINVAL; + } + gdc_log(LOG_INFO, "1 plane get input addr=%x\n", + gdc_cmd->y_base_addr); + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->y_base_addr, + gc->input_y_stride * gc->input_height); + } else if (gs_ex->input_buffer.plane_number == 3) { + cfg = &fh->dma_cfg.input_cfg_plane1; + cfg->fd = gs_ex->input_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d err\n", + gs_ex->input_buffer.y_base_fd); + return -EINVAL; + } + gdc_cmd->y_base_addr = addr; + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->y_base_addr, + gc->input_y_stride * gc->input_height); + + cfg = &fh->dma_cfg.input_cfg_plane2; + cfg->fd = gs_ex->input_buffer.u_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d err\n", + gs_ex->input_buffer.u_base_fd); + return -EINVAL; + } + gdc_cmd->u_base_addr = addr; + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->u_base_addr, + gc->input_y_stride * gc->input_height / 2); + + cfg = &fh->dma_cfg.input_cfg_plane3; + cfg->fd = gs_ex->input_buffer.v_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d err\n", + gs_ex->input_buffer.u_base_fd); + return -EINVAL; + } + gdc_cmd->v_base_addr = addr; + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->v_base_addr, + gc->input_y_stride * gc->input_height / 2); + + gdc_log(LOG_INFO, "3 plane get input y_addr=%x\n", + gdc_cmd->y_base_addr); + gdc_log(LOG_INFO, "3 plane get input u_addr=%x\n", + gdc_cmd->u_base_addr); + gdc_log(LOG_INFO, "3 plane get input v_addr=%x\n", + gdc_cmd->v_base_addr); + } + break; case Y_GREY: + case RGB444_P: cfg = &fh->dma_cfg.input_cfg_plane1; cfg->fd = gs_ex->input_buffer.y_base_fd; cfg->dev = &(fh->gdev->pdev->dev); @@ -631,50 +720,475 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, return 0; } -static long gdc_process_ex_info(struct mgdc_fh_s *fh, +static long gdc_process_input_ion_info(struct mgdc_fh_s *fh, struct gdc_settings_ex *gs_ex) { - long ret; - unsigned long addr = 0; + long ret = -1; + unsigned long addr; size_t len; - struct aml_dma_cfg *cfg = NULL; struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; if (fh == NULL || gs_ex == NULL) { gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } - memcpy(&(gdc_cmd->gdc_config), &(gs_ex->gdc_config), - sizeof(struct gdc_config_s)); - gdc_cmd->fh = fh; - if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_ION) { - /* ion alloc */ + if (gs_ex->input_buffer.plane_number < 1 || + gs_ex->input_buffer.plane_number > 3) { + gdc_log(LOG_ERR, "%s, plane_number=%d invalid\n", + __func__, gs_ex->input_buffer.plane_number); + return -EINVAL; + } + + switch (gc->format) { + case NV12: + if (gs_ex->input_buffer.plane_number == 1) { + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->input_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import input fd %d err\n", + gs_ex->input_buffer.shared_fd); + return -EINVAL; + } + ret = meson_gdc_set_input_addr(addr, gdc_cmd); + if (ret != 0) { + gdc_log(LOG_ERR, "set input addr err\n"); + return -EINVAL; + } + + gdc_log(LOG_INFO, "1 plane get input addr=%x\n", + gdc_cmd->y_base_addr); + } else if (gs_ex->input_buffer.plane_number == 2) { + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->input_buffer.y_base_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import input fd %d err\n", + gs_ex->input_buffer.y_base_fd); + return -EINVAL; + } + gdc_cmd->y_base_addr = addr; + + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->input_buffer.uv_base_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import input fd %d err\n", + gs_ex->input_buffer.uv_base_fd); + return -EINVAL; + } + gdc_cmd->uv_base_addr = addr; + gdc_log(LOG_INFO, "2 plane get input y_addr=%x\n", + gdc_cmd->y_base_addr); + gdc_log(LOG_INFO, "2 plane get input uv_addr=%x\n", + gdc_cmd->uv_base_addr); + } + break; + case YV12: + case YUV444_P: + if (gs_ex->input_buffer.plane_number == 1) { + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->input_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import input fd %d err\n", + gs_ex->input_buffer.shared_fd); + return -EINVAL; + } + + ret = meson_gdc_set_input_addr(addr, gdc_cmd); + if (ret != 0) { + gdc_log(LOG_ERR, "set input addr err\n"); + return -EINVAL; + } + gdc_log(LOG_INFO, "1 plane get input addr=%x\n", + gdc_cmd->y_base_addr); + } else if (gs_ex->input_buffer.plane_number == 3) { + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->input_buffer.y_base_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import input fd %d err\n", + gs_ex->input_buffer.y_base_fd); + return -EINVAL; + } + gdc_cmd->y_base_addr = addr; + + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->input_buffer.u_base_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import input fd %d err\n", + gs_ex->input_buffer.u_base_fd); + return -EINVAL; + } + gdc_cmd->u_base_addr = addr; + + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->input_buffer.v_base_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import input fd %d err\n", + gs_ex->input_buffer.v_base_fd); + return -EINVAL; + } + gdc_cmd->v_base_addr = addr; + + gdc_log(LOG_INFO, "3 plane get input y_addr=%x\n", + gdc_cmd->y_base_addr); + gdc_log(LOG_INFO, "3 plane get input u_addr=%x\n", + gdc_cmd->u_base_addr); + gdc_log(LOG_INFO, "3 plane get input v_addr=%x\n", + gdc_cmd->v_base_addr); + } + break; + case Y_GREY: + case RGB444_P: ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->output_buffer.shared_fd, + gs_ex->input_buffer.y_base_fd, (ion_phys_addr_t *)&addr, &len); if (ret < 0) { - gdc_log(LOG_ERR, "ion import out fd %d failed\n", - gs_ex->output_buffer.shared_fd); + gdc_log(LOG_ERR, "ion import input fd %d err\n", + gs_ex->input_buffer.y_base_fd); return -EINVAL; } - } else if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { - /* dma alloc */ - cfg = &fh->dma_cfg.output_cfg; + gdc_cmd->y_base_addr = addr; + gdc_cmd->uv_base_addr = 0; + break; + default: + gdc_log(LOG_ERR, "Error image format"); + break; + } + return 0; +} + +static long gdc_process_output_dma_info(struct mgdc_fh_s *fh, + struct gdc_settings_ex *gs_ex) +{ + long ret = -1; + unsigned long addr; + struct aml_dma_cfg *cfg = NULL; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + + if (fh == NULL || gs_ex == NULL) { + gdc_log(LOG_ERR, "Error output param\n"); + return -EINVAL; + } + if (gs_ex->output_buffer.plane_number < 1 || + gs_ex->output_buffer.plane_number > 3) { + gs_ex->output_buffer.plane_number = 1; + gdc_log(LOG_ERR, "%s, plane_number=%d invalid\n", + __func__, gs_ex->output_buffer.plane_number); + } + + switch (gc->format) { + case NV12: + if (gs_ex->output_buffer.plane_number == 1) { + cfg = &fh->dma_cfg.output_cfg_plane1; + cfg->fd = gs_ex->output_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_FROM_DEVICE; + + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import output fd %d err\n", + gs_ex->output_buffer.y_base_fd); + return -EINVAL; + } + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; + gdc_log(LOG_INFO, "1 plane get output addr=%x\n", + gdc_cmd->current_addr); + } else if (gs_ex->output_buffer.plane_number == 2) { + cfg = &fh->dma_cfg.output_cfg_plane1; + cfg->fd = gs_ex->output_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import output fd %d err\n", + gs_ex->output_buffer.y_base_fd); + return -EINVAL; + } + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = addr; + + cfg = &fh->dma_cfg.output_cfg_plane2; + cfg->fd = gs_ex->output_buffer.uv_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import output fd %d err\n", + gs_ex->output_buffer.uv_base_fd); + return -EINVAL; + } + gdc_cmd->uv_out_base_addr = addr; + + gdc_log(LOG_INFO, "2 plane get output y_addr=%x\n", + gdc_cmd->current_addr); + gdc_log(LOG_INFO, "2 plane get output uv_addr=%x\n", + gdc_cmd->uv_out_base_addr); + } + break; + case YV12: + case YUV444_P: + case RGB444_P: + if (gs_ex->output_buffer.plane_number == 1) { + cfg = &fh->dma_cfg.output_cfg_plane1; + cfg->fd = gs_ex->output_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import output fd %d err\n", + gs_ex->output_buffer.y_base_fd); + return -EINVAL; + } + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = addr; + gdc_log(LOG_INFO, "1 plane get output addr=%x\n", + gdc_cmd->current_addr); + } else if (gs_ex->output_buffer.plane_number == 3) { + cfg = &fh->dma_cfg.output_cfg_plane1; + cfg->fd = gs_ex->output_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import output fd %d err\n", + gs_ex->output_buffer.y_base_fd); + return -EINVAL; + } + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = addr; + + cfg = &fh->dma_cfg.output_cfg_plane2; + cfg->fd = gs_ex->output_buffer.u_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import output fd %d err\n", + gs_ex->output_buffer.u_base_fd); + return -EINVAL; + } + gdc_cmd->u_out_base_addr = addr; + + cfg = &fh->dma_cfg.output_cfg_plane3; + cfg->fd = gs_ex->output_buffer.v_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import output fd %d err\n", + gs_ex->output_buffer.u_base_fd); + return -EINVAL; + } + gdc_cmd->v_out_base_addr = addr; + + gdc_log(LOG_INFO, "3 plane get output y_addr=%x\n", + gdc_cmd->current_addr); + gdc_log(LOG_INFO, "3 plane get output u_addr=%x\n", + gdc_cmd->u_out_base_addr); + gdc_log(LOG_INFO, "3 plane get output v_addr=%x\n", + gdc_cmd->v_out_base_addr); + } + break; + case Y_GREY: + cfg = &fh->dma_cfg.output_cfg_plane1; cfg->fd = gs_ex->output_buffer.y_base_fd; - cfg->dev = &(gdc_manager.gdc_dev->pdev->dev); + cfg->dev = &(fh->gdev->pdev->dev); cfg->dir = DMA_FROM_DEVICE; ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { - gdc_log(LOG_ERR, "dma import out fd %d failed\n", + gdc_log(LOG_ERR, + "dma import output fd %d err\n", gs_ex->output_buffer.y_base_fd); return -EINVAL; } + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = addr; + break; + default: + gdc_log(LOG_ERR, "Error image format"); + break; + } + return 0; +} +static long gdc_process_output_ion_info(struct mgdc_fh_s *fh, + struct gdc_settings_ex *gs_ex) +{ + long ret = -1; + unsigned long addr; + size_t len; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + + if (fh == NULL || gs_ex == NULL) { + gdc_log(LOG_ERR, "Error output param\n"); + return -EINVAL; + } + if (gs_ex->output_buffer.plane_number < 1 || + gs_ex->output_buffer.plane_number > 3) { + gs_ex->output_buffer.plane_number = 1; + gdc_log(LOG_ERR, "%s, plane_number=%d invalid\n", + __func__, gs_ex->output_buffer.plane_number); + } + + switch (gc->format) { + case NV12: + if (gs_ex->output_buffer.plane_number == 1) { + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->output_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d err\n", + gs_ex->output_buffer.shared_fd); + return -EINVAL; + } + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; + gdc_log(LOG_INFO, "1 plane get output addr=%x\n", + gdc_cmd->current_addr); + } else if (gs_ex->output_buffer.plane_number == 2) { + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->output_buffer.y_base_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d err\n", + gs_ex->output_buffer.y_base_fd); + return -EINVAL; + } + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = addr; + + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->output_buffer.uv_base_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d err\n", + gs_ex->output_buffer.uv_base_fd); + return -EINVAL; + } + gdc_cmd->uv_out_base_addr = addr; + gdc_log(LOG_INFO, "2 plane get output y_addr=%x\n", + gdc_cmd->current_addr); + gdc_log(LOG_INFO, "2 plane get output uv_addr=%x\n", + gdc_cmd->uv_out_base_addr); + } + break; + case YV12: + case YUV444_P: + case RGB444_P: + if (gs_ex->output_buffer.plane_number == 1) { + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->output_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d err\n", + gs_ex->output_buffer.shared_fd); + return -EINVAL; + } + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = addr; + gdc_log(LOG_INFO, "1 plane get output addr=%x\n", + gdc_cmd->current_addr); + } else if (gs_ex->output_buffer.plane_number == 3) { + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->output_buffer.y_base_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d err\n", + gs_ex->output_buffer.y_base_fd); + return -EINVAL; + } + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = addr; + + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->output_buffer.u_base_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d err\n", + gs_ex->output_buffer.u_base_fd); + return -EINVAL; + } + gdc_cmd->u_out_base_addr = addr; + + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->output_buffer.v_base_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d err\n", + gs_ex->output_buffer.v_base_fd); + return -EINVAL; + } + gdc_cmd->v_out_base_addr = addr; + gdc_log(LOG_INFO, "3 plane get output y_addr=%x\n", + gdc_cmd->current_addr); + gdc_log(LOG_INFO, "3 plane get output u_addr=%x\n", + gdc_cmd->u_out_base_addr); + gdc_log(LOG_INFO, "3 plane get output v_addr=%x\n", + gdc_cmd->v_out_base_addr); + } + break; + case Y_GREY: + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->output_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d err\n", + gs_ex->output_buffer.shared_fd); + return -EINVAL; + } + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = addr; + break; + default: + gdc_log(LOG_ERR, "Error image format"); + break; + } + return 0; +} + +static long gdc_process_ex_info(struct mgdc_fh_s *fh, + struct gdc_settings_ex *gs_ex) +{ + long ret; + unsigned long addr = 0; + size_t len; + struct aml_dma_cfg *cfg = NULL; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + + if (fh == NULL || gs_ex == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); + return -EINVAL; + } + memcpy(&(gdc_cmd->gdc_config), &(gs_ex->gdc_config), + sizeof(struct gdc_config_s)); + gdc_cmd->fh = fh; + if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_ION) { + ret = gdc_process_output_ion_info(fh, gs_ex); + if (ret < 0) + return -EINVAL; + } else if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + ret = gdc_process_output_dma_info(fh, gs_ex); + if (ret < 0) + return -EINVAL; } - gdc_log(LOG_INFO, "%s, output addr=%lx\n", __func__, addr); gdc_cmd->base_gdc = 0; - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = gdc_cmd->buffer_addr; + if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_ION) { /* ion alloc */ ret = meson_ion_share_fd_to_phys(fh->ion_client, @@ -703,32 +1217,25 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_ION) { /* ion alloc */ - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->input_buffer.shared_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import input fd %d failed\n", - gs_ex->input_buffer.shared_fd); - return -EINVAL; - } - ret = meson_gdc_set_input_addr(addr, gdc_cmd); - if (ret != 0) { - gdc_log(LOG_ERR, "set input addr failed\n"); + ret = gdc_process_input_ion_info(fh, gs_ex); + if (ret < 0) return -EINVAL; - } } else if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { /* dma alloc */ ret = gdc_process_input_dma_info(fh, gs_ex); if (ret < 0) return -EINVAL; } - gdc_log(LOG_INFO, "%s, input addr=%x\n", - __func__, fh->gdc_cmd.y_base_addr); + gdc_cmd->outplane = gs_ex->output_buffer.plane_number; + if (gdc_cmd->outplane < 1 || gdc_cmd->outplane > 3) { + gdc_cmd->outplane = 1; + gdc_log(LOG_ERR, "%s, plane_number=%d invalid\n", + __func__, gs_ex->output_buffer.plane_number); + } mutex_lock(&fh->gdev->d_mutext); if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) gdc_buffer_dma_flush(gs_ex->config_buffer.shared_fd); - gdc_pwr_config(true); ret = gdc_run(gdc_cmd); if (ret < 0) @@ -751,11 +1258,22 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane1); if (gs_ex->input_buffer.plane_number == 2) gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); + if (gs_ex->input_buffer.plane_number == 3) { + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane3); + } } if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) gdc_dma_buffer_unmap(&fh->dma_cfg.config_cfg); - if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) - gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg); + if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane1); + if (gs_ex->output_buffer.plane_number == 2) + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane2); + if (gs_ex->output_buffer.plane_number == 3) { + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane2); + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane3); + } + } return 0; } @@ -902,9 +1420,6 @@ static long gdc_process_with_fw(struct mgdc_fh_s *fh, struct gdc_settings_with_fw *gs_with_fw) { long ret = -1; - unsigned long addr = 0; - size_t len; - struct aml_dma_cfg *cfg = NULL; struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; char *fw_name = NULL; @@ -928,49 +1443,29 @@ static long gdc_process_with_fw(struct mgdc_fh_s *fh, gdc_cmd->fh = fh; if (gs_with_fw->output_buffer.mem_alloc_type == AML_GDC_MEM_ION) { /* ion alloc */ - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_with_fw->output_buffer.shared_fd, - (ion_phys_addr_t *)&addr, &len); + ret = gdc_process_output_ion_info(fh, + (struct gdc_settings_ex *)gs_with_fw); if (ret < 0) { - gdc_log(LOG_ERR, "ion import out fd %d failed\n", - gs_with_fw->output_buffer.shared_fd); ret = -EINVAL; goto release_fw_name; } } else if (gs_with_fw->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { /* dma alloc */ - cfg = &fh->dma_cfg.output_cfg; - cfg->fd = gs_with_fw->output_buffer.y_base_fd; - cfg->dev = &(gdc_manager.gdc_dev->pdev->dev); - cfg->dir = DMA_FROM_DEVICE; - ret = gdc_dma_buffer_get_phys(cfg, &addr); + ret = gdc_process_output_dma_info(fh, + (struct gdc_settings_ex *)gs_with_fw); if (ret < 0) { - gdc_log(LOG_ERR, "dma import out fd %d failed\n", - gs_with_fw->output_buffer.y_base_fd); ret = -EINVAL; goto release_fw_name; } } - gdc_log(LOG_INFO, "%s, output addr=%lx\n", __func__, addr); gdc_cmd->base_gdc = 0; - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = gdc_cmd->buffer_addr; if (gs_with_fw->input_buffer.mem_alloc_type == AML_GDC_MEM_ION) { /* ion alloc */ - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_with_fw->input_buffer.shared_fd, - (ion_phys_addr_t *)&addr, &len); + ret = gdc_process_input_ion_info(fh, + (struct gdc_settings_ex *)gs_with_fw); if (ret < 0) { - gdc_log(LOG_ERR, "ion import input fd %d failed\n", - gs_with_fw->input_buffer.shared_fd); - ret = -EINVAL; - goto unmap; - } - ret = meson_gdc_set_input_addr(addr, gdc_cmd); - if (ret != 0) { - gdc_log(LOG_ERR, "set input addr failed\n"); ret = -EINVAL; goto unmap; } @@ -978,10 +1473,15 @@ static long gdc_process_with_fw(struct mgdc_fh_s *fh, AML_GDC_MEM_DMABUF) { /* dma alloc */ gdc_process_input_dma_info(fh, - (struct gdc_settings_ex *)gs_with_fw); + (struct gdc_settings_ex *)gs_with_fw); + } + + gdc_cmd->outplane = gs_with_fw->output_buffer.plane_number; + if (gdc_cmd->outplane < 1 || gdc_cmd->outplane > 3) { + gdc_cmd->outplane = 1; + gdc_log(LOG_ERR, "%s, plane_number=%d invalid\n", + __func__, gs_with_fw->output_buffer.plane_number); } - gdc_log(LOG_INFO, "%s, input addr=%x\n", - __func__, fh->gdc_cmd.y_base_addr); /* load firmware */ if (gs_with_fw->fw_info.fw_name != NULL) { @@ -1132,10 +1632,21 @@ unmap: gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane1); if (gs_with_fw->input_buffer.plane_number == 2) gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); + if (gs_with_fw->input_buffer.plane_number == 3) { + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane3); + } } - if (gs_with_fw->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) - gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg); + if (gs_with_fw->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane1); + if (gs_with_fw->output_buffer.plane_number == 2) + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane2); + if (gs_with_fw->output_buffer.plane_number == 3) { + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane2); + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane3); + } + } release_fw_name: kfree(fw_name); @@ -1252,6 +1763,7 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, } gdc_cmd->fh = fh; + gdc_cmd->outplane = 1; mutex_lock(&fh->gdev->d_mutext); if (trace_mode_enable >= 1) @@ -1327,6 +1839,7 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, } gdc_cmd->fh = fh; + gdc_cmd->outplane = 1; mutex_lock(&fh->gdev->d_mutext); meson_gdc_dma_flush(&fh->gdev->pdev->dev, fh->i_paddr, fh->i_len); @@ -1402,6 +1915,7 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, gc->config_addr = fh->c_paddr; gdc_cmd->fh = fh; + gdc_cmd->outplane = 1; mutex_lock(&fh->gdev->d_mutext); ret = meson_gdc_init_dma_addr(fh, &gs); if (ret != 0) { diff --git a/drivers/amlogic/media/gdc/inc/api/gdc_api.h b/drivers/amlogic/media/gdc/inc/api/gdc_api.h index 3ccd62b..f0695c2 100644 --- a/drivers/amlogic/media/gdc/inc/api/gdc_api.h +++ b/drivers/amlogic/media/gdc/inc/api/gdc_api.h @@ -184,6 +184,7 @@ struct gdc_dma_cfg { }; struct gdc_cmd_s { + uint32_t outplane; //writing/reading to gdc base address, currently not read by api uint32_t base_gdc; //array of gdc configuration and sizes @@ -197,6 +198,13 @@ struct gdc_cmd_s { uint32_t buffer_size; //current output address of gdc uint32_t current_addr; + //output address for u, v planes + union { + uint32_t uv_out_base_addr; + uint32_t u_out_base_addr; + }; + uint32_t v_out_base_addr; + //set when expecting an interrupt from gdc int32_t is_waiting_gdc; @@ -309,6 +317,7 @@ struct gdc_settings_with_fw { uint32_t magic; struct gdc_config_s gdc_config; struct gdc_buffer_info input_buffer; + struct gdc_buffer_info reserved; struct gdc_buffer_info output_buffer; struct fw_info_s fw_info; }; diff --git a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h index dbf7300..1d47b0d 100644 --- a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h +++ b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h @@ -46,10 +46,13 @@ struct meson_gdc_dev_t { }; struct gdc_dma_cfg_t { + struct aml_dma_cfg config_cfg; struct aml_dma_cfg input_cfg_plane1; struct aml_dma_cfg input_cfg_plane2; - struct aml_dma_cfg config_cfg; - struct aml_dma_cfg output_cfg; + struct aml_dma_cfg input_cfg_plane3; + struct aml_dma_cfg output_cfg_plane1; + struct aml_dma_cfg output_cfg_plane2; + struct aml_dma_cfg output_cfg_plane3; }; struct mgdc_fh_s { diff --git a/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c index c4c128b..aabc66b 100644 --- a/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c +++ b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c @@ -149,7 +149,10 @@ int gdc_process(struct gdc_cmd_s *gdc_cmd, gdc_data1out_line_offset_write(o_y_line_offset); //gdc uv output - gdc_out_base_addr += output_height * o_y_line_offset; + if (gdc_cmd->outplane == 1) + gdc_out_base_addr += output_height * o_y_line_offset; + else + gdc_out_base_addr = gdc_cmd->uv_out_base_addr; gdc_data2out_addr_write(gdc_out_base_addr); gdc_data2out_line_offset_write(o_uv_line_offset); @@ -224,12 +227,18 @@ int gdc_process_yuv420p(struct gdc_cmd_s *gdc_cmd, gdc_data1out_line_offset_write(output_stride); //gdc u output - gdc_out_base_addr += output_height * output_stride; + if (gdc_cmd->outplane == 1) + gdc_out_base_addr += output_height * output_stride; + else + gdc_out_base_addr = gdc_cmd->u_out_base_addr; gdc_data2out_addr_write(gdc_out_base_addr); gdc_data2out_line_offset_write(output_u_stride); //gdc v output - gdc_out_base_addr += output_height * output_u_stride / 2; + if (gdc_cmd->outplane == 1) + gdc_out_base_addr += output_height * output_u_stride / 2; + else + gdc_out_base_addr = gdc_cmd->v_out_base_addr; gdc_data3out_addr_write(gdc_out_base_addr); gdc_data3out_line_offset_write(output_v_stride); gdc_start(gdc_cmd); @@ -351,12 +360,18 @@ int gdc_process_yuv444p(struct gdc_cmd_s *gdc_cmd, gdc_data1out_line_offset_write(output_stride); //gdc u output - gdc_out_base_addr += output_height * output_stride; + if (gdc_cmd->outplane == 1) + gdc_out_base_addr += output_height * output_stride; + else + gdc_out_base_addr = gdc_cmd->u_out_base_addr; gdc_data2out_addr_write(gdc_out_base_addr); gdc_data2out_line_offset_write(output_u_stride); //gdc v output - gdc_out_base_addr += output_height * output_u_stride; + if (gdc_cmd->outplane == 1) + gdc_out_base_addr += output_height * output_u_stride; + else + gdc_out_base_addr = gdc_cmd->v_out_base_addr; gdc_data3out_addr_write(gdc_out_base_addr); gdc_data3out_line_offset_write(output_v_stride); gdc_start(gdc_cmd); @@ -428,12 +443,18 @@ int gdc_process_rgb444p(struct gdc_cmd_s *gdc_cmd, gdc_data1out_line_offset_write(output_stride); //gdc u output - gdc_out_base_addr += output_height * output_stride; + if (gdc_cmd->outplane == 1) + gdc_out_base_addr += output_height * output_stride; + else + gdc_out_base_addr = gdc_cmd->u_out_base_addr; gdc_data2out_addr_write(gdc_out_base_addr); gdc_data2out_line_offset_write(output_u_stride); //gdc v output - gdc_out_base_addr += output_height * output_u_stride; + if (gdc_cmd->outplane == 1) + gdc_out_base_addr += output_height * output_u_stride; + else + gdc_out_base_addr = gdc_cmd->v_out_base_addr; gdc_data3out_addr_write(gdc_out_base_addr); gdc_data3out_line_offset_write(output_v_stride); gdc_start(gdc_cmd); diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index c6fa127..ec9e6d0 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -33,7 +33,7 @@ enum ge2d_memtype_s { AML_GE2D_MEM_INVALID, }; - +#define MAX_PLANE 4 #define MAX_BITBLT_WORK_CONFIG 4 #define MAX_GE2D_CMD 32 /* 64 */ @@ -631,9 +631,9 @@ struct ge2d_config_s { unsigned int v_scale_coef_type; unsigned int h_scale_coef_type; unsigned int update_flag; - struct ge2d_dma_cfg_s src_dma_cfg; - struct ge2d_dma_cfg_s src2_dma_cfg; - struct ge2d_dma_cfg_s dst_dma_cfg; + struct ge2d_dma_cfg_s src_dma_cfg[MAX_PLANE]; + struct ge2d_dma_cfg_s src2_dma_cfg[MAX_PLANE]; + struct ge2d_dma_cfg_s dst_dma_cfg[MAX_PLANE]; }; struct ge2d_dma_buf_s { -- 2.7.4