Merge tag 'media/v6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[linux-2.6-microblaze.git] / drivers / media / platform / rockchip / rkisp1 / rkisp1-capture.c
index c381c22..2bddb4f 100644 (file)
@@ -47,13 +47,18 @@ enum rkisp1_plane {
  * @fourcc: pixel format
  * @fmt_type: helper filed for pixel format
  * @uv_swap: if cb cr swapped, for yuv
+ * @yc_swap: if y and cb/cr swapped, for yuv
+ * @byte_swap: if byte pairs are swapped, for raw
  * @write_format: defines how YCbCr self picture data is written to memory
- * @output_format: defines sp output format
+ * @output_format: defines the output format (RKISP1_CIF_MI_INIT_MP_OUTPUT_* for
+ *     the main path and RKISP1_MI_CTRL_SP_OUTPUT_* for the self path)
  * @mbus: the mbus code on the src resizer pad that matches the pixel format
  */
 struct rkisp1_capture_fmt_cfg {
        u32 fourcc;
-       u8 uv_swap;
+       u32 uv_swap : 1;
+       u32 yc_swap : 1;
+       u32 byte_swap : 1;
        u32 write_format;
        u32 output_format;
        u32 mbus;
@@ -94,36 +99,50 @@ static const struct rkisp1_capture_fmt_cfg rkisp1_mp_fmts[] = {
                .fourcc = V4L2_PIX_FMT_YUYV,
                .uv_swap = 0,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUVINT,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV422,
+               .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
+       }, {
+               .fourcc = V4L2_PIX_FMT_UYVY,
+               .uv_swap = 0,
+               .yc_swap = 1,
+               .write_format = RKISP1_MI_CTRL_MP_WRITE_YUVINT,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV422,
                .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
        }, {
                .fourcc = V4L2_PIX_FMT_YUV422P,
                .uv_swap = 0,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV422,
                .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
        }, {
                .fourcc = V4L2_PIX_FMT_NV16,
                .uv_swap = 0,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV422,
                .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
        }, {
                .fourcc = V4L2_PIX_FMT_NV61,
                .uv_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV422,
                .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
        }, {
                .fourcc = V4L2_PIX_FMT_NV16M,
                .uv_swap = 0,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV422,
                .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
        }, {
                .fourcc = V4L2_PIX_FMT_NV61M,
                .uv_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV422,
                .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
        }, {
                .fourcc = V4L2_PIX_FMT_YVU422M,
                .uv_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV422,
                .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
        },
        /* yuv400 */
@@ -131,6 +150,7 @@ static const struct rkisp1_capture_fmt_cfg rkisp1_mp_fmts[] = {
                .fourcc = V4L2_PIX_FMT_GREY,
                .uv_swap = 0,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV400,
                .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
        },
        /* yuv420 */
@@ -138,81 +158,107 @@ static const struct rkisp1_capture_fmt_cfg rkisp1_mp_fmts[] = {
                .fourcc = V4L2_PIX_FMT_NV21,
                .uv_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV420,
                .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
        }, {
                .fourcc = V4L2_PIX_FMT_NV12,
                .uv_swap = 0,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV420,
                .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
        }, {
                .fourcc = V4L2_PIX_FMT_NV21M,
                .uv_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV420,
                .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
        }, {
                .fourcc = V4L2_PIX_FMT_NV12M,
                .uv_swap = 0,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV420,
                .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
        }, {
                .fourcc = V4L2_PIX_FMT_YUV420,
                .uv_swap = 0,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV420,
                .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
        }, {
                .fourcc = V4L2_PIX_FMT_YVU420,
                .uv_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_YUV420,
                .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
        },
        /* raw */
        {
                .fourcc = V4L2_PIX_FMT_SRGGB8,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW8,
                .mbus = MEDIA_BUS_FMT_SRGGB8_1X8,
        }, {
                .fourcc = V4L2_PIX_FMT_SGRBG8,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW8,
                .mbus = MEDIA_BUS_FMT_SGRBG8_1X8,
        }, {
                .fourcc = V4L2_PIX_FMT_SGBRG8,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW8,
                .mbus = MEDIA_BUS_FMT_SGBRG8_1X8,
        }, {
                .fourcc = V4L2_PIX_FMT_SBGGR8,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW8,
                .mbus = MEDIA_BUS_FMT_SBGGR8_1X8,
        }, {
                .fourcc = V4L2_PIX_FMT_SRGGB10,
+               .byte_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW10,
                .mbus = MEDIA_BUS_FMT_SRGGB10_1X10,
        }, {
                .fourcc = V4L2_PIX_FMT_SGRBG10,
+               .byte_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW10,
                .mbus = MEDIA_BUS_FMT_SGRBG10_1X10,
        }, {
                .fourcc = V4L2_PIX_FMT_SGBRG10,
+               .byte_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW10,
                .mbus = MEDIA_BUS_FMT_SGBRG10_1X10,
        }, {
                .fourcc = V4L2_PIX_FMT_SBGGR10,
+               .byte_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW10,
                .mbus = MEDIA_BUS_FMT_SBGGR10_1X10,
        }, {
                .fourcc = V4L2_PIX_FMT_SRGGB12,
+               .byte_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW12,
                .mbus = MEDIA_BUS_FMT_SRGGB12_1X12,
        }, {
                .fourcc = V4L2_PIX_FMT_SGRBG12,
+               .byte_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW12,
                .mbus = MEDIA_BUS_FMT_SGRBG12_1X12,
        }, {
                .fourcc = V4L2_PIX_FMT_SGBRG12,
+               .byte_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW12,
                .mbus = MEDIA_BUS_FMT_SGBRG12_1X12,
        }, {
                .fourcc = V4L2_PIX_FMT_SBGGR12,
+               .byte_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+               .output_format = RKISP1_CIF_MI_INIT_MP_OUTPUT_RAW12,
                .mbus = MEDIA_BUS_FMT_SBGGR12_1X12,
        },
 };
@@ -229,6 +275,13 @@ static const struct rkisp1_capture_fmt_cfg rkisp1_sp_fmts[] = {
                .write_format = RKISP1_MI_CTRL_SP_WRITE_INT,
                .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
                .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
+       }, {
+               .fourcc = V4L2_PIX_FMT_UYVY,
+               .uv_swap = 0,
+               .yc_swap = 1,
+               .write_format = RKISP1_MI_CTRL_SP_WRITE_INT,
+               .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
+               .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
        }, {
                .fourcc = V4L2_PIX_FMT_YUV422P,
                .uv_swap = 0,
@@ -442,6 +495,14 @@ static void rkisp1_mp_config(struct rkisp1_capture *cap)
        rkisp1_write(rkisp1, cap->config->mi.cr_size_init,
                     rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR));
 
+       if (rkisp1_has_feature(rkisp1, MAIN_STRIDE)) {
+               rkisp1_write(rkisp1, RKISP1_CIF_MI_MP_Y_LLENGTH, cap->stride);
+               rkisp1_write(rkisp1, RKISP1_CIF_MI_MP_Y_PIC_WIDTH, pixm->width);
+               rkisp1_write(rkisp1, RKISP1_CIF_MI_MP_Y_PIC_HEIGHT, pixm->height);
+               rkisp1_write(rkisp1, RKISP1_CIF_MI_MP_Y_PIC_SIZE,
+                            cap->stride * pixm->height);
+       }
+
        rkisp1_irq_frame_end_enable(cap);
 
        /* set uv swapping for semiplanar formats */
@@ -454,6 +515,25 @@ static void rkisp1_mp_config(struct rkisp1_capture *cap)
                rkisp1_write(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL, reg);
        }
 
+       /*
+        * U/V swapping with the MI_XTD_FORMAT_CTRL register only works for
+        * NV12/NV21 and NV16/NV61, so instead use byte swap to support UYVY.
+        * YVYU and VYUY cannot be supported with this method.
+        */
+       if (rkisp1_has_feature(rkisp1, MAIN_STRIDE)) {
+               reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_OUTPUT_ALIGN_FORMAT);
+               if (cap->pix.cfg->yc_swap || cap->pix.cfg->byte_swap)
+                       reg |= RKISP1_CIF_OUTPUT_ALIGN_FORMAT_MP_BYTE_SWAP_BYTES;
+               else
+                       reg &= ~RKISP1_CIF_OUTPUT_ALIGN_FORMAT_MP_BYTE_SWAP_BYTES;
+
+               reg |= RKISP1_CIF_OUTPUT_ALIGN_FORMAT_MP_LSB_ALIGNMENT;
+               rkisp1_write(rkisp1, RKISP1_CIF_MI_OUTPUT_ALIGN_FORMAT, reg);
+
+               rkisp1_write(rkisp1, RKISP1_CIF_MI_INIT,
+                            cap->pix.cfg->output_format);
+       }
+
        rkisp1_mi_config_ctrl(cap);
 
        reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL);
@@ -479,11 +559,11 @@ static void rkisp1_sp_config(struct rkisp1_capture *cap)
        rkisp1_write(rkisp1, cap->config->mi.cr_size_init,
                     rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR));
 
-       rkisp1_write(rkisp1, RKISP1_CIF_MI_SP_Y_LLENGTH, cap->sp_y_stride);
+       rkisp1_write(rkisp1, RKISP1_CIF_MI_SP_Y_LLENGTH, cap->stride);
        rkisp1_write(rkisp1, RKISP1_CIF_MI_SP_Y_PIC_WIDTH, pixm->width);
        rkisp1_write(rkisp1, RKISP1_CIF_MI_SP_Y_PIC_HEIGHT, pixm->height);
        rkisp1_write(rkisp1, RKISP1_CIF_MI_SP_Y_PIC_SIZE,
-                    cap->sp_y_stride * pixm->height);
+                    cap->stride * pixm->height);
 
        rkisp1_irq_frame_end_enable(cap);
 
@@ -497,6 +577,20 @@ static void rkisp1_sp_config(struct rkisp1_capture *cap)
                rkisp1_write(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL, reg);
        }
 
+       /*
+        * U/V swapping with the MI_XTD_FORMAT_CTRL register only works for
+        * NV12/NV21 and NV16/NV61, so instead use byte swap to support UYVY.
+        * YVYU and VYUY cannot be supported with this method.
+        */
+       if (rkisp1_has_feature(rkisp1, MAIN_STRIDE)) {
+               reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_OUTPUT_ALIGN_FORMAT);
+               if (cap->pix.cfg->yc_swap)
+                       reg |= RKISP1_CIF_OUTPUT_ALIGN_FORMAT_SP_BYTE_SWAP_BYTES;
+               else
+                       reg &= ~RKISP1_CIF_OUTPUT_ALIGN_FORMAT_SP_BYTE_SWAP_BYTES;
+               rkisp1_write(rkisp1, RKISP1_CIF_MI_OUTPUT_ALIGN_FORMAT, reg);
+       }
+
        rkisp1_mi_config_ctrl(cap);
 
        mi_ctrl = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL);
@@ -640,11 +734,13 @@ static void rkisp1_dummy_buf_destroy(struct rkisp1_capture *cap)
 
 static void rkisp1_set_next_buf(struct rkisp1_capture *cap)
 {
+       u8 shift = rkisp1_has_feature(cap->rkisp1, DMA_34BIT) ? 2 : 0;
+
        cap->buf.curr = cap->buf.next;
        cap->buf.next = NULL;
 
        if (!list_empty(&cap->buf.queue)) {
-               u32 *buff_addr;
+               dma_addr_t *buff_addr;
 
                cap->buf.next = list_first_entry(&cap->buf.queue, struct rkisp1_buffer, queue);
                list_del(&cap->buf.next->queue);
@@ -652,7 +748,7 @@ static void rkisp1_set_next_buf(struct rkisp1_capture *cap)
                buff_addr = cap->buf.next->buff_addr;
 
                rkisp1_write(cap->rkisp1, cap->config->mi.y_base_ad_init,
-                            buff_addr[RKISP1_PLANE_Y]);
+                            buff_addr[RKISP1_PLANE_Y] >> shift);
                /*
                 * In order to support grey format we capture
                 * YUV422 planar format from the camera and
@@ -661,17 +757,17 @@ static void rkisp1_set_next_buf(struct rkisp1_capture *cap)
                if (cap->pix.cfg->fourcc == V4L2_PIX_FMT_GREY) {
                        rkisp1_write(cap->rkisp1,
                                     cap->config->mi.cb_base_ad_init,
-                                    cap->buf.dummy.dma_addr);
+                                    cap->buf.dummy.dma_addr >> shift);
                        rkisp1_write(cap->rkisp1,
                                     cap->config->mi.cr_base_ad_init,
-                                    cap->buf.dummy.dma_addr);
+                                    cap->buf.dummy.dma_addr >> shift);
                } else {
                        rkisp1_write(cap->rkisp1,
                                     cap->config->mi.cb_base_ad_init,
-                                    buff_addr[RKISP1_PLANE_CB]);
+                                    buff_addr[RKISP1_PLANE_CB] >> shift);
                        rkisp1_write(cap->rkisp1,
                                     cap->config->mi.cr_base_ad_init,
-                                    buff_addr[RKISP1_PLANE_CR]);
+                                    buff_addr[RKISP1_PLANE_CR] >> shift);
                }
        } else {
                /*
@@ -679,11 +775,11 @@ static void rkisp1_set_next_buf(struct rkisp1_capture *cap)
                 * throw data if there is no available buffer.
                 */
                rkisp1_write(cap->rkisp1, cap->config->mi.y_base_ad_init,
-                            cap->buf.dummy.dma_addr);
+                            cap->buf.dummy.dma_addr >> shift);
                rkisp1_write(cap->rkisp1, cap->config->mi.cb_base_ad_init,
-                            cap->buf.dummy.dma_addr);
+                            cap->buf.dummy.dma_addr >> shift);
                rkisp1_write(cap->rkisp1, cap->config->mi.cr_base_ad_init,
-                            cap->buf.dummy.dma_addr);
+                            cap->buf.dummy.dma_addr >> shift);
        }
 
        /* Set plane offsets */
@@ -722,6 +818,7 @@ irqreturn_t rkisp1_capture_isr(int irq, void *ctx)
 {
        struct device *dev = ctx;
        struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
+       unsigned int dev_count = rkisp1_path_count(rkisp1);
        unsigned int i;
        u32 status;
 
@@ -734,7 +831,7 @@ irqreturn_t rkisp1_capture_isr(int irq, void *ctx)
 
        rkisp1_write(rkisp1, RKISP1_CIF_MI_ICR, status);
 
-       for (i = 0; i < ARRAY_SIZE(rkisp1->capture_devs); ++i) {
+       for (i = 0; i < dev_count; ++i) {
                struct rkisp1_capture *cap = &rkisp1->capture_devs[i];
 
                if (!(status & RKISP1_CIF_MI_FRAME(cap)))
@@ -891,6 +988,7 @@ static void rkisp1_cap_stream_enable(struct rkisp1_capture *cap)
 {
        struct rkisp1_device *rkisp1 = cap->rkisp1;
        struct rkisp1_capture *other = &rkisp1->capture_devs[cap->id ^ 1];
+       bool has_self_path = rkisp1_has_feature(rkisp1, SELF_PATH);
 
        cap->ops->set_data_path(cap);
        cap->ops->config(cap);
@@ -899,19 +997,40 @@ static void rkisp1_cap_stream_enable(struct rkisp1_capture *cap)
        spin_lock_irq(&cap->buf.lock);
        rkisp1_set_next_buf(cap);
        cap->ops->enable(cap);
-       /* It's safe to configure ACTIVE and SHADOW registers for the
-        * first stream. While when the second is starting, do NOT
-        * force update because it also updates the first one.
+
+       /*
+        * It's safe to configure ACTIVE and SHADOW registers for the first
+        * stream. While when the second is starting, do NOT force update
+        * because it also updates the first one.
         *
-        * The latter case would drop one more buffer(that is 2) since
-        * there's no buffer in a shadow register when the second FE received.
-        * This's also required because the second FE maybe corrupt
-        * especially when run at 120fps.
+        * The latter case would drop one more buffer(that is 2) since there's
+        * no buffer in a shadow register when the second FE received. This's
+        * also required because the second FE maybe corrupt especially when
+        * run at 120fps.
         */
-       if (!other->is_streaming) {
-               /* force cfg update */
-               rkisp1_write(rkisp1, RKISP1_CIF_MI_INIT,
-                            RKISP1_CIF_MI_INIT_SOFT_UPD);
+       if (!has_self_path || !other->is_streaming) {
+               u32 reg;
+
+               /*
+                * Force cfg update.
+                *
+                * The ISP8000 (implementing the MAIN_STRIDE feature) as a
+                * mp_output_format field in the CIF_MI_INIT register that must
+                * be preserved. It can be read back, but it is not clear what
+                * other register bits will return. Mask them out.
+                *
+                * On Rockchip platforms, the CIF_MI_INIT register is marked as
+                * write-only and reads as zeros. We can skip reading it.
+                */
+               if (rkisp1_has_feature(rkisp1, MAIN_STRIDE))
+                       reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_INIT)
+                           & RKISP1_CIF_MI_INIT_MP_OUTPUT_MASK;
+               else
+                       reg = 0;
+
+               reg |= RKISP1_CIF_MI_INIT_SOFT_UPD;
+               rkisp1_write(rkisp1, RKISP1_CIF_MI_INIT, reg);
+
                rkisp1_set_next_buf(cap);
        }
        spin_unlock_irq(&cap->buf.lock);
@@ -1095,8 +1214,8 @@ static const struct vb2_ops rkisp1_vb2_ops = {
  */
 
 static const struct v4l2_format_info *
-rkisp1_fill_pixfmt(struct v4l2_pix_format_mplane *pixm,
-                  enum rkisp1_stream_id id)
+rkisp1_fill_pixfmt(const struct rkisp1_capture *cap,
+                  struct v4l2_pix_format_mplane *pixm)
 {
        struct v4l2_plane_pix_format *plane_y = &pixm->plane_fmt[0];
        const struct v4l2_format_info *info;
@@ -1109,10 +1228,13 @@ rkisp1_fill_pixfmt(struct v4l2_pix_format_mplane *pixm,
 
        /*
         * The SP supports custom strides, expressed as a number of pixels for
-        * the Y plane. Clamp the stride to a reasonable value to avoid integer
-        * overflows when calculating the bytesperline and sizeimage values.
+        * the Y plane, and so does the MP in ISP versions that have the
+        * MAIN_STRIDE feature. Clamp the stride to a reasonable value to avoid
+        * integer overflows when calculating the bytesperline and sizeimage
+        * values.
         */
-       if (id == RKISP1_SELFPATH)
+       if (cap->id == RKISP1_SELFPATH ||
+           rkisp1_has_feature(cap->rkisp1, MAIN_STRIDE))
                stride = clamp(DIV_ROUND_UP(plane_y->bytesperline, info->bpp[0]),
                               pixm->width, 65536U);
        else
@@ -1147,10 +1269,14 @@ rkisp1_fill_pixfmt(struct v4l2_pix_format_mplane *pixm,
 static const struct rkisp1_capture_fmt_cfg *
 rkisp1_find_fmt_cfg(const struct rkisp1_capture *cap, const u32 pixelfmt)
 {
+       bool yc_swap_support = rkisp1_has_feature(cap->rkisp1, MAIN_STRIDE);
        unsigned int i;
 
        for (i = 0; i < cap->config->fmt_size; i++) {
-               if (cap->config->fmts[i].fourcc == pixelfmt)
+               const struct rkisp1_capture_fmt_cfg *fmt = &cap->config->fmts[i];
+
+               if (fmt->fourcc == pixelfmt &&
+                   (!fmt->yc_swap || yc_swap_support))
                        return &cap->config->fmts[i];
        }
        return NULL;
@@ -1187,7 +1313,7 @@ static void rkisp1_try_fmt(const struct rkisp1_capture *cap,
        pixm->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
        pixm->quantization = V4L2_QUANTIZATION_DEFAULT;
 
-       info = rkisp1_fill_pixfmt(pixm, cap->id);
+       info = rkisp1_fill_pixfmt(cap, pixm);
 
        if (fmt_cfg)
                *fmt_cfg = fmt;
@@ -1199,12 +1325,9 @@ static void rkisp1_set_fmt(struct rkisp1_capture *cap,
                           struct v4l2_pix_format_mplane *pixm)
 {
        rkisp1_try_fmt(cap, pixm, &cap->pix.cfg, &cap->pix.info);
-       cap->pix.fmt = *pixm;
 
-       /* SP supports custom stride in number of pixels of the Y plane */
-       if (cap->id == RKISP1_SELFPATH)
-               cap->sp_y_stride = pixm->plane_fmt[0].bytesperline /
-                                  cap->pix.info->bpp[0];
+       cap->pix.fmt = *pixm;
+       cap->stride = pixm->plane_fmt[0].bytesperline / cap->pix.info->bpp[0];
 }
 
 static int rkisp1_try_fmt_vid_cap_mplane(struct file *file, void *fh,
@@ -1222,23 +1345,29 @@ static int rkisp1_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
 {
        struct rkisp1_capture *cap = video_drvdata(file);
        const struct rkisp1_capture_fmt_cfg *fmt = NULL;
+       bool yc_swap_support = rkisp1_has_feature(cap->rkisp1, MAIN_STRIDE);
        unsigned int i, n = 0;
 
-       if (!f->mbus_code) {
-               if (f->index >= cap->config->fmt_size)
-                       return -EINVAL;
+       if (f->index >= cap->config->fmt_size)
+               return -EINVAL;
 
+       if (!f->mbus_code && yc_swap_support) {
                fmt = &cap->config->fmts[f->index];
                f->pixelformat = fmt->fourcc;
                return 0;
        }
 
        for (i = 0; i < cap->config->fmt_size; i++) {
-               if (cap->config->fmts[i].mbus != f->mbus_code)
+               fmt = &cap->config->fmts[i];
+
+               if (f->mbus_code && fmt->mbus != f->mbus_code)
+                       continue;
+
+               if (!yc_swap_support && fmt->yc_swap)
                        continue;
 
                if (n++ == f->index) {
-                       f->pixelformat = cap->config->fmts[i].fourcc;
+                       f->pixelformat = fmt->fourcc;
                        return 0;
                }
        }
@@ -1501,10 +1630,11 @@ rkisp1_capture_init(struct rkisp1_device *rkisp1, enum rkisp1_stream_id id)
 
 int rkisp1_capture_devs_register(struct rkisp1_device *rkisp1)
 {
+       unsigned int dev_count = rkisp1_path_count(rkisp1);
        unsigned int i;
        int ret;
 
-       for (i = 0; i < ARRAY_SIZE(rkisp1->capture_devs); i++) {
+       for (i = 0; i < dev_count; i++) {
                struct rkisp1_capture *cap = &rkisp1->capture_devs[i];
 
                rkisp1_capture_init(rkisp1, i);