MLK-20326-2: ISI: enable horizonal and vertical flip for mem2mem
authorGuoniu.Zhou <guoniu.zhou@nxp.com>
Fri, 9 Nov 2018 10:48:13 +0000 (18:48 +0800)
committerLeonard Crestez <leonard.crestez@nxp.com>
Wed, 17 Apr 2019 23:51:34 +0000 (02:51 +0300)
Eanble horizonal and vertical flip for memory to memory function
of ISI

Signed-off-by: Guoniu.Zhou <guoniu.zhou@nxp.com>
drivers/media/platform/imx8/mxc-isi-m2m.c

index f8dfe02..f1c87dc 100644 (file)
@@ -855,6 +855,84 @@ static const struct v4l2_ioctl_ops mxc_isi_m2m_ioctl_ops = {
        .vidioc_streamoff               = mxc_isi_m2m_streamoff,
 };
 
+/*
+ * V4L2 controls handling
+ */
+#define ctrl_to_mxc_isi_m2m(__ctrl) \
+       container_of((__ctrl)->handler, struct mxc_isi_dev, m2m.ctrls.handler)
+
+static int mxc_isi_m2m_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct mxc_isi_dev *mxc_isi = ctrl_to_mxc_isi_m2m(ctrl);
+       unsigned long flags;
+
+       dev_dbg(&mxc_isi->pdev->dev, "%s\n", __func__);
+
+       if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
+               return 0;
+
+       spin_lock_irqsave(&mxc_isi->slock, flags);
+
+       switch (ctrl->id) {
+       case V4L2_CID_HFLIP:
+               if (ctrl->val < 0)
+                       return -EINVAL;
+               mxc_isi->m2m.hflip = (ctrl->val > 0) ? 1 : 0;
+               break;
+
+       case V4L2_CID_VFLIP:
+               if (ctrl->val < 0)
+                       return -EINVAL;
+               mxc_isi->m2m.vflip = (ctrl->val > 0) ? 1 : 0;
+               break;
+
+       default:
+               dev_err(&mxc_isi->pdev->dev, "%s: Not support %d CID\n", __func__, ctrl->id);
+               return -EINVAL;
+       }
+
+       spin_unlock_irqrestore(&mxc_isi->slock, flags);
+
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops mxc_isi_m2m_ctrl_ops = {
+       .s_ctrl = mxc_isi_m2m_s_ctrl,
+};
+
+static int mxc_isi_m2m_ctrls_create(struct mxc_isi_dev *mxc_isi)
+{
+       struct mxc_isi_ctrls *ctrls = &mxc_isi->m2m.ctrls;
+       struct v4l2_ctrl_handler *handler = &ctrls->handler;
+
+       if (mxc_isi->m2m.ctrls.ready)
+               return 0;
+
+       v4l2_ctrl_handler_init(handler, 4);
+
+       ctrls->hflip = v4l2_ctrl_new_std(handler, &mxc_isi_m2m_ctrl_ops,
+                                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       ctrls->vflip = v4l2_ctrl_new_std(handler, &mxc_isi_m2m_ctrl_ops,
+                                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+       if (!handler->error)
+               ctrls->ready = true;
+
+       return handler->error;
+
+}
+
+void mxc_isi_m2m_ctrls_delete(struct mxc_isi_dev *mxc_isi)
+{
+       struct mxc_isi_ctrls *ctrls = &mxc_isi->m2m.ctrls;
+
+       if (ctrls->ready) {
+               v4l2_ctrl_handler_free(&ctrls->handler);
+               ctrls->ready = false;
+               ctrls->alpha = NULL;
+       }
+}
+
 int mxc_isi_register_m2m_device(struct mxc_isi_dev *mxc_isi,
                                 struct v4l2_device *v4l2_dev)
 {
@@ -890,15 +968,23 @@ int mxc_isi_register_m2m_device(struct mxc_isi_dev *mxc_isi,
        vdev->vfl_dir = VFL_DIR_M2M;
        vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;
 
+       ret = mxc_isi_m2m_ctrls_create(mxc_isi);
+       if (ret)
+               goto free_m2m;
+
        ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
        if (ret < 0) {
                dev_err(dev, "%s fail to register video device\n", __func__);
-               goto free_m2m;
+               goto ctrl_free;
        }
+
+       vdev->ctrl_handler = &mxc_isi->m2m.ctrls.handler;
        video_set_drvdata(vdev, mxc_isi);
 
        return 0;
 
+ctrl_free:
+       mxc_isi_m2m_ctrls_delete(mxc_isi);
 free_m2m:
        v4l2_m2m_release(isi_m2m->m2m_dev);
        return ret;