gdc: add gdc multi plane fd support [1/2]
authorPengcheng Chen <pengcheng.chen@amlogic.com>
Tue, 2 Apr 2019 09:08:28 +0000 (17:08 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Sun, 5 May 2019 07:31:37 +0000 (00:31 -0700)
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 <pengcheng.chen@amlogic.com>
drivers/amlogic/media/gdc/app/gdc_module.c
drivers/amlogic/media/gdc/inc/api/gdc_api.h
drivers/amlogic/media/gdc/inc/gdc/gdc_config.h
drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c

index 4b40847..9506df6 100644 (file)
@@ -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) {
index 3ccd62b..f0695c2 100644 (file)
@@ -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;
 };
index dbf7300..1d47b0d 100644 (file)
@@ -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 {
index c4c128b..aabc66b 100644 (file)
@@ -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);