MLK-19362: media: csi: Fix "Hresponse" and "Rx fifo overflow" camera errors
authorMirela Rabulea <mirela.rabulea@nxp.com>
Wed, 12 Sep 2018 08:50:54 +0000 (11:50 +0300)
committerRobby Cai <robby.cai@nxp.com>
Thu, 18 Apr 2019 10:21:34 +0000 (18:21 +0800)
When the register setting for fifo_send_level is set to high, some residual
data of a frame which cannot fill up to the send_level, will be sent with
the next frame data. In this case, for CSI receive dma, sometimes,
the vertical blanking is too short to finish the storage of the previous
frame before the next frame start, depending on the system bandwidth.

Tested on imx8mq-evk rev B4 and B3, with OV5640 camera.

This patch was proposed by Tom Zheng <haidong.zheng@nxp.com>

Signed-off-by: Mirela Rabulea <mirela.rabulea@nxp.com>
Reviewed-by: Robby Cai <robby.cai@nxp.com>
(cherry picked from commit 12f811f934b53008a445c3af67f1f22baea98a86)

drivers/media/platform/mxc/capture/mx6s_capture.c

index a3ce1cc..f57817a 100644 (file)
@@ -295,6 +295,11 @@ struct mx6s_csi_mux {
        u8 req_bit;
 };
 
+struct mx6s_csi_soc {
+       bool rx_fifo_rst;
+       int baseaddr_switch;
+};
+
 struct mx6s_csi_dev {
        struct device           *dev;
        struct video_device *vdev;
@@ -341,7 +346,7 @@ struct mx6s_csi_dev {
 
        bool csi_mipi_mode;
        bool csi_two_8bit_sensor_mode;
-       const bool *rx_fifo_rst;
+       const struct mx6s_csi_soc *soc;
        struct mx6s_csi_mux csi_mux;
 };
 
@@ -447,7 +452,9 @@ static void csisw_reset(struct mx6s_csi_dev *csi_dev)
        isr = csi_read(csi_dev, CSI_CSISR);
        csi_write(csi_dev, isr, CSI_CSISR);
 
-       /* Ensable csi  */
+       cr18 |= csi_dev->soc->baseaddr_switch;
+
+       /* Enable csi  */
        cr18 |= BIT_CSI_ENABLE;
        csi_write(csi_dev, cr18, CSI_CSICR18);
 }
@@ -859,7 +866,7 @@ static int mx6s_configure_csi(struct mx6s_csi_dev *csi_dev)
                csi_write(csi_dev, cr1, CSI_CSICR1);
 
                cr18 = csi_read(csi_dev, CSI_CSICR18);
-               cr18 &= BIT_MIPI_DATA_FORMAT_MASK;
+               cr18 &= ~BIT_MIPI_DATA_FORMAT_MASK;
                cr18 |= BIT_DATA_FROM_MIPI;
 
                switch (csi_dev->fmt->pixelformat) {
@@ -1104,7 +1111,7 @@ static irqreturn_t mx6s_csi_irq_handler(int irq, void *data)
 
        if (status & BIT_RFF_OR_INT) {
                dev_warn(csi_dev->dev, "%s Rx fifo overflow\n", __func__);
-               if (*csi_dev->rx_fifo_rst)
+               if (csi_dev->soc->rx_fifo_rst)
                        csi_error_recovery(csi_dev);
        }
 
@@ -1899,7 +1906,7 @@ static int mx6s_csi_probe(struct platform_device *pdev)
        of_id = of_match_node(mx6s_csi_dt_ids, csi_dev->dev->of_node);
        if (!of_id)
                return -EINVAL;
-       csi_dev->rx_fifo_rst = of_id->data;
+       csi_dev->soc = of_id->data;
 
        snprintf(csi_dev->v4l2_dev.name,
                 sizeof(csi_dev->v4l2_dev.name), "CSI");
@@ -1999,15 +2006,28 @@ static const struct dev_pm_ops mx6s_csi_pm_ops = {
        SET_RUNTIME_PM_OPS(mx6s_csi_runtime_suspend, mx6s_csi_runtime_resume, NULL)
 };
 
-static const u8 mx6s_fifo_rst = true;
-static const u8 mx6sl_fifo_rst = false;
+static const struct mx6s_csi_soc mx6s_soc = {
+       .rx_fifo_rst = true,
+       .baseaddr_switch = 0,
+};
+static const struct mx6s_csi_soc mx6sl_soc = {
+       .rx_fifo_rst = false,
+       .baseaddr_switch = 0,
+};
+static const struct mx6s_csi_soc mx8mq_soc = {
+       .rx_fifo_rst = true,
+       .baseaddr_switch = 0x80030,
+};
 
 static const struct of_device_id mx6s_csi_dt_ids[] = {
        { .compatible = "fsl,imx6s-csi",
-         .data = &mx6s_fifo_rst,
+         .data = &mx6s_soc,
        },
        { .compatible = "fsl,imx6sl-csi",
-         .data = &mx6sl_fifo_rst,
+         .data = &mx6sl_soc,
+       },
+       { .compatible = "fsl,imx8mq-csi",
+         .data = &mx8mq_soc,
        },
        { /* sentinel */ }
 };