i.mx8mq and ov8865 base address switching change error

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i.mx8mq and ov8865 base address switching change error

1,132 Views
ohporter
Contributor I

I'm enabling an ov8865 sensor on the 5.4.24 kernel on a Variscite DART-8M board.

I've made the following modifications:

  • Added support for SBGGT10 in mx6s_capture.c
  • Set the clk and clk_ui to maximum rates as recommended in other posts:

 

assigned-clock-rates = <266000000>, <333000000>, <66000000>;

 

  • Configured bridge, phy, and sensor for 4 lanes 

I'm able to capture single frames. However, I see the following issues:

  1. Intermittently, perhaps 15-20% of single frame captures good data whereas the other captures are whereas the other captured frames have repeated data
  2. Most importantly, when capturing multiple frames (after the first frame completes), the bridge driver reports base address switching Change Err. (when debug is enabled) and fails fill the next queued buffer. This condition continues for each dma transfer complete interrupt until the capture process is manually stopped.

Following previous posts, I don't see any clear guidelines on the possible root causes of the base address switching Change Err. What are the possible causes of this error?

Labels (1)
0 Kudos
7 Replies

1,126 Views
igorpadykov
NXP Employee
NXP Employee

Hi ohporter

 

in general 'base address switching change' error can be in two cases:

1: CSI DMA can't transfer data from CSI FIFO to DDR RAM in time, for this case may be suggested
to check that used latest BSP & latest DDR RPA tools.

2: CSI data format is configured wrongly.

 

Error happens when frame switching occurs before DMA complete to transfer the data. This base address switch is used only when receiving interlaced data (like the signals from TV decoders). If interlaced data

is not used then seems camera driver is not setting correctly the video format.

 

Best regards
igor

0 Kudos

1,119 Views
ohporter
Contributor I

Hi igor,

Thanks for the helpful response.

The statement that base address switch should only be used in conjunction with interlaced data concerns me because this does not seem to be the case in NXP BSP (5.4.24 or 5.4.47 are the same in this respect). mx6s_capture.c enables base address switching by default on i.mx8mq when the bridge is reset.

static const struct mx6s_csi_soc mx8mq_soc = {
        .rx_fifo_rst = true,
        .baseaddr_switch = 0x80030,
};

and in csisw_reset():

cr18 |= csi_dev->soc->baseaddr_switch;

Immediately after csisw_reset() is called, the interlaced check is performed but this base address switching default is never disabled even in non-interlaced mode:

if (pix->field == V4L2_FIELD_INTERLACED)
   csi_tvdec_enable(csi_dev, true);

If base address switching should not be used then it appears the supplied driver is incorrect and should actually be:

if (pix->field == V4L2_FIELD_INTERLACED)
   csi_tvdec_enable(csi_dev, true);
else
   csi_tvdec_enable(csi_dev, false);

or just disable base address switching in the defaults for i.mx8mq as follows:

static const struct mx6s_csi_soc mx8mq_soc = {
        .rx_fifo_rst = true,
        .baseaddr_switch = 0,
};

It seems odd that the struct mx8mq_soc struct explicitly turns on base address switching by default (while older socs have it off by default) if it only should be used for interlaced video. If you could confirm that the mx6s_capture.c driver incorrectly handles base address switching enable/disable that would help.

 

0 Kudos

1,113 Views
igorpadykov
NXP Employee
NXP Employee

what bsp used in the case, base address switching is enabled below:

static int mx6s_configure_csi(struct mx6s_csi_dev *csi_dev)
{
	struct v4l2_pix_format *pix = &csi_dev->pix;
	u32 cr1, cr18;
	u32 width;

	if (pix->field == V4L2_FIELD_INTERLACED) {
		csi_deinterlace_enable(csi_dev, true);

 

https://source.codeaurora.org/external/imx/linux-imx/tree/drivers/media/platform/mxc/capture/mx6s_ca...

 

Best regards
igor

0 Kudos

1,105 Views
ohporter
Contributor I

I'm using https://source.codeaurora.org/external/imx/linux-imx/tree/drivers/media/platform/mxc/capture/mx6s_ca... which has no functional changes in this driver versus 5.4.47_2.2.0 (just a switch to use the generic vb2_fop_mmap in the mx6s_csi_fops).

In csi_deinterlace_enable, there is no configuration of base address switching at all:

static void csi_deinterlace_enable(struct mx6s_csi_dev *csi_dev, bool enable)
{
	unsigned long cr18 = __raw_readl(csi_dev->regbase + CSI_CSICR18);

	if (enable == true)
		cr18 |= BIT_DEINTERLACE_EN;
	else
		cr18 &= ~BIT_DEINTERLACE_EN;

	__raw_writel(cr18, csi_dev->regbase + CSI_CSICR18);
}

I can confirm that my pix->field is not equal to V4L2_FIELD_INTERLACED in any case so DEINTERLACE_EN is off as expected.

The base address switching is unconditionally enabled for i.mx8qm as part of csisw_reset() in  https://source.codeaurora.org/external/imx/linux-imx/tree/drivers/media/platform/mxc/capture/mx6s_c...

using the cr18 value defined in https://source.codeaurora.org/external/imx/linux-imx/tree/drivers/media/platform/mxc/capture/mx6s_ca...

The value, 0x80030, corresponds to:

  • MASK_OPTION
    • 02 - Writing to memory from second completely frame, when using this option, the CSI_ENABLE should be 1.
  • BASEADDR_SWITCH_SEL
    • 1 - Switching base address at the edge of the first data of each frame
  • BASEADDR_SWITCH_EN
    • When this bit is enabled, CSI DMA will switch the base address according to BASEADDR_SWITCH_SEL rather than atomically by DMA completed

This seems to demonstrate that base address switching is always enabled in the current driver on i.mx8mq parts, it's not specific to interlaced mode at all.

0 Kudos

1,003 Views
jgsandom
Contributor III

Hi @ohporter,

I have come across the issue where streaming works around 50% of the time - if it works correctly on power up, then will continue to work as I start and stop streaming. However, if it doesn't work from power up, then the base address switching error will occur each time streaming is stopped and started.

I have basically come to the exact same conclusion as you have with regards to the base address switching change error. I've seen various posts about the BASEADDR_SWITCH_EN only being applicable to interlaced video sources. However, there isn't anything in the documentation which suggests this (that I can see anyway) + it's strange that the default baseaddress_switch is 0x80030 for IMX8MQ.

I tried the following on the consideration that BASEADDR_SWITCH_EN + related fields are only relevant for interlaced modes. Here is the patch;

if (pix->field == V4L2_FIELD_INTERLACED)
   csi_tvdec_enable(csi_dev, true);
+else
+   csi_tvdec_enable(csi_dev, false);

 The outcome was that, the base address switching error no longer occurred as the interrupt was disabled. However, the 50% of the time it didn't work - the FPS drops and the resulting output has a lot of repeated data overlaid onto each other.

Did you ever manage to fix this issue? it would be really helpful if you could share your experience since last posting!

Thank you.

0 Kudos

1,092 Views
igorpadykov
NXP Employee
NXP Employee

>The base address switching is unconditionally enabled for i.mx8qm as part of csisw_reset()

 

sorry I can not agree.  Function csisw_reset() is called with "csi_dev" argument and

It can be false or true, depending on "csi_dev" structure data,

static void csisw_reset(struct mx6s_csi_dev *csi_dev)
{
..
		cr18 |= csi_dev->soc->baseaddr_switch;

 Best regards
igor

0 Kudos

1,086 Views
ohporter
Contributor I

On i.mx8mq, the value is 0x80030 so base address switching is always enabled. It's only the case on i.mx6s/i.mx6sl that base address switching is disabled since the per-soc value is 0 in that case.

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_soc,
        },
        { .compatible = "fsl,imx6sl-csi",
          .data = &mx6sl_soc,
        },
        { .compatible = "fsl,imx8mq-csi",
          .data = &mx8mq_soc,
        },
        { /* sentinel */ }
};                          
MODULE_DEVICE_TABLE(of, mx6s_csi_dt_ids);
0 Kudos