[9610] fimc-is2: added subdev, DEV_HW_PAF config for paf_rdma
authorEunyoung Lee <ey470.lee@samsung.com>
Mon, 23 Apr 2018 07:18:13 +0000 (16:18 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:22:31 +0000 (20:22 +0300)
Change-Id: I0bf007220b0040ae19a60a3e69e9fcd8beb4f7b3
Signed-off-by: Eunyoung Lee <ey470.lee@samsung.com>
drivers/media/platform/exynos/fimc-is2/ischain/fimc-is-v6_10_0/Makefile
drivers/media/platform/exynos/fimc-is2/ischain/fimc-is-v6_10_0/fimc-is-config.h
drivers/media/platform/exynos/fimc-is2/ischain/fimc-is-v6_10_0/fimc-is-hw-chain.c
drivers/media/platform/exynos/fimc-is2/ischain/fimc-is-v6_10_0/fimc-is-hw-chain.h
drivers/media/platform/exynos/fimc-is2/ischain/fimc-is-v6_10_0/fimc-is-param.h
drivers/media/platform/exynos/fimc-is2/ischain/fimc-is-v6_10_0/fimc-is-subdev-paf.c [new file with mode: 0644]

index 73d8487beea6ffb422feda2ded7ed9fae15e2793..1ee2d082ed8fb0fbd2136fabbc3d562d13406e0b 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_FIMC_IS_V6_10_0) += fimc-is-subdev-mexc.o
 obj-$(CONFIG_FIMC_IS_V6_10_0) += fimc-is-subdev-mcs.o
 obj-$(CONFIG_FIMC_IS_V6_10_0) += fimc-is-subdev-mcsp.o
 obj-$(CONFIG_FIMC_IS_V6_10_0) += fimc-is-subdev-vra.o
+obj-$(CONFIG_FIMC_IS_V6_10_0) += fimc-is-subdev-paf.o
 ifeq ($(CONFIG_USE_SENSOR_GROUP),y)
 obj-$(CONFIG_FIMC_IS_V6_10_0) += fimc-is-subdev-sensor.o
 obj-$(CONFIG_FIMC_IS_V6_10_0) += fimc-is-subdev-sensor_vc0.o
index 9d47366ea38496defe99fdaf000e177485254690..33ba3936827c142ec4ce30012acf741ecd50b86a 100644 (file)
@@ -79,7 +79,7 @@
 /* #define SOC_TPU0 */
 /* #define SOC_TPU1 */
 
-#define HW_SLOT_MAX            (5)
+#define HW_SLOT_MAX            (7)
 #define valid_hw_slot_id(slot_id) \
        (0 <= slot_id && slot_id < HW_SLOT_MAX)
 /* #define DISABLE_SETFILE */
index 040634a8ee081322ef8314dbe5d34337b9fe17f2..61078a7c461bb7062c5afa00e1a3b165f80fc60e 100644 (file)
@@ -171,6 +171,12 @@ int fimc_is_hw_group_cfg(void *group_data)
        }
 
        switch (group->slot) {
+       case GROUP_SLOT_PAF:
+               fimc_is_hw_group_init(group);
+               group->subdev[ENTRY_PAF] = &device->group_paf.leader;
+
+               list_add_tail(&device->group_paf.leader.list, &group->subdev_list);
+               break;
        case GROUP_SLOT_3AA:
                fimc_is_hw_group_init(group);
                group->subdev[ENTRY_3AA] = &device->group_3aa.leader;
@@ -266,6 +272,8 @@ int fimc_is_hw_group_open(void *group_data)
        case GROUP_ID_SS4:
        case GROUP_ID_SS5:
 #endif
+       case GROUP_ID_PAF0:
+       case GROUP_ID_PAF1:
        case GROUP_ID_3AA0:
        case GROUP_ID_3AA1:
        case GROUP_ID_ISP0:
@@ -586,6 +594,18 @@ static irqreturn_t fimc_is_isr1_vra(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t fimc_is_isr1_paf0(int irq, void *data)
+{
+       fimc_is_isr1_host(data);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t fimc_is_isr1_paf1(int irq, void *data)
+{
+       fimc_is_isr1_host(data);
+       return IRQ_HANDLED;
+}
+
 inline int fimc_is_hw_slot_id(int hw_id)
 {
        int slot_id = -1;
@@ -606,6 +626,12 @@ inline int fimc_is_hw_slot_id(int hw_id)
        case DEV_HW_VRA:
                slot_id = 4;
                break;
+       case DEV_HW_PAF0:
+               slot_id = 5;
+               break;
+       case DEV_HW_PAF1:
+               slot_id = 6;
+               break;
        default:
                break;
        }
@@ -623,6 +649,12 @@ int fimc_is_get_hw_list(int group_id, int *hw_list)
                hw_list[i] = -1;
 
        switch (group_id) {
+       case GROUP_ID_PAF0:
+               hw_list[hw_index] = DEV_HW_PAF0; hw_index++;
+               break;
+       case GROUP_ID_PAF1:
+               hw_list[hw_index] = DEV_HW_PAF1; hw_index++;
+               break;
        case GROUP_ID_3AA0:
                hw_list[hw_index] = DEV_HW_3AA0; hw_index++;
                break;
@@ -721,6 +753,9 @@ static int fimc_is_hw_get_clk_gate(struct fimc_is_hw_ip *hw_ip, int hw_id)
 
                spin_lock_init(&clk_gate->slock);
                break;
+       case DEV_HW_PAF0:
+       case DEV_HW_PAF1:
+               break;
        default:
                probe_err("hw_id(%d) is invalid", hw_id);
                ret = -EINVAL;
@@ -846,6 +881,72 @@ int fimc_is_hw_get_address(void *itfc_data, void *pdev_data, int hw_id)
 
                info_itfc("[ID:%2d] VRA1 VA(0x%p)\n", hw_id, itf_hwip->hw_ip->regs_b);
                break;
+       case DEV_HW_PAF0:
+               mem_res = platform_get_resource(pdev, IORESOURCE_MEM, IORESOURCE_PAF_RDMA);
+               if (!mem_res) {
+                       dev_err(&pdev->dev, "Failed to get io memory region\n");
+                       return -EINVAL;
+               }
+
+               itf_hwip->hw_ip->regs_start = mem_res->start;
+               itf_hwip->hw_ip->regs_end = mem_res->end;
+               itf_hwip->hw_ip->regs = ioremap_nocache(mem_res->start, resource_size(mem_res));
+               if (!itf_hwip->hw_ip->regs) {
+                       dev_err(&pdev->dev, "Failed to remap io region\n");
+                       return -EINVAL;
+               }
+
+               info_itfc("[ID:%2d] PAF0 RD VA(0x%p)\n", hw_id, itf_hwip->hw_ip->regs);
+
+               mem_res = platform_get_resource(pdev, IORESOURCE_MEM, IORESOURCE_PAF_CORE);
+               if (!mem_res) {
+                       dev_err(&pdev->dev, "Failed to get io memory region\n");
+                       return -EINVAL;
+               }
+
+               itf_hwip->hw_ip->regs_b_start = mem_res->start;
+               itf_hwip->hw_ip->regs_b_end = mem_res->end;
+               itf_hwip->hw_ip->regs_b = ioremap_nocache(mem_res->start, resource_size(mem_res));
+               if (!itf_hwip->hw_ip->regs_b) {
+                       dev_err(&pdev->dev, "Failed to remap io region\n");
+                       return -EINVAL;
+               }
+
+               info_itfc("[ID:%2d] PAF0 COMMON VA(0x%p)\n", hw_id, itf_hwip->hw_ip->regs_b);
+               break;
+       case DEV_HW_PAF1:
+               mem_res = platform_get_resource(pdev, IORESOURCE_MEM, IORESOURCE_PAF_RDMA);
+               if (!mem_res) {
+                       dev_err(&pdev->dev, "Failed to get io memory region\n");
+                       return -EINVAL;
+               }
+
+               itf_hwip->hw_ip->regs_start = mem_res->start;
+               itf_hwip->hw_ip->regs_end = mem_res->end;
+               itf_hwip->hw_ip->regs = ioremap_nocache(mem_res->start, resource_size(mem_res));
+               if (!itf_hwip->hw_ip->regs) {
+                       dev_err(&pdev->dev, "Failed to remap io region\n");
+                       return -EINVAL;
+               }
+
+               info_itfc("[ID:%2d] PAF1 RD VA(0x%p)\n", hw_id, itf_hwip->hw_ip->regs);
+
+               mem_res = platform_get_resource(pdev, IORESOURCE_MEM, IORESOURCE_PAF_CORE);
+               if (!mem_res) {
+                       dev_err(&pdev->dev, "Failed to get io memory region\n");
+                       return -EINVAL;
+               }
+
+               itf_hwip->hw_ip->regs_b_start = mem_res->start;
+               itf_hwip->hw_ip->regs_b_end = mem_res->end;
+               itf_hwip->hw_ip->regs_b = ioremap_nocache(mem_res->start, resource_size(mem_res));
+               if (!itf_hwip->hw_ip->regs_b) {
+                       dev_err(&pdev->dev, "Failed to remap io region\n");
+                       return -EINVAL;
+               }
+
+               info_itfc("[ID:%2d] PAF1 COMMON VA(0x%p)\n", hw_id, itf_hwip->hw_ip->regs_b);
+               break;
        default:
                probe_err("hw_id(%d) is invalid", hw_id);
                return -EINVAL;
@@ -924,6 +1025,20 @@ int fimc_is_hw_get_irq(void *itfc_data, void *pdev_data, int hw_id)
                        return -EINVAL;
                }
                break;
+       case DEV_HW_PAF0:
+               itf_hwip->irq[INTR_HWIP1] = platform_get_irq(pdev, 8);
+               if (itf_hwip->irq[INTR_HWIP1] < 0) {
+                       err("Failed to get irq PAF0\n");
+                       return -EINVAL;
+               }
+               break;
+       case DEV_HW_PAF1:
+               itf_hwip->irq[INTR_HWIP1] = platform_get_irq(pdev, 9);
+               if (itf_hwip->irq[INTR_HWIP1] < 0) {
+                       err("Failed to get irq PAF1\n");
+                       return -EINVAL;
+               }
+               break;
        default:
                probe_err("hw_id(%d) is invalid", hw_id);
                return -EINVAL;
@@ -987,6 +1102,12 @@ int fimc_is_hw_request_irq(void *itfc_data, int hw_id)
        case DEV_HW_VRA:
                ret = __fimc_is_hw_request_irq(itf_hwip, "vra", INTR_HWIP2, fimc_is_isr1_vra); /* VRA CH1 */
                break;
+       case DEV_HW_PAF0:
+               ret = __fimc_is_hw_request_irq(itf_hwip, "paf0", INTR_HWIP1, fimc_is_isr1_paf0);
+               break;
+       case DEV_HW_PAF1:
+               ret = __fimc_is_hw_request_irq(itf_hwip, "paf1", INTR_HWIP1, fimc_is_isr1_paf1);
+               break;
        default:
                probe_err("hw_id(%d) is invalid", hw_id);
                return -EINVAL;
index 0b2cdc4562ab4b42b816cf2d97fc76debfe0b097..f99f7635fe81dc1427d74984439f4debb345dc29 100644 (file)
@@ -24,7 +24,8 @@
 #define IORESOURCE_MCSC                4
 #define IORESOURCE_VRA_CH0     5
 #define IORESOURCE_VRA_CH1     6
-#define IORESOURCE_STAT_DMA    7
+#define IORESOURCE_PAF_CORE    7
+#define IORESOURCE_PAF_RDMA    8
 
 #define FIMC_IS_RESERVE_LIB_SIZE       (0x01100000)    /* 17MB */
 #define FIMC_IS_TAAISP_SIZE            (0x00500000)    /* 5MB */
 
 #define LIC_3AA1_OFFSET_ADDR           (0x00004000)
 
+#define PAF_CONTEXT0_OFFSET                    (0x00000000)
+#define PAF_CONTEXT1_OFFSET                    (0x00004000)
+#define PAF_RDMA0_OFFSET                       (0x00000000)
+#define PAF_RDMA1_OFFSET                       (0x00004000)
+
 enum taaisp_chain_id {
        ID_3AA_0 = 0,
        ID_3AA_1 = 1,
index 4b9a23c376da453c9bcdb1cac9aa7465c9e4c476..04491301bf4f78f9b617d06f7dfe42d70421569c 100644 (file)
@@ -99,6 +99,9 @@ enum is_param {
        PARAM_DCP_OUTPUT_SLAVE_DS,
        PARAM_DCP_INPIT_DISPARITY,
        PARAM_DCP_OUTPUT_DISPARITY,
+       PARAM_PAF_CONTROL,
+       PARAM_PAF_DMA_INPUT,
+       PARAM_PAF_OTF_OUTPUT,
        PARAM_END,
 };
 
@@ -1158,6 +1161,12 @@ struct tdnr_param {
        struct param_dma_output         dma_output;
 };
 
+struct paf_rdma_param {
+       struct param_control            control;
+       struct param_dma_input          dma_input;      /* dma_input */
+       struct param_otf_output         otf_output;
+};
+
 struct param_mcs_input {
        u32     otf_cmd; /* DISABLE or ENABLE */
        u32     otf_format;
@@ -1250,6 +1259,7 @@ struct is_param_region {
        struct mcs_param                mcs;
        struct vra_param                vra;
        struct dcp_param                dcp;
+       struct paf_rdma_param           paf;
        struct mcs_param                srdz;   /* TODO */
 };
 
diff --git a/drivers/media/platform/exynos/fimc-is2/ischain/fimc-is-v6_10_0/fimc-is-subdev-paf.c b/drivers/media/platform/exynos/fimc-is2/ischain/fimc-is-v6_10_0/fimc-is-subdev-paf.c
new file mode 100644 (file)
index 0000000..bec6c92
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "fimc-is-device-ischain.h"
+#include "fimc-is-device-sensor.h"
+#include "fimc-is-subdev-ctrl.h"
+#include "fimc-is-config.h"
+#include "fimc-is-param.h"
+#include "fimc-is-video.h"
+#include "fimc-is-type.h"
+
+static int fimc_is_ischain_paf_cfg(struct fimc_is_subdev *leader,
+       void *device_data,
+       struct fimc_is_frame *frame,
+       struct fimc_is_crop *incrop,
+       struct fimc_is_crop *otcrop,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct fimc_is_group *group;
+       struct fimc_is_queue *queue;
+       struct param_otf_output *otf_output;
+       struct param_dma_input *dma_input;
+       struct param_control *control;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_ischain *device;
+       u32 hw_format = DMA_INPUT_FORMAT_BAYER;
+       u32 hw_bitwidth = DMA_INPUT_BIT_WIDTH_16BIT;
+
+       device = (struct fimc_is_device_ischain *)device_data;
+
+       FIMC_BUG(!leader);
+       FIMC_BUG(!device);
+       FIMC_BUG(!device->sensor);
+       FIMC_BUG(!incrop);
+       FIMC_BUG(!lindex);
+       FIMC_BUG(!hindex);
+       FIMC_BUG(!indexes);
+
+       group = &device->group_paf;
+
+       ret = fimc_is_sensor_g_module(device->sensor, &module);
+       if (ret) {
+               merr("fimc_is_sensor_g_module is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       if (!test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+               queue = GET_SUBDEV_QUEUE(leader);
+               if (!queue) {
+                       merr("queue is NULL", device);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (!queue->framecfg.format) {
+                       merr("format is NULL", device);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               hw_format = queue->framecfg.format->hw_format;
+               hw_bitwidth = queue->framecfg.format->hw_bitwidth; /* memory width per pixel */
+       }
+
+       /* Configure Conrtol */
+       if (!frame) {
+               control = fimc_is_itf_g_param(device, NULL, PARAM_PAF_CONTROL);
+               if (test_bit(FIMC_IS_GROUP_START, &group->state)) {
+                       control->cmd = CONTROL_COMMAND_START;
+                       control->bypass = CONTROL_BYPASS_DISABLE;
+               } else {
+                       control->cmd = CONTROL_COMMAND_STOP;
+                       control->bypass = CONTROL_BYPASS_DISABLE;
+               }
+               *lindex |= LOWBIT_OF(PARAM_PAF_CONTROL);
+               *hindex |= HIGHBIT_OF(PARAM_PAF_CONTROL);
+               (*indexes)++;
+       }
+
+       dma_input = fimc_is_itf_g_param(device, frame, PARAM_PAF_DMA_INPUT);
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state))
+               dma_input->cmd = DMA_INPUT_COMMAND_DISABLE;
+       else
+               dma_input->cmd = DMA_INPUT_COMMAND_ENABLE;
+       dma_input->format = hw_format;
+       dma_input->bitwidth = hw_bitwidth;
+       dma_input->msb = module->bitwidth - 1; /* msb zero padding by HW constraint */
+       dma_input->order = DMA_INPUT_ORDER_GR_BG;
+       dma_input->plane = 1;
+       dma_input->width = incrop->w;
+       dma_input->height = incrop->h;
+
+       dma_input->dma_crop_offset = 0;
+       dma_input->dma_crop_width = leader->input.width;
+       dma_input->dma_crop_height = leader->input.height;
+       dma_input->bayer_crop_offset_x = incrop->x;
+       dma_input->bayer_crop_offset_y = incrop->y;
+       dma_input->bayer_crop_width = incrop->w;
+       dma_input->bayer_crop_height = incrop->h;
+       *lindex |= LOWBIT_OF(PARAM_PAF_DMA_INPUT);
+       *hindex |= HIGHBIT_OF(PARAM_PAF_DMA_INPUT);
+       (*indexes)++;
+
+       otf_output = fimc_is_itf_g_param(device, frame, PARAM_PAF_OTF_OUTPUT);
+       if (test_bit(FIMC_IS_GROUP_OTF_OUTPUT, &group->state))
+               otf_output->cmd = OTF_OUTPUT_COMMAND_ENABLE;
+       else
+               otf_output->cmd = OTF_OUTPUT_COMMAND_DISABLE;
+
+       otf_output->width = otcrop->w;
+       otf_output->height = otcrop->h;
+       otf_output->crop_enable = 0;
+       otf_output->format = OTF_OUTPUT_FORMAT_BAYER;
+       otf_output->bitwidth = OTF_OUTPUT_BIT_WIDTH_12BIT;
+       otf_output->order = OTF_OUTPUT_ORDER_BAYER_GR_BG;
+       *lindex |= LOWBIT_OF(PARAM_PAF_OTF_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_PAF_OTF_OUTPUT);
+       (*indexes)++;
+
+       leader->input.crop = *incrop;
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_ischain_paf_tag(struct fimc_is_subdev *subdev,
+       void *device_data,
+       struct fimc_is_frame *frame,
+       struct camera2_node *node)
+{
+       int ret = 0;
+       struct fimc_is_group *group;
+       struct paf_rdma_param *paf_param;
+       struct fimc_is_crop inparm, otparm;
+       struct fimc_is_crop *incrop, *otcrop;
+       struct fimc_is_subdev *leader;
+       struct fimc_is_device_ischain *device;
+       u32 lindex, hindex, indexes;
+
+       device = (struct fimc_is_device_ischain *)device_data;
+
+       FIMC_BUG(!subdev);
+       FIMC_BUG(!device);
+       FIMC_BUG(!device->is_region);
+       FIMC_BUG(!frame);
+
+       mdbgs_ischain(4, "PAF TAG\n", device);
+
+       incrop = (struct fimc_is_crop *)node->input.cropRegion;
+       otcrop = (struct fimc_is_crop *)node->output.cropRegion;
+
+       group = &device->group_paf;
+       leader = subdev->leader;
+       lindex = hindex = indexes = 0;
+       paf_param = &device->is_region->parameter.paf;
+
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+               merr("%s is fail: paf rdma is not supported OTF_INPUT", device, __func__);
+               goto p_err;
+       } else {
+               inparm.x = 0;
+               inparm.y = 0;
+               inparm.w = paf_param->dma_input.dma_crop_width;
+               inparm.h = paf_param->dma_input.dma_crop_height;
+       }
+
+       if (IS_NULL_CROP(incrop))
+               *incrop = inparm;
+
+       /* not supported DMA input crop */
+       if ((incrop->x != 0) || (incrop->y != 0))
+               *incrop = inparm;
+
+       if (test_bit(FIMC_IS_GROUP_OTF_OUTPUT, &group->state)) {
+               otparm.x = 0;
+               otparm.y = 0;
+               otparm.w = paf_param->otf_output.width;
+               otparm.h = paf_param->otf_output.height;
+       } else {
+               otparm.x = otcrop->x;
+               otparm.y = otcrop->y;
+               otparm.w = otcrop->w;
+               otparm.h = otcrop->h;
+       }
+
+       if (IS_NULL_CROP(otcrop)) {
+               msrwarn("ot_crop [%d, %d, %d, %d] -> [%d, %d, %d, %d]\n", device, subdev, frame,
+                       otcrop->x, otcrop->y, otcrop->w, otcrop->h,
+                       otparm.x, otparm.y, otparm.w, otparm.h);
+               *otcrop = otparm;
+       }
+       set_bit(FIMC_IS_SUBDEV_FORCE_SET, &leader->state);
+
+       if (!COMPARE_CROP(incrop, &inparm) ||
+               !COMPARE_CROP(otcrop, &otparm) ||
+               test_bit(FIMC_IS_SUBDEV_FORCE_SET, &leader->state)) {
+               ret = fimc_is_ischain_paf_cfg(subdev,
+                       device,
+                       frame,
+                       incrop,
+                       otcrop,
+                       &lindex,
+                       &hindex,
+                       &indexes);
+               if (ret) {
+                       merr("fimc_is_ischain_paf_cfg is fail(%d)", device, ret);
+                       goto p_err;
+               }
+
+               msrinfo("in_crop[%d, %d, %d, %d]\n", device, subdev, frame,
+                       incrop->x, incrop->y, incrop->w, incrop->h);
+               msrinfo("ot_crop[%d, %d, %d, %d]\n", device, subdev, frame,
+                       otcrop->x, otcrop->y, otcrop->w, otcrop->h);
+       }
+
+       ret = fimc_is_itf_s_param(device, frame, lindex, hindex, indexes);
+       if (ret) {
+               mrerr("fimc_is_itf_s_param is fail(%d)", device, frame, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+const struct fimc_is_subdev_ops fimc_is_subdev_paf_ops = {
+       .bypass                 = NULL,
+       .cfg                    = fimc_is_ischain_paf_cfg,
+       .tag                    = fimc_is_ischain_paf_tag,
+};