[COMMON] fimc-is2: added video_node, GROUP_PAF for paf_rdma
authorEunyoung Lee <ey470.lee@samsung.com>
Mon, 23 Apr 2018 07:20:15 +0000 (16:20 +0900)
committerEunyoung Lee <ey470.lee@samsung.com>
Tue, 19 Jun 2018 08:47:18 +0000 (17:47 +0900)
Change-Id: I75f9a900781460b471e24068e7d7e235761bbb39
Signed-off-by: Eunyoung Lee <ey470.lee@samsung.com>
23 files changed:
drivers/media/platform/exynos/fimc-is2/Makefile
drivers/media/platform/exynos/fimc-is2/fimc-is-clk-gate.c
drivers/media/platform/exynos/fimc-is2/fimc-is-core.c
drivers/media/platform/exynos/fimc-is2/fimc-is-core.h
drivers/media/platform/exynos/fimc-is2/fimc-is-device-ischain.c
drivers/media/platform/exynos/fimc-is2/fimc-is-device-ischain.h
drivers/media/platform/exynos/fimc-is2/fimc-is-framemgr.h
drivers/media/platform/exynos/fimc-is2/fimc-is-groupmgr.c
drivers/media/platform/exynos/fimc-is2/fimc-is-groupmgr.h
drivers/media/platform/exynos/fimc-is2/fimc-is-interface-wrap.c
drivers/media/platform/exynos/fimc-is2/fimc-is-subdev-ctrl.h
drivers/media/platform/exynos/fimc-is2/fimc-is-video-pafrdma.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is2/fimc-is-video.h
drivers/media/platform/exynos/fimc-is2/hardware/Makefile
drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-control.c
drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-control.h
drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-paf-rdma.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-paf-rdma.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is2/include/fimc-is-cmd.h
drivers/media/platform/exynos/fimc-is2/include/fimc-is-common-config.h
drivers/media/platform/exynos/fimc-is2/interface/fimc-is-interface-ddk.c
drivers/media/platform/exynos/fimc-is2/interface/fimc-is-interface-ischain.c
drivers/media/platform/exynos/fimc-is2/interface/fimc-is-interface-ischain.h

index d299d6fd642b262586d9a21e48f32a9295d88333..05fa9ce1dd5965da3c02bb12d9c4f0cad74f708d 100644 (file)
@@ -28,6 +28,7 @@ fimc-is-objs  := fimc-is-core.o \
                fimc-is-video-ssvc2.o \
                fimc-is-video-ssvc3.o \
                fimc-is-video-preprocessor.o \
+               fimc-is-video-pafrdma.o \
                fimc-is-subdev-ctrl.o \
                fimc-is-device-ischain.o \
                fimc-is-device-preprocessor.o \
@@ -62,7 +63,6 @@ obj-$(CONFIG_EXYNOS_DEVICE_MIPI_CSIS_VER4) += fimc-is-device-csi_v4.o
 
 obj-$(CONFIG_EXYNOS_FIMC_BNS) += fimc-is-device-flite.o
 
-
 obj-$(CONFIG_VIDEO_EXYNOS_FIMC_IS2) += fimc-is.o
 obj-$(CONFIG_VIDEO_EXYNOS_FIMC_IS2) += sensor/
 obj-$(CONFIG_VIDEO_EXYNOS_FIMC_IS2) += ischain/
index c3a65002bcf16ff3c08031305eebae5bfb332ca4..4e100ec2340304337784bfb5951fa0fbbc810815 100644 (file)
@@ -91,6 +91,10 @@ inline bool fimc_is_group_otf(struct fimc_is_device_ischain *device, int group_i
        struct fimc_is_group *group;
 
        switch (group_id) {
+       case GROUP_ID_PAF0:
+       case GROUP_ID_PAF1:
+               group = &device->group_paf;
+               break;
        case GROUP_ID_3AA0:
        case GROUP_ID_3AA1:
                group = &device->group_3aa;
index dc5e62d21ec99da1885fb1e060cd74c7d1bd6078..ab738eff97d12520979201ea7d65fde7279a6c12 100644 (file)
@@ -1307,6 +1307,16 @@ static int __init fimc_is_probe(struct platform_device *pdev)
        fimc_is_vra_video_probe(core);
 #endif
 
+#ifdef SOC_PAF0
+       /* video entity - paf_rdma0 */
+       fimc_is_paf0s_video_probe(core);
+#endif
+
+#ifdef SOC_PAF1
+       /* video entity - paf_rdma1 */
+       fimc_is_paf1s_video_probe(core);
+#endif
+
 /* TODO: video probe is needed for DCP */
 
        platform_set_drvdata(pdev, core);
index 597f428bb567227dadeed803e91d98823e4b9184..0c8f108201ffde220135f767fda0d257edf48a0d 100644 (file)
@@ -333,6 +333,8 @@ struct fimc_is_core {
        struct fimc_is_video                    video_m4p;
        struct fimc_is_video                    video_m5p;
        struct fimc_is_video                    video_vra;
+       struct fimc_is_video                    video_paf0s;
+       struct fimc_is_video                    video_paf1s;
 
        /* spi */
        struct fimc_is_spi                      spi0;
index d4a3024af951208159cc2de63f794a01229c52fb..859f18624f7639be529c3d850099e36d16eac9e0 100644 (file)
@@ -66,6 +66,7 @@
 #include "fimc-is-device-preprocessor.h"
 #include "fimc-is-vender-specific.h"
 #include "exynos-fimc-is-module.h"
+#include "./sensor/module_framework/modules/fimc-is-device-module-base.h"
 
 #include "fimc-is-vender-specific.h"
 
@@ -98,6 +99,7 @@ extern struct pm_qos_request exynos_isp_qos_cpu_online_min;
 extern struct gb_qos_request gb_req;
 #endif
 
+extern const struct fimc_is_subdev_ops fimc_is_subdev_paf_ops;
 extern const struct fimc_is_subdev_ops fimc_is_subdev_3aa_ops;
 extern const struct fimc_is_subdev_ops fimc_is_subdev_3ac_ops;
 extern const struct fimc_is_subdev_ops fimc_is_subdev_3ap_ops;
@@ -123,6 +125,8 @@ extern const struct fimc_is_subdev_ops fimc_is_subdev_vra_ops;
 extern void *fd_vaddr;
 #endif
 
+static int fimc_is_ischain_paf_stop(void *qdevice,
+       struct fimc_is_queue *queue);
 static int fimc_is_ischain_3aa_stop(void *qdevice,
        struct fimc_is_queue *queue);
 static int fimc_is_ischain_isp_stop(void *qdevice,
@@ -136,6 +140,8 @@ static int fimc_is_ischain_mcs_stop(void *qdevice,
 static int fimc_is_ischain_vra_stop(void *qdevice,
        struct fimc_is_queue *queue);
 
+static int fimc_is_ischain_paf_shot(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame);
 static int fimc_is_ischain_3aa_shot(struct fimc_is_device_ischain *device,
        struct fimc_is_frame *frame);
 static int fimc_is_ischain_isp_shot(struct fimc_is_device_ischain *device,
@@ -1332,6 +1338,9 @@ static u32 fimc_is_itf_g_group_info(struct fimc_is_device_ischain *device,
 {
        u32 group = 0;
 
+       if (path->group[GROUP_SLOT_PAF] != GROUP_ID_MAX)
+               group |= (GROUP_ID(path->group[GROUP_SLOT_PAF]) & GROUP_ID_PARM_MASK);
+
        if (path->group[GROUP_SLOT_3AA] != GROUP_ID_MAX)
                group |= (GROUP_ID(path->group[GROUP_SLOT_3AA]) & GROUP_ID_PARM_MASK);
 
@@ -3264,6 +3273,9 @@ int fimc_is_ischain_probe(struct fimc_is_device_ischain *device,
        fimc_is_pipe_probe(&device->pipe);
 #endif
 
+       fimc_is_group_probe(groupmgr, &device->group_paf, NULL, device,
+               fimc_is_ischain_paf_shot,
+               GROUP_SLOT_PAF, ENTRY_PAF, "PXS", &fimc_is_subdev_paf_ops);
        fimc_is_group_probe(groupmgr, &device->group_3aa, NULL, device,
                fimc_is_ischain_3aa_shot,
                GROUP_SLOT_3AA, ENTRY_3AA, "3XS", &fimc_is_subdev_3aa_ops);
@@ -4106,6 +4118,292 @@ p_err:
        return ret;
 }
 
+int fimc_is_ischain_paf_open(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+       int ret_err = 0;
+       u32 group_id;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       FIMC_BUG(!device);
+       FIMC_BUG(!vctx);
+       FIMC_BUG(!GET_VIDEO(vctx));
+
+       groupmgr = device->groupmgr;
+       group = &device->group_paf;
+       group_id = GROUP_ID_PAF0 + GET_PAFXS_ID(GET_VIDEO(vctx));
+
+       ret = fimc_is_group_open(groupmgr,
+               group,
+               group_id,
+               vctx);
+       if (ret) {
+               merr("fimc_is_group_open is fail(%d)", device, ret);
+               goto err_group_open;
+       }
+
+       ret = fimc_is_ischain_open_wrap(device, false);
+       if (ret) {
+               merr("fimc_is_ischain_open_wrap is fail(%d)", device, ret);
+               goto err_ischain_open;
+       }
+
+       atomic_inc(&device->group_open_cnt);
+
+       return 0;
+
+err_ischain_open:
+       ret_err = fimc_is_group_close(groupmgr, group);
+       if (ret_err)
+               merr("fimc_is_group_close is fail(%d)", device, ret_err);
+err_group_open:
+       return ret;
+}
+
+int fimc_is_ischain_paf_close(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+       struct fimc_is_queue *queue;
+
+       FIMC_BUG(!device);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_paf;
+       queue = GET_QUEUE(vctx);
+
+       /* for mediaserver dead */
+       if (test_bit(FIMC_IS_GROUP_START, &group->state)) {
+               mgwarn("sudden group close", device, group);
+               if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
+                       fimc_is_itf_sudden_stop_wrap(device, device->instance);
+               set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
+               if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
+                       msleep(sysfs_debug.hal_debug_delay);
+                       panic("HAL sudden group close #1");
+               }
+       }
+
+       if (group->head && test_bit(FIMC_IS_GROUP_START, &group->head->state)) {
+               mgwarn("sudden group close", device, group);
+               if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
+                       fimc_is_itf_sudden_stop_wrap(device, device->instance);
+               set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
+               if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
+                       msleep(sysfs_debug.hal_debug_delay);
+                       panic("HAL sudden group close #2");
+               }
+       }
+
+       ret = fimc_is_ischain_paf_stop(device, queue);
+       if (ret)
+               merr("fimc_is_ischain_paf_rdma_stop is fail", device);
+
+       ret = fimc_is_group_close(groupmgr, group);
+       if (ret)
+               merr("fimc_is_group_close is fail", device);
+
+       ret = fimc_is_ischain_close_wrap(device);
+       if (ret)
+               merr("fimc_is_ischain_close_wrap is fail(%d)", device, ret);
+
+       atomic_dec(&device->group_open_cnt);
+
+       return ret;
+}
+
+int fimc_is_ischain_paf_s_input(struct fimc_is_device_ischain *device,
+       u32 stream_type,
+       u32 module_id,
+       u32 video_id,
+       u32 input_type,
+       u32 stream_leader)
+{
+       int ret = 0;
+       struct fimc_is_group *group;
+       struct fimc_is_groupmgr *groupmgr;
+
+       FIMC_BUG(!device);
+       FIMC_BUG(!device->groupmgr);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_paf;
+
+       mdbgd_ischain("%s()\n", device, __func__);
+
+       ret = fimc_is_group_init(groupmgr, group, input_type, video_id, stream_leader);
+       if (ret) {
+               merr("fimc_is_group_init is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_init_wrap(device, stream_type, module_id);
+       if (ret) {
+               merr("fimc_is_ischain_init_wrap is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_ischain_paf_start(void *qdevice,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       struct fimc_is_device_ischain *device = qdevice;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       FIMC_BUG(!device);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_paf;
+
+       ret = fimc_is_group_start(groupmgr, group);
+       if (ret) {
+               merr("fimc_is_group_start is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_start_wrap(device, group);
+       if (ret) {
+               merr("fimc_is_ischain_start_wrap is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_ischain_paf_stop(void *qdevice,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       struct fimc_is_device_ischain *device = qdevice;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       FIMC_BUG(!device);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_paf;
+
+       ret = fimc_is_group_stop(groupmgr, group);
+       if (ret) {
+               merr("fimc_is_group_stop is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_stop_wrap(device, group);
+       if (ret) {
+               merr("fimc_is_ischain_stop_wrap is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+p_err:
+       mginfo("%s(%d):%d\n", device, group,  __func__, atomic_read(&group->scount), ret);
+       return ret;
+}
+
+static int fimc_is_ischain_paf_reqbufs(void *qdevice,
+       struct fimc_is_queue *queue, u32 count)
+{
+       int ret = 0;
+       struct fimc_is_device_ischain *device = qdevice;
+       struct fimc_is_group *group;
+
+       FIMC_BUG(!device);
+
+       group = &device->group_paf;
+
+       if (!count) {
+               ret = fimc_is_itf_unmap(device, GROUP_ID(group->id));
+               if (ret)
+                       merr("fimc_is_itf_unmap is fail(%d)", device, ret);
+       }
+
+       return ret;
+}
+
+static int fimc_is_ischain_paf_s_format(void *qdevice,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       struct fimc_is_device_ischain *device = qdevice;
+       struct fimc_is_subdev *leader;
+
+       FIMC_BUG(!device);
+       FIMC_BUG(!queue);
+
+       leader = &device->group_paf.leader;
+
+       leader->input.width = queue->framecfg.width;
+       leader->input.height = queue->framecfg.height;
+
+       leader->input.crop.x = 0;
+       leader->input.crop.y = 0;
+       leader->input.crop.w = leader->input.width;
+       leader->input.crop.h = leader->input.height;
+
+       return ret;
+}
+
+int fimc_is_ischain_paf_buffer_queue(struct fimc_is_device_ischain *device,
+       struct fimc_is_queue *queue,
+       u32 index)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       FIMC_BUG(!device);
+       FIMC_BUG(!test_bit(FIMC_IS_ISCHAIN_OPEN, &device->state));
+
+       mdbgs_ischain(4, "%s\n", device, __func__);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_paf;
+
+       ret = fimc_is_group_buffer_queue(groupmgr, group, queue, index);
+       if (ret)
+               merr("fimc_is_group_buffer_queue is fail(%d)", device, ret);
+
+       return ret;
+}
+
+int fimc_is_ischain_paf_buffer_finish(struct fimc_is_device_ischain *device,
+       u32 index)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       FIMC_BUG(!device);
+
+       mdbgs_ischain(4, "%s\n", device, __func__);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_paf;
+
+       ret = fimc_is_group_buffer_finish(groupmgr, group, index);
+       if (ret)
+               merr("fimc_is_group_buffer_finish is fail(%d)", device, ret);
+
+       return ret;
+}
+
+const struct fimc_is_queue_ops fimc_is_ischain_paf_ops = {
+       .start_streaming        = fimc_is_ischain_paf_start,
+       .stop_streaming         = fimc_is_ischain_paf_stop,
+       .s_format               = fimc_is_ischain_paf_s_format,
+       .request_bufs           = fimc_is_ischain_paf_reqbufs
+};
+
 int fimc_is_ischain_3aa_open(struct fimc_is_device_ischain *device,
        struct fimc_is_video_ctx *vctx)
 {
@@ -5826,6 +6124,25 @@ const struct fimc_is_queue_ops fimc_is_ischain_vra_ops = {
        .request_bufs           = fimc_is_ischain_vra_reqbufs
 };
 
+static int fimc_is_ischain_paf_group_tag(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame,
+       struct camera2_node *ldr_node)
+{
+       int ret = 0;
+       struct fimc_is_group *group;
+
+       group = &device->group_paf;
+
+       ret = CALL_SOPS(&group->leader, tag, device, frame, ldr_node);
+       if (ret) {
+               merr("fimc_is_ischain_paf_tag is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
 static int fimc_is_ischain_3aa_group_tag(struct fimc_is_device_ischain *device,
        struct fimc_is_frame *frame,
        struct camera2_node *ldr_node)
@@ -6467,6 +6784,214 @@ static void fimc_is_ischain_update_shot(struct fimc_is_device_ischain *device,
 #endif
 }
 
+static int fimc_is_ischain_paf_shot(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *check_frame)
+{
+       int ret = 0;
+       unsigned long flags;
+       struct fimc_is_group *group, *child, *vra;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+       struct camera2_node_group *node_group;
+       struct camera2_node ldr_node = {0, };
+       u32 setfile_save = 0;
+
+       FIMC_BUG(!device);
+       FIMC_BUG(!check_frame);
+
+       mdbgs_ischain(4, "%s()\n", device, __func__);
+
+       frame = NULL;
+       group = &device->group_paf;
+
+       framemgr = GET_HEAD_GROUP_FRAMEMGR(group);
+       if (!framemgr) {
+               merr("framemgr is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       frame = peek_frame(framemgr, FS_REQUEST);
+
+       if (unlikely(!frame)) {
+               merr("frame is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (unlikely(frame != check_frame)) {
+               merr("frame checking is fail(%p != %p)", device, frame, check_frame);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (unlikely(!frame->shot)) {
+               merr("frame->shot is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (unlikely(!test_bit(FRAME_MEM_MAPPED, &frame->mem_state))) {
+               fimc_is_itf_map(device, GROUP_ID(group->id), frame->dvaddr_shot, frame->shot_size);
+               set_bit(FRAME_MEM_MAPPED, &frame->mem_state);
+       }
+
+       frame->shot->ctl.vendor_entry.lowIndexParam = 0;
+       frame->shot->ctl.vendor_entry.highIndexParam = 0;
+       frame->shot->dm.vendor_entry.lowIndexParam = 0;
+       frame->shot->dm.vendor_entry.highIndexParam = 0;
+       node_group = &frame->shot_ext->node_group;
+
+       PROGRAM_COUNT(8);
+
+       if ((frame->shot_ext->setfile != device->setfile) &&
+               (group->id == get_ischain_leader_group(device)->id)) {
+                       setfile_save = device->setfile;
+                       device->setfile = frame->shot_ext->setfile;
+
+               mgrinfo(" setfile change at shot(%d -> %d)\n", device, group, frame,
+                       setfile_save, device->setfile & FIMC_IS_SETFILE_MASK);
+
+               if (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)) {
+                       ret = fimc_is_ischain_chg_setfile(device);
+                       if (ret) {
+                               merr("fimc_is_ischain_chg_setfile is fail", device);
+                               device->setfile = setfile_save;
+                               goto p_err;
+                       }
+               }
+       }
+
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+               enum aa_capture_intent captureIntent;
+               captureIntent = group->intent_ctl.captureIntent;
+
+               if (captureIntent != AA_CAPTURE_INTENT_CUSTOM) {
+                       frame->shot->ctl.aa.captureIntent = captureIntent;
+                       group->intent_ctl.captureIntent = AA_CAPTURE_INTENT_CUSTOM;
+                       frame->shot->ctl.aa.vendor_captureCount = group->intent_ctl.vendor_captureCount;
+                       group->intent_ctl.vendor_captureCount = 0;
+                       if (group->intent_ctl.vendor_captureExposureTime > 0) {
+                               frame->shot->ctl.aa.vendor_captureExposureTime = group->intent_ctl.vendor_captureExposureTime;
+                               group->intent_ctl.vendor_captureExposureTime = 0;
+                       }
+                       minfo("frame count(%d), intent(%d), count(%d) captureExposureTime(%d)\n", device, frame->fcount,
+                               frame->shot->ctl.aa.captureIntent, frame->shot->ctl.aa.vendor_captureCount,
+                               frame->shot->ctl.aa.vendor_captureExposureTime);
+               }
+       }
+
+       /* fd information copy */
+#if !defined(ENABLE_SHARED_METADATA) && !defined(FAST_FDAE)
+       memcpy(&frame->shot->uctl.fdUd, &device->fdUd, sizeof(struct camera2_fd_uctl));
+#endif
+
+       PROGRAM_COUNT(9);
+
+       if (test_bit(FIMC_IS_SUBDEV_PARAM_ERR, &group->head->leader.state))
+               set_bit(FIMC_IS_SUBDEV_FORCE_SET, &group->head->leader.state);
+       else
+               clear_bit(FIMC_IS_SUBDEV_FORCE_SET, &group->head->leader.state);
+
+       child = group;
+       while (child) {
+               switch (child->slot) {
+               case GROUP_SLOT_PAF:
+                       TRANS_CROP(ldr_node.input.cropRegion,
+                               node_group->leader.input.cropRegion);
+
+                       ret = fimc_is_ischain_paf_group_tag(device, frame, &ldr_node);
+                       if (ret) {
+                               merr("fimc_is_ischain_paf_group_tag is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+                       break;
+               case GROUP_SLOT_3AA:
+                       TRANS_CROP(ldr_node.input.cropRegion,
+                               node_group->leader.input.cropRegion);
+                       if (child->junction->cid < CAPTURE_NODE_MAX) {
+                               TRANS_CROP(ldr_node.output.cropRegion,
+                                       node_group->capture[child->junction->cid].output.cropRegion);
+                       } else {
+                               mgerr("capture id(%d) is invalid", group, group, child->junction->cid);
+                       }
+
+                       ret = fimc_is_ischain_3aa_group_tag(device, frame, &ldr_node);
+                       if (ret) {
+                               merr("fimc_is_ischain_3aa_group_tag is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+                       break;
+               case GROUP_SLOT_ISP:
+                       TRANS_CROP(ldr_node.input.cropRegion,
+                               ldr_node.output.cropRegion);
+                       TRANS_CROP(ldr_node.output.cropRegion,
+                               ldr_node.input.cropRegion);
+                       ret = fimc_is_ischain_isp_group_tag(device, frame, &ldr_node);
+                       if (ret) {
+                               merr("fimc_is_ischain_isp_group_tag is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+                       break;
+               case GROUP_SLOT_DIS:
+                       TRANS_CROP(ldr_node.input.cropRegion,
+                               ldr_node.output.cropRegion);
+                       TRANS_CROP(ldr_node.output.cropRegion,
+                               ldr_node.input.cropRegion);
+                       ret = fimc_is_ischain_dis_group_tag(device, frame, &ldr_node);
+                       if (ret) {
+                               merr("fimc_is_ischain_dis_group_tag is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+                       break;
+               case GROUP_SLOT_MCS:
+                       TRANS_CROP(ldr_node.input.cropRegion,
+                               ldr_node.output.cropRegion);
+                       TRANS_CROP(ldr_node.output.cropRegion,
+                               ldr_node.input.cropRegion);
+                       ret = fimc_is_ischain_mcs_group_tag(device, frame, &ldr_node);
+                       if (ret) {
+                               merr("fimc_is_ischain_mcs_group_tag is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+                       break;
+               case GROUP_SLOT_VRA:
+                       vra = &device->group_vra;
+                       TRANS_CROP(ldr_node.input.cropRegion,
+                               (u32 *)&vra->prev->junction->output.crop);
+                       TRANS_CROP(ldr_node.output.cropRegion,
+                               ldr_node.input.cropRegion);
+                       ret = fimc_is_ischain_vra_group_tag(device, frame, &ldr_node);
+                       if (ret) {
+                               merr("fimc_is_ischain_vra_group_tag is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+                       break;
+               default:
+                       merr("group slot is invalid(%d)", device, child->slot);
+                       BUG();
+               }
+
+               child = child->child;
+       }
+
+       PROGRAM_COUNT(10);
+
+p_err:
+       fimc_is_ischain_update_shot(device, frame);
+
+       if (ret) {
+               mgrerr(" SKIP(%d) : %d\n", device, group, check_frame, check_frame->index, ret);
+       } else {
+               set_bit(group->leader.id, &frame->out_flag);
+               framemgr_e_barrier_irqs(framemgr, FMGR_IDX_25, flags);
+               trans_frame(framemgr, frame, FS_PROCESS);
+               framemgr_x_barrier_irqr(framemgr, FMGR_IDX_25, flags);
+       }
+
+       return ret;
+}
+
 static int fimc_is_ischain_3aa_shot(struct fimc_is_device_ischain *device,
        struct fimc_is_frame *check_frame)
 {
index 1d5ad2e78a215e26904392f69450bf1474489b31..1bb288b78de7086b22d0e03196f7c7558f10422c 100644 (file)
@@ -128,6 +128,8 @@ struct fimc_is_device_ischain {
        struct fimc_is_pipe                     pipe;
 #endif
 
+       struct fimc_is_group                    group_paf;              /* for PAF RDMA */
+
        struct fimc_is_group                    group_3aa;
        struct fimc_is_subdev                   txc;
        struct fimc_is_subdev                   txp;
@@ -205,6 +207,23 @@ int fimc_is_ischain_stop_wrap(struct fimc_is_device_ischain *device,
 void fimc_is_ischain_version(enum fimc_is_bin_type type, const char *load_bin, u32 size);
 char* fimc_is_ischain_get_version(enum fimc_is_bin_type type);
 
+/* PAF_RDMA subdev */
+int fimc_is_ischain_paf_open(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx);
+int fimc_is_ischain_paf_close(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx);
+int fimc_is_ischain_paf_s_input(struct fimc_is_device_ischain *device,
+       u32 stream_type,
+       u32 module_id,
+       u32 video_id,
+       u32 input_type,
+       u32 stream_leader);
+int fimc_is_ischain_paf_buffer_queue(struct fimc_is_device_ischain *device,
+       struct fimc_is_queue *queue,
+       u32 index);
+int fimc_is_ischain_paf_buffer_finish(struct fimc_is_device_ischain *device,
+       u32 index);
+
 /* 3AA subdev */
 int fimc_is_ischain_3aa_open(struct fimc_is_device_ischain *device,
        struct fimc_is_video_ctx *vctx);
@@ -362,6 +381,7 @@ int fimc_is_ischain_buf_tag_64bit(struct fimc_is_device_ischain *device,
        u32 height,
        uint64_t target_addr[]);
 
+extern const struct fimc_is_queue_ops fimc_is_ischain_paf_ops;
 extern const struct fimc_is_queue_ops fimc_is_ischain_3aa_ops;
 extern const struct fimc_is_queue_ops fimc_is_ischain_isp_ops;
 extern const struct fimc_is_queue_ops fimc_is_ischain_dis_ops;
index 31da4381bbcee4726fe73a9fbe0077923315bf5e..6cf62c4f73af161fd77c012c6bca31aece5e7dea 100644 (file)
                                 FRAMEMGR_ID_SSXVC2 | FRAMEMGR_ID_SSXVC3)
 #else
 #define FRAMEMGR_ID_MEXC       0x02000000      /* for ME */
-#define FRAMEMGR_ID_HW         0x04000000
+#define FRAMEMGR_ID_PAFXS      0x04000000      /* for PAF_RDMA */
+#define FRAMEMGR_ID_HW         0x08000000
 #define FRAMEMGR_ID_SHOT       (FRAMEMGR_ID_SSX | FRAMEMGR_ID_3XS | \
                                 FRAMEMGR_ID_IXS | FRAMEMGR_ID_DXS | \
-                                FRAMEMGR_ID_MXS | FRAMEMGR_ID_VRA)
+                                FRAMEMGR_ID_MXS | FRAMEMGR_ID_VRA | \
+                                FRAMEMGR_ID_PAFXS)
 #define FRAMEMGR_ID_STREAM     (FRAMEMGR_ID_3XC | FRAMEMGR_ID_3XP | \
                                 FRAMEMGR_ID_DXS | FRAMEMGR_ID_DXC | \
                                 FRAMEMGR_ID_M0P | FRAMEMGR_ID_M1P | \
index 9eec022f729d57bd00ad6b1f8c0184b2cbbbcf22..ff613501dc6668e739a4a15b867c2ac8d22901ba 100644 (file)
@@ -1252,6 +1252,10 @@ int fimc_is_groupmgr_init(struct fimc_is_groupmgr *groupmgr,
                                }
                                break;
 #endif
+                       case GROUP_ID_PAF0:
+                               break;
+                       case GROUP_ID_PAF1:
+                               break;
                        case GROUP_ID_3AA0:
                                if ((video->id >= FIMC_IS_VIDEO_31S_NUM) &&
                                        (video->id <= FIMC_IS_VIDEO_31P_NUM)) {
@@ -2202,6 +2206,7 @@ void wait_subdev_flush_work(struct fimc_is_device_ischain *device,
                wq_id = WORK_M5P_FDONE;
                break;
        case ENTRY_SENSOR:      /* Falls Through */
+       case ENTRY_PAF:         /* Falls Through */
        case ENTRY_3AA:         /* Falls Through */
        case ENTRY_ISP:         /* Falls Through */
        case ENTRY_DIS:         /* Falls Through */
index ad149fd5f06a32b7f928827b5ce932bbaf9db278..d610e29cf437274e7ac2693d624b5dcfd990dcba 100644 (file)
 #define GROUP_ID_MCS0          7
 #define GROUP_ID_MCS1          8
 #define GROUP_ID_VRA0          9
-#define GROUP_ID_SS0           10
-#define GROUP_ID_SS1           11
-#define GROUP_ID_SS2           12
-#define GROUP_ID_SS3           13
-#define GROUP_ID_SS4           14
-#define GROUP_ID_SS5           15
-#define GROUP_ID_MAX           16
+#define GROUP_ID_PAF0          10      /* PAF RDMA */
+#define GROUP_ID_PAF1          11      /* PAF RDMA */
+#define GROUP_ID_SS0           12
+#define GROUP_ID_SS1           13
+#define GROUP_ID_SS2           14
+#define GROUP_ID_SS3           15
+#define GROUP_ID_SS4           16
+#define GROUP_ID_SS5           17
+#define GROUP_ID_MAX           18
 #define GROUP_ID_PARM_MASK     ((1 << (GROUP_ID_SS0)) - 1)
-#define GROUP_ID_SHIFT         (16)
-#define GROUP_ID_MASK          (0xFFFF)
+#define GROUP_ID_SHIFT         (18)
+#define GROUP_ID_MASK          (0x3FFFF)
 #define GROUP_ID(id)           (1 << (id))
 
 #define GROUP_SLOT_SENSOR      0
-#define GROUP_SLOT_3AA         1
-#define GROUP_SLOT_ISP         2
-#define GROUP_SLOT_DIS         3
-#define GROUP_SLOT_DCP         4
-#define GROUP_SLOT_MCS         5
-#define GROUP_SLOT_VRA         6
-#define GROUP_SLOT_MAX         7
+#define GROUP_SLOT_PAF         1
+#define GROUP_SLOT_3AA         2
+#define GROUP_SLOT_ISP         3
+#define GROUP_SLOT_DIS         4
+#define GROUP_SLOT_DCP         5
+#define GROUP_SLOT_MCS         6
+#define GROUP_SLOT_VRA         7
+#define GROUP_SLOT_MAX         8
 #else
 #define TRACE_GROUP
 #define GROUP_ID_3AA0          0
index 4c75bd71c2689727ae45a54a968f5a2359e3f06e..2aac9d7818b117dbff4b662644bc0b1e144083db 100644 (file)
@@ -145,8 +145,11 @@ int fimc_is_itf_open_wrap(struct fimc_is_device_ischain *device, u32 module_id,
        for (hw_id = 0; hw_id < DEV_HW_END; hw_id++)
                clear_bit(hw_id, &hardware->hw_map[instance]);
 
-       for (group_slot = GROUP_SLOT_3AA; group_slot < GROUP_SLOT_MAX; group_slot++) {
+       for (group_slot = GROUP_SLOT_PAF; group_slot < GROUP_SLOT_MAX; group_slot++) {
                switch (group_slot) {
+               case GROUP_SLOT_PAF:
+                       group = &device->group_paf;
+                       break;
                case GROUP_SLOT_3AA:
                        group = &device->group_3aa;
                        break;
@@ -247,7 +250,7 @@ int fimc_is_itf_close_wrap(struct fimc_is_device_ischain *device)
        }
 #endif
 
-       for (group_slot = GROUP_SLOT_3AA; group_slot < GROUP_SLOT_MAX; group_slot++) {
+       for (group_slot = GROUP_SLOT_PAF; group_slot < GROUP_SLOT_MAX; group_slot++) {
                group_id = path->group[group_slot];
                dbg_hw(1, "itf_close_wrap: group[SLOT_%d]=[%x]\n", group_slot, group_id);
                hw_maxnum = fimc_is_get_hw_list(group_id, hw_list);
index a5fb3f64a246438ff84e14ca0693a3dcae86b04d..137cbd7025ce6f87e7aa5b234185f5961030b519 100644 (file)
@@ -81,6 +81,7 @@ enum fimc_is_subdev_id {
        ENTRY_M4P,
        ENTRY_M5P,
        ENTRY_VRA,
+       ENTRY_PAF, /* PDP(PATSTAT) RDMA */
        ENTRY_END
 };
 
diff --git a/drivers/media/platform/exynos/fimc-is2/fimc-is-video-pafrdma.c b/drivers/media/platform/exynos/fimc-is2/fimc-is-video-pafrdma.c
new file mode 100644 (file)
index 0000000..7ca1475
--- /dev/null
@@ -0,0 +1,796 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 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 <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include <media/videobuf2-v4l2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-mediabus.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+#include "fimc-is-param.h"
+
+const struct v4l2_file_operations fimc_is_paf_video_fops;
+const struct v4l2_ioctl_ops fimc_is_paf_video_ioctl_ops;
+const struct vb2_ops fimc_is_paf_qops;
+
+int fimc_is_paf0s_video_probe(void *data)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       core = (struct fimc_is_core *)data;
+       video = &core->video_paf0s;
+       video->resourcemgr = &core->resourcemgr;
+
+       if (!core->pdev) {
+               probe_err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               FIMC_IS_VIDEO_PAFXS_NAME(0),
+               FIMC_IS_VIDEO_PAF0S_NUM,
+               VFL_DIR_M2M,
+               &core->resourcemgr.mem,
+               &core->v4l2_dev,
+               &fimc_is_paf_video_fops,
+               &fimc_is_paf_video_ioctl_ops);
+       if (ret)
+               dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_paf1s_video_probe(void *data)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       core = (struct fimc_is_core *)data;
+       video = &core->video_paf1s;
+       video->resourcemgr = &core->resourcemgr;
+
+       if (!core->pdev) {
+               probe_err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               FIMC_IS_VIDEO_PAFXS_NAME(1),
+               FIMC_IS_VIDEO_PAF1S_NUM,
+               VFL_DIR_M2M,
+               &core->resourcemgr.mem,
+               &core->v4l2_dev,
+               &fimc_is_paf_video_fops,
+               &fimc_is_paf_video_ioctl_ops);
+       if (ret)
+               dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       return ret;
+}
+
+/*
+ * =============================================================================
+ * Video File Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_paf_video_open(struct file *file)
+{
+       int ret = 0;
+       int ret_err = 0;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_resourcemgr *resourcemgr;
+       char name[FIMC_IS_STR_LEN];
+
+       vctx = NULL;
+       device = NULL;
+       video = video_drvdata(file);
+       resourcemgr = video->resourcemgr;
+       if (!resourcemgr) {
+               err("resourcemgr is NULL");
+               ret = -EINVAL;
+               goto err_resource_null;
+       }
+
+       ret = fimc_is_resource_open(resourcemgr, RESOURCE_TYPE_ISCHAIN, (void **)&device);
+       if (ret) {
+               err("fimc_is_resource_open is fail(%d)", ret);
+               goto err_resource_open;
+       }
+
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto err_device_null;
+       }
+
+       minfo("[PAF%dS:V] %s\n", device, GET_PAFXS_ID(video), __func__);
+
+       snprintf(name, sizeof(name), "PAF%dS", GET_PAFXS_ID(video));
+       ret = open_vctx(file, video, &vctx, device->instance, FRAMEMGR_ID_PAFXS, name);
+       if (ret) {
+               merr("open_vctx is fail(%d)", device, ret);
+               goto err_vctx_open;
+       }
+
+       ret = fimc_is_video_open(vctx,
+               device,
+               VIDEO_PAFXS_READY_BUFFERS,
+               video,
+               &fimc_is_paf_qops,
+               &fimc_is_ischain_paf_ops);
+       if (ret) {
+               merr("fimc_is_video_open is fail(%d)", device, ret);
+               goto err_video_open;
+       }
+
+       ret = fimc_is_ischain_paf_open(device, vctx);
+       if (ret) {
+               merr("fimc_is_ischain_paf_open is fail(%d)", device, ret);
+               goto err_ischain_open;
+       }
+
+       return 0;
+
+err_ischain_open:
+       ret_err = fimc_is_video_close(vctx);
+       if (ret_err)
+               merr("fimc_is_video_close is fail(%d)", device, ret_err);
+err_video_open:
+       ret_err = close_vctx(file, video, vctx);
+       if (ret_err < 0)
+               merr("close_vctx is fail(%d)", device, ret_err);
+err_vctx_open:
+err_device_null:
+err_resource_open:
+err_resource_null:
+       return ret;
+}
+
+static int fimc_is_paf_video_close(struct file *file)
+{
+       int ret = 0;
+       int refcount;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_video *video;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!file);
+       BUG_ON(!vctx);
+       BUG_ON(!GET_VIDEO(vctx));
+       BUG_ON(!GET_DEVICE(vctx));
+
+       video = GET_VIDEO(vctx);
+       device = GET_DEVICE(vctx);
+
+       ret = fimc_is_ischain_paf_close(device, vctx);
+       if (ret)
+               merr("fimc_is_ischain_paf_close is fail(%d)", device, ret);
+
+       ret = fimc_is_video_close(vctx);
+       if (ret)
+               merr("fimc_is_video_close is fail(%d)", device, ret);
+
+       refcount = close_vctx(file, video, vctx);
+       if (refcount < 0)
+               merr("close_vctx is fail(%d)", device, refcount);
+
+       minfo("[PAF%dS:V] %s(%d,%d):%d\n", device, GET_PAFXS_ID(video), __func__, atomic_read(&device->open_cnt), refcount, ret);
+
+       return ret;
+}
+
+static unsigned int fimc_is_paf_video_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       u32 ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_poll(file, vctx, wait);
+       if (ret)
+               merr("fimc_is_video_poll is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_paf_video_mmap(struct file *file,
+       struct vm_area_struct *vma)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_mmap(file, vctx, vma);
+       if (ret)
+               merr("fimc_is_video_mmap is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+const struct v4l2_file_operations fimc_is_paf_video_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fimc_is_paf_video_open,
+       .release        = fimc_is_paf_video_close,
+       .poll           = fimc_is_paf_video_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = fimc_is_paf_video_mmap,
+};
+
+/*
+ * =============================================================================
+ * Video Ioctl Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_paf_video_querycap(struct file *file, void *fh,
+       struct v4l2_capability *cap)
+{
+       /* Todo : add to query capability code */
+       return 0;
+}
+
+static int fimc_is_paf_video_enum_fmt_mplane(struct file *file, void *priv,
+       struct v4l2_fmtdesc *f)
+{
+       /* Todo : add to enumerate format code */
+       return 0;
+}
+
+static int fimc_is_paf_video_get_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       /* Todo : add to get format code */
+       return 0;
+}
+
+static int fimc_is_paf_video_set_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       BUG_ON(!vctx);
+       BUG_ON(!format);
+
+       mdbgv_paf("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_set_format_mplane(file, vctx, format);
+       if (ret) {
+               merr("fimc_is_video_set_format_mplane is fail(%d)", vctx, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_paf_video_cropcap(struct file *file, void *fh,
+       struct v4l2_cropcap *cropcap)
+{
+       /* Todo : add to crop capability code */
+       return 0;
+}
+
+static int fimc_is_paf_video_get_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       /* Todo : add to get crop control code */
+       return 0;
+}
+
+static int fimc_is_paf_video_set_crop(struct file *file, void *fh,
+       const struct v4l2_crop *crop)
+{
+       /* Todo : add to set crop control code */
+       return 0;
+}
+
+static int fimc_is_paf_video_reqbufs(struct file *file, void *priv,
+       struct v4l2_requestbuffers *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       BUG_ON(!vctx);
+
+       mdbgv_paf("%s(buffers : %d)\n", vctx, __func__, buf->count);
+
+       ret = fimc_is_video_reqbufs(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_reqbufs is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_paf_video_querybuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_paf("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_querybuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_querybuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_paf_video_qbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       BUG_ON(!vctx);
+
+       mvdbgs(3, "%s(%02d:%d)\n", vctx, &vctx->queue, __func__, buf->type, buf->index);
+
+       ret = CALL_VOPS(vctx, qbuf, buf);
+       if (ret)
+               merr("qbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_paf_video_dqbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       bool blocking = file->f_flags & O_NONBLOCK;
+
+       BUG_ON(!vctx);
+
+       mvdbgs(3, "%s\n", vctx, &vctx->queue, __func__);
+
+       ret = CALL_VOPS(vctx, dqbuf, buf, blocking);
+       if (ret)
+               merr("dqbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_paf_video_prepare(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!buf);
+       BUG_ON(!vctx);
+       BUG_ON(!GET_FRAMEMGR(vctx));
+       BUG_ON(!GET_DEVICE(vctx));
+       BUG_ON(!GET_VIDEO(vctx));
+
+       device = GET_DEVICE(vctx);
+       framemgr = GET_FRAMEMGR(vctx);
+       frame = &framemgr->frames[buf->index];
+
+       ret = fimc_is_video_prepare(file, vctx, buf);
+       if (ret) {
+               merr("fimc_is_video_prepare is fail(%d)", vctx, ret);
+               goto p_err;
+       }
+
+       if (!test_bit(FRAME_MEM_MAPPED, &frame->mem_state)) {
+               fimc_is_itf_map(device, GROUP_ID(device->group_3aa.id), frame->dvaddr_shot, frame->shot_size);
+               set_bit(FRAME_MEM_MAPPED, &frame->mem_state);
+       }
+
+p_err:
+       minfo("[PAF%dS:V] %s(%d):%d\n", device, GET_PAFXS_ID(GET_VIDEO(vctx)), __func__, buf->index, ret);
+       return ret;
+}
+
+static int fimc_is_paf_video_streamon(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_paf("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamon(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamon is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_paf_video_streamoff(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_paf("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamoff(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamoff is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_paf_video_enum_input(struct file *file, void *priv,
+       struct v4l2_input *input)
+{
+       /* Todo: add enum input control code */
+       return 0;
+}
+
+static int fimc_is_paf_video_g_input(struct file *file, void *priv,
+       unsigned int *input)
+{
+       /* Todo: add to get input control code */
+       return 0;
+}
+
+static int fimc_is_paf_video_s_input(struct file *file, void *priv,
+       unsigned int input)
+{
+       int ret = 0;
+       u32 stream, position, vindex, intype, leader;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->device);
+
+       device = GET_DEVICE(vctx);
+       stream = (input & INPUT_STREAM_MASK) >> INPUT_STREAM_SHIFT;
+       position = (input & INPUT_POSITION_MASK) >> INPUT_POSITION_SHIFT;
+       vindex = (input & INPUT_VINDEX_MASK) >> INPUT_VINDEX_SHIFT;
+       intype = (input & INPUT_INTYPE_MASK) >> INPUT_INTYPE_SHIFT;
+       leader = (input & INPUT_LEADER_MASK) >> INPUT_LEADER_SHIFT;
+
+       mdbgv_paf("%s(input : %08X)[%d,%d,%d,%d,%d]\n", vctx, __func__, input,
+                       stream, position, vindex, intype, leader);
+
+       ret = fimc_is_video_s_input(file, vctx);
+       if (ret) {
+               merr("fimc_is_video_s_input is fail(%d)", vctx, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_paf_s_input(device, stream, position, vindex, intype, leader);
+       if (ret) {
+               merr("fimc_is_ischain_paf_s_input is fail(%d)", vctx, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_paf_video_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+       BUG_ON(!GET_DEVICE(vctx));
+       BUG_ON(!ctrl);
+
+       mdbgv_paf("%s\n", vctx, __func__);
+
+       device = GET_DEVICE(vctx);
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_FORCE_DONE:
+               set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &device->group_paf.state);
+               break;
+       default:
+               ret = fimc_is_video_s_ctrl(file, vctx, ctrl);
+               if (ret) {
+                       merr("fimc_is_video_s_ctrl is fail(%d)", device, ret);
+                       goto p_err;
+               }
+               break;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_paf_video_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       /* Todo: add to get control code */
+       return 0;
+}
+
+static int fimc_is_paf_video_s_ext_ctrl(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       int ret = 0;
+       int i;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_queue *queue;
+       struct v4l2_ext_control *ext_ctrl;
+       struct v4l2_control ctrl;
+
+       BUG_ON(!vctx);
+       BUG_ON(!GET_DEVICE(vctx));
+       BUG_ON(!ctrls);
+
+       mdbgv_paf("%s\n", vctx, __func__);
+
+       if (ctrls->which != V4L2_CTRL_CLASS_CAMERA) {
+               merr("Invalid control class(%d)", vctx, ctrls->which);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       device = GET_DEVICE(vctx);
+       queue = GET_QUEUE(vctx);
+       framemgr = &queue->framemgr;
+
+       for (i = 0; i < ctrls->count; i++) {
+               ext_ctrl = (ctrls->controls + i);
+
+               switch (ext_ctrl->id) {
+               default:
+                       ctrl.id = ext_ctrl->id;
+                       ctrl.value = ext_ctrl->value;
+
+                       ret = fimc_is_video_s_ctrl(file, vctx, &ctrl);
+                       if (ret) {
+                               merr("fimc_is_video_s_ctrl is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+                       break;
+               }
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_paf_video_g_ext_ctrl(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       /* Todo: add to get extra control code */
+       return 0;
+}
+
+const struct v4l2_ioctl_ops fimc_is_paf_video_ioctl_ops = {
+       .vidioc_querycap                = fimc_is_paf_video_querycap,
+
+       .vidioc_enum_fmt_vid_out_mplane = fimc_is_paf_video_enum_fmt_mplane,
+       .vidioc_enum_fmt_vid_cap_mplane = fimc_is_paf_video_enum_fmt_mplane,
+
+       .vidioc_g_fmt_vid_out_mplane    = fimc_is_paf_video_get_format_mplane,
+       .vidioc_g_fmt_vid_cap_mplane    = fimc_is_paf_video_get_format_mplane,
+
+       .vidioc_s_fmt_vid_out_mplane    = fimc_is_paf_video_set_format_mplane,
+       .vidioc_s_fmt_vid_cap_mplane    = fimc_is_paf_video_set_format_mplane,
+
+       .vidioc_querybuf                = fimc_is_paf_video_querybuf,
+       .vidioc_reqbufs                 = fimc_is_paf_video_reqbufs,
+
+       .vidioc_qbuf                    = fimc_is_paf_video_qbuf,
+       .vidioc_dqbuf                   = fimc_is_paf_video_dqbuf,
+       .vidioc_prepare_buf             = fimc_is_paf_video_prepare,
+
+       .vidioc_streamon                = fimc_is_paf_video_streamon,
+       .vidioc_streamoff               = fimc_is_paf_video_streamoff,
+
+       .vidioc_enum_input              = fimc_is_paf_video_enum_input,
+       .vidioc_g_input                 = fimc_is_paf_video_g_input,
+       .vidioc_s_input                 = fimc_is_paf_video_s_input,
+
+       .vidioc_s_ctrl                  = fimc_is_paf_video_s_ctrl,
+       .vidioc_g_ctrl                  = fimc_is_paf_video_g_ctrl,
+       .vidioc_s_ext_ctrls             = fimc_is_paf_video_s_ext_ctrl,
+       .vidioc_g_ext_ctrls             = fimc_is_paf_video_g_ext_ctrl,
+
+       .vidioc_cropcap                 = fimc_is_paf_video_cropcap,
+       .vidioc_g_crop                  = fimc_is_paf_video_get_crop,
+       .vidioc_s_crop                  = fimc_is_paf_video_set_crop,
+};
+
+static int fimc_is_paf_queue_setup(struct vb2_queue *vbq,
+       unsigned int *num_buffers,
+       unsigned int *num_planes,
+       unsigned int sizes[],
+       struct device *alloc_devs[])
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_video *video;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+
+       mdbgv_paf("%s\n", vctx, __func__);
+
+       video = GET_VIDEO(vctx);
+       queue = GET_QUEUE(vctx);
+
+       ret = fimc_is_queue_setup(queue,
+               video->alloc_ctx,
+               num_planes,
+               sizes,
+               alloc_devs);
+       if (ret)
+               merr("fimc_is_queue_setup is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_paf_buffer_prepare(struct vb2_buffer *vb)
+{
+       return fimc_is_queue_prepare(vb);
+}
+
+static inline void fimc_is_paf_wait_prepare(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_prepare(vbq);
+}
+
+static inline void fimc_is_paf_wait_finish(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_finish(vbq);
+}
+
+static int fimc_is_paf_start_streaming(struct vb2_queue *vbq,
+       unsigned int count)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+       BUG_ON(!GET_DEVICE(vctx));
+
+       mdbgv_paf("%s\n", vctx, __func__);
+
+       device = GET_DEVICE(vctx);
+       queue = GET_QUEUE(vctx);
+
+       ret = fimc_is_queue_start_streaming(queue, device);
+       if (ret) {
+               merr("fimc_is_queue_start_streaming is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static void fimc_is_paf_stop_streaming(struct vb2_queue *vbq)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+       BUG_ON(!GET_DEVICE(vctx));
+
+       mdbgv_paf("%s\n", vctx, __func__);
+
+       device = GET_DEVICE(vctx);
+       queue = GET_QUEUE(vctx);
+
+       ret = fimc_is_queue_stop_streaming(queue, device);
+       if (ret) {
+               merr("fimc_is_queue_stop_streaming is fail(%d)", device, ret);
+               return;
+       }
+}
+
+static void fimc_is_paf_buffer_queue(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!GET_DEVICE(vctx));
+
+       mvdbgs(3, "%s(%d)\n", vctx, &vctx->queue, __func__, vb->index);
+
+       device = GET_DEVICE(vctx);
+       queue = GET_QUEUE(vctx);
+
+       ret = fimc_is_queue_buffer_queue(queue, vb);
+       if (ret) {
+               merr("fimc_is_queue_buffer_queue is fail(%d)", device, ret);
+               return;
+       }
+
+       ret = fimc_is_ischain_paf_buffer_queue(device, queue, vb->index);
+       if (ret) {
+               merr("fimc_is_ischain_paf_buffer_queue is fail(%d)", device, ret);
+               return;
+       }
+}
+
+static void fimc_is_paf_buffer_finish(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+       BUG_ON(!GET_DEVICE(vctx));
+
+       mvdbgs(3, "%s(%d)\n", vctx, &vctx->queue, __func__, vb->index);
+
+       device = GET_DEVICE(vctx);
+
+       fimc_is_queue_buffer_finish(vb);
+
+       ret = fimc_is_ischain_paf_buffer_finish(device, vb->index);
+       if (ret) {
+               merr("fimc_is_ischain_paf_buffer_finish is fail(%d)", device, ret);
+               return;
+       }
+}
+
+const struct vb2_ops fimc_is_paf_qops = {
+       .queue_setup            = fimc_is_paf_queue_setup,
+       .buf_init               = fimc_is_buffer_init,
+       .buf_prepare            = fimc_is_paf_buffer_prepare,
+       .buf_queue              = fimc_is_paf_buffer_queue,
+       .buf_finish             = fimc_is_paf_buffer_finish,
+       .wait_prepare           = fimc_is_paf_wait_prepare,
+       .wait_finish            = fimc_is_paf_wait_finish,
+       .start_streaming        = fimc_is_paf_start_streaming,
+       .stop_streaming         = fimc_is_paf_stop_streaming,
+};
index 1c18b568e4c6107dbcdbcd849d039cebc7d2c63f..5dcd576f0f0bdf2bb4d8911ae2ce3ef51743e197 100644 (file)
 #define VIDEO_SSXVC1_READY_BUFFERS             0
 #define VIDEO_SSXVC2_READY_BUFFERS             0
 #define VIDEO_SSXVC3_READY_BUFFERS             0
+#define VIDEO_PAFXS_READY_BUFFERS              0
 
 #define FIMC_IS_VIDEO_NAME(name)               ("exynos-fimc-is-"name)
 #define FIMC_IS_VIDEO_SSX_NAME                 FIMC_IS_VIDEO_NAME("ss")
 #define FIMC_IS_VIDEO_SSXVC1_NAME(id)          FIMC_IS_VIDEO_NAME("ss"#id"vc1")
 #define FIMC_IS_VIDEO_SSXVC2_NAME(id)          FIMC_IS_VIDEO_NAME("ss"#id"vc2")
 #define FIMC_IS_VIDEO_SSXVC3_NAME(id)          FIMC_IS_VIDEO_NAME("ss"#id"vc3")
+#define FIMC_IS_VIDEO_PAFXS_NAME(id)           FIMC_IS_VIDEO_NAME("p"#id"s")
 
 struct fimc_is_device_ischain;
 struct fimc_is_subdev;
@@ -212,6 +214,8 @@ enum fimc_is_video_dev_num {
        FIMC_IS_VIDEO_SS5VC1_NUM,
        FIMC_IS_VIDEO_SS5VC2_NUM,
        FIMC_IS_VIDEO_SS5VC3_NUM,
+       FIMC_IS_VIDEO_PAF0S_NUM = 140,
+       FIMC_IS_VIDEO_PAF1S_NUM,
        FIMC_IS_VIDEO_MAX_NUM
 };
 
@@ -462,6 +466,8 @@ extern int fimc_is_ssxvc0_video_probe(void *data);
 extern int fimc_is_ssxvc1_video_probe(void *data);
 extern int fimc_is_ssxvc2_video_probe(void *data);
 extern int fimc_is_ssxvc3_video_probe(void *data);
+extern int fimc_is_paf0s_video_probe(void *data);
+extern int fimc_is_paf1s_video_probe(void *data);
 
 #define GET_VIDEO(vctx)                (vctx ? (vctx)->video : NULL)
 #define GET_QUEUE(vctx)                (vctx ? &(vctx)->queue : NULL)
index 491a5271ab98a13e29a41337b446671156a6b80c..d3d886cac43c742bdc763cbd7e6ef3f266f6996a 100644 (file)
@@ -1,4 +1,5 @@
 obj-$(CONFIG_USE_DIRECT_IS_CONTROL) += fimc-is-hw-control.o \
+               fimc-is-hw-paf-rdma.o \
                fimc-is-hw-3aa.o \
                fimc-is-hw-isp.o \
                fimc-is-hw-tpu.o \
index c2854b31fcaf02401ad96518e135a4e476ecd626..d9716455b996652fdf748d23b99891cc1e17e859 100644 (file)
@@ -28,6 +28,7 @@
 #include "fimc-is-hw-vra.h"
 #include "fimc-is-hw-dcp.h"
 #include "fimc-is-hw-dm.h"
+#include "fimc-is-hw-paf-rdma.h"
 
 #define INTERNAL_SHOT_EXIST    (1)
 
@@ -193,6 +194,9 @@ static void prepare_sfr_dump(struct fimc_is_hardware *hardware)
                if (hw_ip->id == DEV_HW_END || hw_ip->id == 0)
                       continue;
 
+               if (hw_ip->id == DEV_HW_PAF0 || hw_ip->id == DEV_HW_PAF1)
+                      continue;
+
                if (IS_ERR_OR_NULL(hw_ip->regs) ||
                        (hw_ip->regs_start == 0) ||
                        (hw_ip->regs_end == 0)) {
@@ -441,6 +445,12 @@ u32 get_group_id_from_hw_ip(u32 hw_id)
        case DEV_HW_DCP:
                group_id = GROUP_ID_DCP;
                break;
+       case DEV_HW_PAF0:
+               group_id = GROUP_ID_PAF0;
+               break;
+       case DEV_HW_PAF1:
+               group_id = GROUP_ID_PAF1;
+               break;
        default:
                group_id = GROUP_ID_MAX;
                err_hw("invalid hw_id(%d)", hw_id);
@@ -485,6 +495,12 @@ u32 get_hw_id_from_group(u32 group_id)
        case GROUP_ID_VRA0:
                hw_id = DEV_HW_VRA;
                break;
+       case GROUP_ID_PAF0:
+               hw_id = DEV_HW_PAF0;
+               break;
+       case GROUP_ID_PAF1:
+               hw_id = DEV_HW_PAF1;
+               break;
        default:
                hw_id = DEV_HW_END;
                err_hw("invalid group(%d)", group_id);
@@ -673,6 +689,34 @@ int fimc_is_hardware_probe(struct fimc_is_hardware *hardware,
        sema_init(&hardware->smp_mcsc_hw_bug, 1);
 #endif
 
+#if defined(SOC_PAF0)
+       hw_id = DEV_HW_PAF0;
+       hw_slot = fimc_is_hw_slot_id(hw_id);
+       if (!valid_hw_slot_id(hw_slot)) {
+               err_hw("invalid slot (%d,%d)", hw_id, hw_slot);
+               return -EINVAL;
+       }
+       ret = fimc_is_hw_paf_probe(&(hardware->hw_ip[hw_slot]), itf, itfc, hw_id, "PAF0");
+       if (ret) {
+               err_hw("probe fail (%d,%d)", hw_id, hw_slot);
+               return ret;
+       }
+#endif
+
+#if defined(SOC_PAF1)
+       hw_id = DEV_HW_PAF1;
+       hw_slot = fimc_is_hw_slot_id(hw_id);
+       if (!valid_hw_slot_id(hw_slot)) {
+               err_hw("invalid slot (%d,%d)", hw_id, hw_slot);
+               return -EINVAL;
+       }
+       ret = fimc_is_hw_paf_probe(&(hardware->hw_ip[hw_slot]), itf, itfc, hw_id, "PAF1");
+       if (ret) {
+               err_hw("probe fail (%d,%d)", hw_id, hw_slot);
+               return ret;
+       }
+#endif
+
 #if defined(SOC_3AAISP)
        hw_id = DEV_HW_3AA0;
        hw_slot = fimc_is_hw_slot_id(hw_id);
@@ -1364,7 +1408,7 @@ int fimc_is_hardware_config_lock(struct fimc_is_hw_ip *hw_ip, u32 instance, u32
 
        hardware = hw_ip->hardware;
 
-       if (!test_bit(FIMC_IS_GROUP_OTF_INPUT, &hw_ip->group[instance]->state))
+       if (!test_bit(FIMC_IS_GROUP_OTF_INPUT, &hw_ip->group[instance]->head->state))
                return ret;
 
        msdbgs_hw(2, "[F:%d]C.L\n", instance, hw_ip, framenum);
@@ -2290,6 +2334,8 @@ int fimc_is_hardware_shot_done(struct fimc_is_hw_ip *hw_ip, struct fimc_is_frame
                goto free_frame;
 
        switch (head->id) {
+       case GROUP_ID_PAF0:
+       case GROUP_ID_PAF1:
        case GROUP_ID_3AA0:
        case GROUP_ID_3AA1:
        case GROUP_ID_ISP0:
index 33a967e45892ce689bab053e7b50ad23d8d17763..d26ad62c7453f9bafe2b6fcac2afc658e2ca8eb3 100644 (file)
@@ -87,6 +87,8 @@ enum fimc_is_hardware_id {
        DEV_HW_FD,
        DEV_HW_VRA,     /* = 15 */
        DEV_HW_DCP,
+       DEV_HW_PAF0,    /* PAF RDMA */
+       DEV_HW_PAF1,
        DEV_HW_END
 };
 
diff --git a/drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-paf-rdma.c b/drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-paf-rdma.c
new file mode 100644 (file)
index 0000000..dbe0671
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+ * Samsung EXYNOS FIMC-IS (Imaging Subsystem) driver
+ *
+ * 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-hw-paf-rdma.h"
+#include "fimc-is-err.h"
+#include "fimc-is-param.h"
+#if defined(CONFIG_CAMERA_PAFSTAT)
+#include "../sensor/module_framework/pafstat/fimc-is-hw-pafstat.h"
+#elif defined(CONFIG_CAMERA_PDP)
+#include "../sensor/module_framework/pdp/fimc-is-hw-pdp.h"
+#endif
+static int fimc_is_hw_paf_handle_interrupt(u32 id, void *context)
+{
+       struct fimc_is_hardware *hardware;
+       struct fimc_is_hw_ip *hw_ip = NULL;
+       struct fimc_is_hw_paf *hw_paf = NULL;
+       void __iomem *paf_ctx_addr;
+       u32 irq_src, irq_mask, status;
+       u32 hw_fcount, instance;
+
+       hw_ip = (struct fimc_is_hw_ip *)context;
+       hardware = hw_ip->hardware;
+       hw_fcount = atomic_read(&hw_ip->fcount);
+       instance = atomic_read(&hw_ip->instance);
+
+       if (!test_bit(HW_INIT, &hw_ip->state))
+               return IRQ_NONE;
+
+       FIMC_BUG(!hw_ip->priv_info);
+       hw_paf = (struct fimc_is_hw_paf *)hw_ip->priv_info;
+       paf_ctx_addr = (hw_ip->id == DEV_HW_PAF1) ? hw_paf->paf_ctx1_regs : hw_paf->paf_ctx0_regs;
+
+       irq_src = pafstat_hw_g_irq_src(paf_ctx_addr);
+       irq_mask = pafstat_hw_g_irq_mask(paf_ctx_addr);
+       status = (~irq_mask) & irq_src;
+
+       pafstat_hw_s_irq_src(paf_ctx_addr, status);
+
+       msdbg_hw(2, "PAFSTAT RDMA IRQ : %08X\n", instance, hw_ip, irq_src);
+
+       if (status & (1 << PAFSTAT_INT_FRAME_START)) {
+               msdbg_hw(2, "PAF: F.S[F:%d]", instance, hw_ip, hw_fcount);
+               fimc_is_hardware_frame_start(hw_ip, instance);
+       }
+
+       if (status & (1 << PAFSTAT_INT_TOTAL_FRAME_END)) {
+               msdbg_hw(2, "PAF: F.E[F:%d]", instance, hw_ip, hw_fcount);
+               fimc_is_hardware_frame_done(hw_ip, NULL, -1, FIMC_IS_HW_CORE_END,
+                                               IS_SHOT_SUCCESS, true);
+               atomic_set(&hw_ip->status.Vvalid, V_BLANK);
+               wake_up(&hw_ip->status.wait_queue);
+               CALL_HW_OPS(hw_ip, clk_gate, instance, false, false);
+       }
+
+       return 0;
+}
+
+static int fimc_is_hw_paf_open(struct fimc_is_hw_ip *hw_ip, u32 instance,
+       struct fimc_is_group *group)
+{
+       int ret = 0;
+       struct fimc_is_hw_paf *hw_paf = NULL;
+
+       FIMC_BUG(!hw_ip);
+
+       if (test_bit(HW_OPEN, &hw_ip->state))
+               return 0;
+
+       frame_manager_probe(hw_ip->framemgr, FRAMEMGR_ID_HW | (1 << hw_ip->id), "HWPAF");
+       frame_manager_probe(hw_ip->framemgr_late, FRAMEMGR_ID_HW | (1 << hw_ip->id) | 0xF000, "HWPAF LATE");
+       frame_manager_open(hw_ip->framemgr, FIMC_IS_MAX_HW_FRAME);
+       frame_manager_open(hw_ip->framemgr_late, FIMC_IS_MAX_HW_FRAME_LATE);
+
+       hw_ip->priv_info = vzalloc(sizeof(struct fimc_is_hw_paf));
+       if(!hw_ip->priv_info) {
+               mserr_hw("hw_ip->priv_info(null)", instance, hw_ip);
+               ret = -ENOMEM;
+               goto err_alloc;
+       }
+
+       hw_paf = (struct fimc_is_hw_paf *)hw_ip->priv_info;
+
+       /* set baseaddress for context */
+       hw_paf->paf_core_regs = hw_ip->regs_b;
+       hw_paf->paf_ctx0_regs = hw_paf->paf_core_regs + PAF_CONTEXT0_OFFSET;
+       hw_paf->paf_ctx1_regs = hw_paf->paf_core_regs + PAF_CONTEXT1_OFFSET;
+
+       hw_paf->paf_rdma_core_regs = hw_ip->regs;
+       hw_paf->paf_rdma0_regs = hw_paf->paf_rdma_core_regs + PAF_RDMA0_OFFSET;
+       hw_paf->paf_rdma1_regs = hw_paf->paf_rdma_core_regs + PAF_RDMA1_OFFSET;
+
+       set_bit(HW_OPEN, &hw_ip->state);
+       msdbg_hw(2, "open: [G:0x%x], framemgr[%s]", instance, hw_ip,
+               GROUP_ID(group->id), hw_ip->framemgr->name);
+
+       return 0;
+
+err_alloc:
+       frame_manager_close(hw_ip->framemgr);
+       frame_manager_close(hw_ip->framemgr_late);
+       return ret;
+}
+
+static int fimc_is_hw_paf_init(struct fimc_is_hw_ip *hw_ip, u32 instance,
+       struct fimc_is_group *group, bool flag, u32 module_id)
+{
+       int ret = 0;
+       struct fimc_is_hw_paf *hw_paf = NULL;
+
+       FIMC_BUG(!hw_ip);
+       FIMC_BUG(!hw_ip->priv_info);
+       FIMC_BUG(!group);
+
+       hw_paf = (struct fimc_is_hw_paf *)hw_ip->priv_info;
+
+       set_bit(HW_INIT, &hw_ip->state);
+       return ret;
+}
+
+static int fimc_is_hw_paf_deinit(struct fimc_is_hw_ip *hw_ip, u32 instance)
+{
+       int ret = 0;
+       struct fimc_is_hw_paf *hw_paf;
+
+       FIMC_BUG(!hw_ip);
+       FIMC_BUG(!hw_ip->priv_info);
+
+       hw_paf = (struct fimc_is_hw_paf *)hw_ip->priv_info;
+
+       return ret;
+}
+
+static int fimc_is_hw_paf_close(struct fimc_is_hw_ip *hw_ip, u32 instance)
+{
+       int ret = 0;
+       struct fimc_is_hw_paf *hw_paf;
+       void __iomem *paf_rdma_addr;
+
+       FIMC_BUG(!hw_ip);
+
+       if (!test_bit(HW_OPEN, &hw_ip->state))
+               return 0;
+
+       FIMC_BUG(!hw_ip->priv_info);
+       hw_paf = (struct fimc_is_hw_paf *)hw_ip->priv_info;
+
+       hw_paf = (struct fimc_is_hw_paf *)hw_ip->priv_info;
+       paf_rdma_addr = (hw_ip->id == DEV_HW_PAF1) ? hw_paf->paf_rdma1_regs : hw_paf->paf_rdma0_regs;
+       fimc_is_hw_paf_rdma_enable(hw_paf->paf_rdma_core_regs, paf_rdma_addr, 0);
+
+       vfree(hw_ip->priv_info);
+       frame_manager_close(hw_ip->framemgr);
+       frame_manager_close(hw_ip->framemgr_late);
+
+       clear_bit(HW_OPEN, &hw_ip->state);
+
+       return ret;
+}
+
+static int fimc_is_hw_paf_enable(struct fimc_is_hw_ip *hw_ip, u32 instance, ulong hw_map)
+{
+       int ret = 0;
+
+       FIMC_BUG(!hw_ip);
+
+       if (!test_bit_variables(hw_ip->id, &hw_map))
+               return 0;
+
+       if (!test_bit(HW_INIT, &hw_ip->state)) {
+               mserr_hw("not initialized!!", instance, hw_ip);
+               return -EINVAL;
+       }
+
+       set_bit(HW_RUN, &hw_ip->state);
+
+       return ret;
+}
+
+static int fimc_is_hw_paf_disable(struct fimc_is_hw_ip *hw_ip, u32 instance, ulong hw_map)
+{
+       int ret = 0;
+       long timetowait;
+
+       FIMC_BUG(!hw_ip);
+
+       if (!test_bit_variables(hw_ip->id, &hw_map))
+               return 0;
+
+       msinfo_hw("disable: Vvalid(%d)\n", instance, hw_ip,
+               atomic_read(&hw_ip->status.Vvalid));
+
+       timetowait = wait_event_timeout(hw_ip->status.wait_queue,
+               !atomic_read(&hw_ip->status.Vvalid),
+               FIMC_IS_HW_STOP_TIMEOUT);
+
+       if (!timetowait) {
+               mserr_hw("wait FRAME_END timeout (%ld)", instance,
+                       hw_ip, timetowait);
+               ret = -ETIME;
+       }
+
+       if (atomic_read(&hw_ip->rsccount) > 1)
+               return 0;
+
+       clear_bit(HW_RUN, &hw_ip->state);
+       clear_bit(HW_CONFIG, &hw_ip->state);
+
+       return ret;
+}
+
+static int fimc_is_hw_paf_shot(struct fimc_is_hw_ip *hw_ip, struct fimc_is_frame *frame,
+       ulong hw_map)
+{
+       int ret = 0;
+       int i;
+       struct fimc_is_hw_paf *hw_paf;
+       struct is_region *region;
+       struct paf_rdma_param *param;
+       u32 lindex, hindex;
+       void __iomem *paf_rdma_addr;
+       void __iomem *paf_ctx_addr;
+
+       FIMC_BUG(!hw_ip);
+       FIMC_BUG(!frame);
+
+       msdbgs_hw(2, "[F:%d]shot\n", frame->instance, hw_ip, frame->fcount);
+
+       if (!test_bit_variables(hw_ip->id, &hw_map))
+               return 0;
+
+       if (!test_bit(HW_INIT, &hw_ip->state)) {
+               mserr_hw("not initialized!!", frame->instance, hw_ip);
+               return -EINVAL;
+       }
+
+       FIMC_BUG(!hw_ip->priv_info);
+       hw_paf = (struct fimc_is_hw_paf *)hw_ip->priv_info;
+       region = hw_ip->region[frame->instance];
+       FIMC_BUG(!region);
+
+       FIMC_BUG(!frame->shot);
+       /* per-frame control
+        * check & update size from region */
+       lindex = frame->shot->ctl.vendor_entry.lowIndexParam;
+       hindex = frame->shot->ctl.vendor_entry.highIndexParam;
+
+       if (hw_ip->internal_fcount != 0) {
+               hw_ip->internal_fcount = 0;
+               lindex |= LOWBIT_OF(PARAM_PAF_DMA_INPUT);
+               lindex |= LOWBIT_OF(PARAM_PAF_OTF_OUTPUT);
+
+               hindex |= HIGHBIT_OF(PARAM_PAF_DMA_INPUT);
+               hindex |= HIGHBIT_OF(PARAM_PAF_OTF_OUTPUT);
+       }
+
+       /* DMA settings */
+       param = &hw_ip->region[frame->instance]->parameter.paf;
+       if (param->dma_input.cmd != DMA_INPUT_COMMAND_DISABLE) {
+               for (i = 0; i < frame->planes; i++) {
+                       hw_paf->input_dva[i] = frame->dvaddr_buffer[i];
+                       if (frame->dvaddr_buffer[i] == 0) {
+                               msinfo_hw("[F:%d]dvaddr_buffer[%d] is zero\n",
+                                       frame->instance, hw_ip, frame->fcount, i);
+                               FIMC_BUG(1);
+                       }
+               }
+       }
+
+       /* multi-buffer */
+       if (frame->num_buffers)
+               hw_ip->num_buffers = frame->num_buffers;
+
+       paf_ctx_addr = (hw_ip->id == DEV_HW_PAF1) ? hw_paf->paf_ctx1_regs : hw_paf->paf_ctx0_regs;
+       paf_rdma_addr = (hw_ip->id == DEV_HW_PAF1) ? hw_paf->paf_rdma1_regs : hw_paf->paf_rdma0_regs;
+
+       ret = fimc_is_hw_paf_update_param(hw_ip,
+               region, param,
+               lindex, hindex, frame->instance);
+
+       fimc_is_hw_paf_rdma_enable(hw_paf->paf_rdma_core_regs, paf_rdma_addr, 1);
+       fimc_is_hw_paf_oneshot_enable(paf_ctx_addr, 1);
+
+       set_bit(hw_ip->id, &frame->core_flag);
+       set_bit(HW_CONFIG, &hw_ip->state);
+
+#if 0
+       fimc_is_hw_paf_sfr_dump(hw_paf->paf_core_regs, hw_paf->paf_rdma_core_regs);
+       fimc_is_hw_paf_sfr_dump(hw_paf->paf_ctx0_regs, hw_paf->paf_rdma0_regs);
+       fimc_is_hw_paf_sfr_dump(hw_paf->paf_ctx1_regs, hw_paf->paf_rdma1_regs);
+#endif
+
+       return ret;
+}
+
+static int fimc_is_hw_paf_set_param(struct fimc_is_hw_ip *hw_ip, struct is_region *region,
+       u32 lindex, u32 hindex, u32 instance, ulong hw_map)
+{
+       int ret = 0;
+       struct fimc_is_hw_paf *hw_paf;
+       struct paf_rdma_param *param;
+
+       FIMC_BUG(!hw_ip);
+
+       if (!test_bit_variables(hw_ip->id, &hw_map))
+               return 0;
+
+       if (!test_bit(HW_INIT, &hw_ip->state)) {
+               mserr_hw("not initialized!!", instance, hw_ip);
+               return -EINVAL;
+       }
+
+       FIMC_BUG(!hw_ip->priv_info);
+
+       hw_paf = (struct fimc_is_hw_paf *)hw_ip->priv_info;
+       param = &hw_ip->region[instance]->parameter.paf;
+
+       hw_ip->region[instance] = region;
+       hw_ip->lindex[instance] = lindex;
+       hw_ip->hindex[instance] = hindex;
+
+       return ret;
+}
+
+int fimc_is_hw_paf_update_param(struct fimc_is_hw_ip *hw_ip, struct is_region *region,
+       struct paf_rdma_param *param, u32 lindex, u32 hindex, u32 instance)
+{
+       int ret = 0;
+       struct fimc_is_hw_paf *hw_paf;
+       u32 hw_format, bitwidth;
+       u32 width, height;
+       u32 paf_ch;
+       void __iomem *paf_ctx_addr;
+       void __iomem *paf_rdma_addr;
+
+       FIMC_BUG(!hw_ip);
+       FIMC_BUG(!region);
+       FIMC_BUG(!param);
+       FIMC_BUG(!hw_ip->priv_info);
+
+       hw_paf = (struct fimc_is_hw_paf *)hw_ip->priv_info;
+       param = &hw_ip->region[instance]->parameter.paf;
+
+       hw_format = param->dma_input.format;
+       bitwidth = param->dma_input.bitwidth;
+       width = param->dma_input.width;
+       height = param->dma_input.height;
+
+       paf_ch = (hw_ip->id == DEV_HW_PAF1) ? 1 : 0;
+       paf_ctx_addr = (hw_ip->id == DEV_HW_PAF1) ? hw_paf->paf_ctx1_regs : hw_paf->paf_ctx0_regs;
+       paf_rdma_addr = (hw_ip->id == DEV_HW_PAF1) ? hw_paf->paf_rdma1_regs : hw_paf->paf_rdma0_regs;
+
+       if (width == 0 || height == 0) {
+               mserr_hw("pafstat size is zero : not configured\n", instance, hw_ip);
+               return 0;
+       }
+
+       fimc_is_hw_paf_common_config(hw_paf->paf_core_regs, paf_ctx_addr, paf_ch, width, height);
+       fimc_is_hw_paf_rdma_set_addr(paf_rdma_addr, hw_paf->input_dva[0]);
+       fimc_is_hw_paf_rdma_config(paf_rdma_addr, hw_format, bitwidth, width, height);
+
+       return ret;
+}
+
+static int fimc_is_hw_paf_frame_ndone(struct fimc_is_hw_ip *hw_ip, struct fimc_is_frame *frame,
+       u32 instance, enum ShotErrorType done_type)
+{
+       int output_id;
+       int ret = 0;
+
+       FIMC_BUG(!hw_ip);
+       FIMC_BUG(!frame);
+
+       output_id = FIMC_IS_HW_CORE_END;
+       if (test_bit_variables(hw_ip->id, &frame->core_flag))
+               ret = fimc_is_hardware_frame_done(hw_ip, frame, -1,
+                               output_id, done_type, false);
+
+       return ret;
+}
+
+const struct fimc_is_hw_ip_ops fimc_is_hw_paf_ops = {
+       .open                   = fimc_is_hw_paf_open,
+       .init                   = fimc_is_hw_paf_init,
+       .deinit                 = fimc_is_hw_paf_deinit,
+       .close                  = fimc_is_hw_paf_close,
+       .enable                 = fimc_is_hw_paf_enable,
+       .disable                = fimc_is_hw_paf_disable,
+       .shot                   = fimc_is_hw_paf_shot,
+       .set_param              = fimc_is_hw_paf_set_param,
+       .frame_ndone            = fimc_is_hw_paf_frame_ndone,
+       .clk_gate               = fimc_is_hardware_clk_gate,
+};
+
+int fimc_is_hw_paf_probe(struct fimc_is_hw_ip *hw_ip, struct fimc_is_interface *itf,
+       struct fimc_is_interface_ischain *itfc, int id, const char *name)
+{
+       int ret = 0;
+       int hw_slot = -1;
+
+       FIMC_BUG(!hw_ip);
+       FIMC_BUG(!itf);
+       FIMC_BUG(!itfc);
+
+       /* initialize device hardware */
+       hw_ip->id   = id;
+       snprintf(hw_ip->name, sizeof(hw_ip->name), "%s", name);
+       hw_ip->ops  = &fimc_is_hw_paf_ops;
+       hw_ip->itf  = itf;
+       hw_ip->itfc = itfc;
+       atomic_set(&hw_ip->fcount, 0);
+       hw_ip->internal_fcount = 0;
+       hw_ip->is_leader = true;
+       atomic_set(&hw_ip->status.Vvalid, V_BLANK);
+       atomic_set(&hw_ip->status.otf_start, 0);
+       atomic_set(&hw_ip->rsccount, 0);
+       init_waitqueue_head(&hw_ip->status.wait_queue);
+
+       hw_slot = fimc_is_hw_slot_id(id);
+       if (!valid_hw_slot_id(hw_slot)) {
+               serr_hw("invalid hw_slot (%d)", hw_ip, hw_slot);
+               return -EINVAL;
+       }
+
+       itfc->itf_ip[hw_slot].handler[INTR_HWIP1].handler = &fimc_is_hw_paf_handle_interrupt;
+
+       clear_bit(HW_OPEN, &hw_ip->state);
+       clear_bit(HW_INIT, &hw_ip->state);
+       clear_bit(HW_CONFIG, &hw_ip->state);
+       clear_bit(HW_RUN, &hw_ip->state);
+       clear_bit(HW_TUNESET, &hw_ip->state);
+
+       sinfo_hw("probe done\n", hw_ip);
+
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-paf-rdma.h b/drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-paf-rdma.h
new file mode 100644 (file)
index 0000000..36971c7
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Samsung EXYNOS FIMC-IS (Imaging Subsystem) driver
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_HW_PAFRDMA_H
+#define FIMC_IS_HW_PAFRDMA_H
+
+#include "fimc-is-hw-control.h"
+#include "fimc-is-param.h"
+
+struct fimc_is_hw_paf {
+       struct paf_rdma_param           param[FIMC_IS_STREAM_COUNT];
+       void __iomem    *paf_core_regs;
+       void __iomem    *paf_ctx0_regs;
+       void __iomem    *paf_ctx1_regs;
+       void __iomem    *paf_rdma_core_regs;
+       void __iomem    *paf_rdma0_regs;
+       void __iomem    *paf_rdma1_regs;
+       u32     input_dva[FIMC_IS_MAX_PLANES];
+       u32     instance_id;
+       u32     fcount;
+};
+
+int fimc_is_hw_paf_probe(struct fimc_is_hw_ip *hw_ip, struct fimc_is_interface *itf,
+       struct fimc_is_interface_ischain *itfc, int id, const char *name);
+int fimc_is_hw_paf_mode_change(struct fimc_is_hw_ip *hw_ip, u32 instance, ulong hw_map);
+int fimc_is_hw_paf_update_param(struct fimc_is_hw_ip *hw_ip, struct is_region *region,
+       struct paf_rdma_param *param, u32 lindex, u32 hindex, u32 instance);
+int fimc_is_hw_paf_reset(struct fimc_is_hw_ip *hw_ip);
+#endif
index 32c4db371a562421fc070f59a5848c7fa7fbc25f..9249fb4993b1b76ce6004aeea29da236175296a7 100644 (file)
@@ -185,7 +185,7 @@ struct is_setfile_header_element {
 };
 
 #ifdef CONFIG_USE_SENSOR_GROUP
-#define MAX_ACTIVE_GROUP 7
+#define MAX_ACTIVE_GROUP 8
 #else
 #define MAX_ACTIVE_GROUP 6
 #endif
index 423d98e4e2607384612844c23ee8b36e02b9e52c..d91bd7ddb87c1275e4cc4a9312eef26a7026b5a5 100644 (file)
@@ -158,6 +158,7 @@ extern int debug_sensor;
 #endif
 
 #define GET_SSX_ID(video) (video->id - FIMC_IS_VIDEO_SS0_NUM)
+#define GET_PAFXS_ID(video) ((video->id < FIMC_IS_VIDEO_PAF1S_NUM) ? 0 : 1)
 #define GET_3XS_ID(video) ((video->id < FIMC_IS_VIDEO_31S_NUM) ? 0 : 1)
 #define GET_3XC_ID(video) ((video->id < FIMC_IS_VIDEO_31S_NUM) ? 0 : 1)
 #define GET_3XP_ID(video) ((video->id < FIMC_IS_VIDEO_31S_NUM) ? 0 : 1)
@@ -405,6 +406,11 @@ extern int debug_sensor;
 #define mdbgv_ssxvc3(fmt, this, args...) \
        mdbg_common(debug_video, "[%d][SSXVC3:V]", fmt, ((struct fimc_is_device_sensor *)this->device)->instance, ##args)
 
+#define mdbgv_paf(fmt, this, args...) \
+       mdbg_common(debug_video, "[%d][PAF%dS:V]", fmt, \
+                               ((struct fimc_is_device_ischain *)this->device)->instance, \
+                               GET_PAFXS_ID(this->video), ##args)
+
 /*
  * =================================================================================================
  * LOG - DEBUG_DEVICE
index 46f926c2a9213228a12fc25c9f69ebfc8e3146d7..2a92e8a988f42b77dfa042286317b28de0e28f5e 100644 (file)
@@ -546,7 +546,6 @@ int fimc_is_lib_isp_object_create(struct fimc_is_hw_ip *hw_ip,
 {
        int ret = 0;
        u32 chain_id, input_type, obj_info = 0;
-       struct fimc_is_group *head;
 
        FIMC_BUG(!hw_ip);
        FIMC_BUG(!this);
@@ -571,11 +570,8 @@ int fimc_is_lib_isp_object_create(struct fimc_is_hw_ip *hw_ip,
                break;
        }
 
-       head = GET_HEAD_GROUP_IN_DEVICE(FIMC_IS_DEVICE_ISCHAIN, hw_ip->group[instance_id]);
-
-       FIMC_BUG(!head);
-
-       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &head->state))
+       /* input_type : use only in 3AA (guide by DDK) */
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &hw_ip->group[instance_id]->state))
                input_type = 0; /* default */
        else
                input_type = 1;
index 13b5519293919a151cfcc5f77d3c10520ff1d80a..ee28546a71f2fa29a211b8ef6b5b04a1908ff21a 100644 (file)
@@ -59,6 +59,38 @@ int fimc_is_interface_ischain_probe(struct fimc_is_interface_ischain *this,
        /* this->regs_mcuctl = fimc_is_hw_get_sysreg(core_regs); *//* deprecated */
        this->minfo = &resourcemgr->minfo;
 
+#if defined(SOC_PAF0)
+       hw_id = DEV_HW_PAF0;
+       hw_slot = fimc_is_hw_slot_id(hw_id);
+       if (!valid_hw_slot_id(hw_slot)) {
+               err_itfc("invalid hw_slot (%d) ", hw_slot);
+               return -EINVAL;
+       }
+
+       this->itf_ip[hw_slot].hw_ip = &(hardware->hw_ip[hw_slot]);
+       ret = fimc_is_interface_paf_probe(this, hw_id, pdev);
+       if (ret) {
+               err_itfc("interface probe fail (%d,%d)", hw_id, hw_slot);
+               return -EINVAL;
+       }
+#endif
+
+#if defined(SOC_PAF1)
+       hw_id = DEV_HW_PAF1;
+       hw_slot = fimc_is_hw_slot_id(hw_id);
+       if (!valid_hw_slot_id(hw_slot)) {
+               err_itfc("invalid hw_slot (%d) ", hw_slot);
+               return -EINVAL;
+       }
+
+       this->itf_ip[hw_slot].hw_ip = &(hardware->hw_ip[hw_slot]);
+       ret = fimc_is_interface_paf_probe(this, hw_id, pdev);
+       if (ret) {
+               err_itfc("interface probe fail (%d,%d)", hw_id, hw_slot);
+               return -EINVAL;
+       }
+#endif
+
 #if defined(SOC_30S)
        hw_id = DEV_HW_3AA0;
        hw_slot = fimc_is_hw_slot_id(hw_id);
@@ -754,6 +786,51 @@ int fimc_is_interface_srdz_probe(struct fimc_is_interface_ischain *itfc,
        return ret;
 }
 
+int fimc_is_interface_paf_probe(struct fimc_is_interface_ischain *itfc,
+       int hw_id, struct platform_device *pdev)
+{
+       struct fimc_is_interface_hwip *itf_paf = NULL;
+       int ret = 0;
+       int hw_slot = -1;
+
+       FIMC_BUG(!itfc);
+       FIMC_BUG(!pdev);
+
+       hw_slot = fimc_is_hw_slot_id(hw_id);
+       if (!valid_hw_slot_id(hw_slot)) {
+               err_itfc("invalid hw_slot (%d) ", hw_slot);
+               return -EINVAL;
+       }
+
+       itf_paf = &itfc->itf_ip[hw_slot];
+       itf_paf->id = hw_id;
+       itf_paf->state = 0;
+
+       ret = fimc_is_hw_get_address(itf_paf, pdev, hw_id);
+       if (ret) {
+               err_itfc("[ID:%2d] hw_get_address failed (%d)", hw_id, ret);
+               return -EINVAL;
+       }
+
+       ret = fimc_is_hw_get_irq(itf_paf, pdev, hw_id);
+       if (ret) {
+               err_itfc("[ID:%2d] hw_get_irq failed (%d)", hw_id, ret);
+               return -EINVAL;
+       }
+
+       ret = fimc_is_hw_request_irq(itf_paf, hw_id);
+       if (ret) {
+               err_itfc("[ID:%2d] hw_request_irq failed (%d)", hw_id, ret);
+               return -EINVAL;
+       }
+
+       set_bit(IS_CHAIN_IF_STATE_INIT, &itf_paf->state);
+
+       dbg_itfc("[ID:%2d] probe done\n", hw_id);
+
+       return ret;
+}
+
 int print_fre_work_list(struct fimc_is_work_list *this)
 {
        struct fimc_is_work *work, *temp;
@@ -2529,6 +2606,10 @@ static void wq_func_shot(struct work_struct *data)
                status = msg->param2;
 
                switch (group_id) {
+               case GROUP_ID(GROUP_ID_PAF0):
+               case GROUP_ID(GROUP_ID_PAF1):
+                       group = &device->group_paf;
+                       break;
                case GROUP_ID(GROUP_ID_3AA0):
                case GROUP_ID(GROUP_ID_3AA1):
                        group = &device->group_3aa;
index 0433a2a28283c734d3dc1ceb95bf41a76c96906a..f47c871bfde899f7233bf6b865834c549795c758 100644 (file)
@@ -64,6 +64,8 @@ struct fimc_is_interface_ischain {
 int fimc_is_interface_ischain_probe(struct fimc_is_interface_ischain *this,
        struct fimc_is_hardware *hardware, struct fimc_is_resourcemgr *resourcemgr,
        struct platform_device *pdev, ulong core_regs);
+int fimc_is_interface_paf_probe(struct fimc_is_interface_ischain *itfc,
+       int hw_id, struct platform_device *pdev);
 int fimc_is_interface_3aa_probe(struct fimc_is_interface_ischain *itfc,
        int hw_id, struct platform_device *pdev);
 int fimc_is_interface_isp_probe(struct fimc_is_interface_ischain *itfc,