Re: [RFC PATCH] media: rcar-csi2: Fix field detection

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Steve,

Thanks for your work.

I upported most rcar-csi2 patches but a few of them are still pending, 
an alternating version based on this BSP patch is already on its way.

https://patchwork.linuxtv.org/patch/55623/

As a general feedback calling v4l2_subdev_call() for g_std is not the 
best way to handle this problem in a MC centric driver. There is a 
discussion about in in earlier versions of the patch mentioned above.

On 2019-04-16 16:38:07 -0700, Steve Longerbeam wrote:
> The RCAR Gen3 hardware manual doesn't mention that the "Word Count" field
> in the MIPI CSI-2 Frame Start packet is really the frame number. FS packets
> are short packets, and short packets do not have a WC but rather a 16-bit
> data field, and for Frame synchronization packets (FS/FE) the 16-bit data
> field contains a frame number.
> 
> Here is a reprinting from the MIPI CSI-2 specification, version 2
> (section 9.1.2 Low Level Protocol Short Packet Format):
> 
> "Figure 42 and Figure 43 show the Low Level Protocol Short Packet
> structures for the D-PHY and C-PHY physical layer options, respectively.
> For each option, the Short Packet structure matches the Packet Header of
> the corresponding Low Level Protocol Long Packet structure with the
> exception that the Packet Header Word Count (WC) field shall be replaced
> by the Short Packet Data Field...For Frame Synchronization Data Types
> the Short Packet Data Field shall be the frame number..."
> 
> Also in section 9.8.1 Frame Synchronization Packets, the CSI-2 spec reads:
> 
> "The behavior of the 16-bit frame number shall be as one of the following
> - Frame number is always zero – frame number is inoperative.
> - Frame number increments by 1 for every FS packet with the same Virtual
>   Channel and is periodically reset to one e.g. 1, 2, 1, 2, 1, 2, 1, 2 or
>   1, 2, 3, 4, 1, 2, 3, 4"
> 
> So from the above, FLD_NUM in the FLD register matches against the
> frame number transmitted by the CSI-2 source in the Frame Start Packet,
> and goes as "1,2,1,2,1,2" or "1,2,3,4,...,1,2,3,4". If there is a match,
> the RCAR CSI-2 receiver declares the field as the even, e.g. the BOTTOM,
> field.
> 
> NTSC transmits bottom/even field first, and PAL and HD transmit top/odd
> field first. So fields with a frame number 1 in the CSI-2 Frame Start
> Packet are bottom/even fields for NTSC, and frame number 2 are bottom/even
> fields for PAL/HD.
> 
> But the above assumes the transmitting CSI-2 sensor is sending frame
> numbers in the sequence "1,2,1,2,...". But according to the CSI-2 spec,
> sensors are also allowed to send frame numbers that simply increment as
> in "1,2,3,4,...". To generalize to catch those cases, set FLD_DET_SEL
> to 0x01, which according to the RCAR Gen3 hardware manual means "the
> field is detected as the EVEN field when FLD_NUM[0] matches WC[0]".
> Then, the even/bottom fields have odd frame numbers for NTSC, and even
> frame numbers for PAL (this patch assumes HDMI sources will not
> implement .g_std(), so std will be 0 in that case).
> 
> Finally, set the FLD register to non-zero value only if trnsmitter is
> sending ALTERNATE fields.
> 
> Signed-off-by: Steve Longerbeam <slongerbeam@xxxxxxxxx>
> ---
>  drivers/media/platform/rcar-vin/rcar-csi2.c | 37 ++++++++++++++++++---
>  1 file changed, 32 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
> index a438ec2c218f..c5bee20d7907 100644
> --- a/drivers/media/platform/rcar-vin/rcar-csi2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
> @@ -67,6 +67,7 @@ struct rcar_csi2;
>  /* Field Detection Control */
>  #define FLD_REG				0x1c
>  #define FLD_FLD_NUM(n)			(((n) & 0xff) << 16)
> +#define FLD_FLD_DET_SEL(n)		(((n) & 0x3) << 4)
>  #define FLD_FLD_EN4			BIT(3)
>  #define FLD_FLD_EN3			BIT(2)
>  #define FLD_FLD_EN2			BIT(1)
> @@ -462,10 +463,11 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp)
>  	return mbps;
>  }
>  
> -static int rcsi2_start(struct rcar_csi2 *priv)
> +static int rcsi2_start(struct rcar_csi2 *priv, struct v4l2_subdev *nextsd)
>  {
>  	const struct rcar_csi2_format *format;
> -	u32 phycnt, vcdt = 0, vcdt2 = 0;
> +	u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0;
> +	v4l2_std_id std = 0;
>  	unsigned int i;
>  	int mbps, ret;
>  
> @@ -476,6 +478,10 @@ static int rcsi2_start(struct rcar_csi2 *priv)
>  	/* Code is validated in set_fmt. */
>  	format = rcsi2_code_to_fmt(priv->mf.code);
>  
> +	ret = v4l2_subdev_call(nextsd, video, g_std, &std);
> +	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
> +		return ret;
> +
>  	/*
>  	 * Enable all supported CSI-2 channels with virtual channel and
>  	 * data type matching.
> @@ -509,9 +515,30 @@ static int rcsi2_start(struct rcar_csi2 *priv)
>  	rcsi2_reset(priv);
>  	rcsi2_write(priv, PHTC_REG, 0);
>  
> +	/*
> +	 * NTSC standard transmits even/bottom field first, then odd/top.
> +	 * PAL standard and interlaced HD transmit odd/top field first,
> +	 * then even/bottom.
> +	 *
> +	 * For CSI-2 sensors that transmit frame numbers (in the CSI-2
> +	 * Frame Start packet) as "1,2,1,2,..." or "1,2,3,4,5,...", then:
> +	 *
> +	 * - for NTSC, the even/bottom fields have odd frame numbers.
> +	 * - for PAL and HD, the even/bottom fields have even frame numbers.
> +	 */
> +	if (priv->mf.field == V4L2_FIELD_ALTERNATE) {
> +		fld = FLD_FLD_DET_SEL(1) | FLD_FLD_EN4 | FLD_FLD_EN3 |
> +			FLD_FLD_EN2 | FLD_FLD_EN;
> +
> +		if (std & V4L2_STD_525_60)
> +			fld |= FLD_FLD_NUM(1); /* NTSC */
> +		else
> +			fld |= FLD_FLD_NUM(0); /* PAL or HD */
> +	}
> +
>  	/* Configure */
> -	rcsi2_write(priv, FLD_REG, FLD_FLD_NUM(2) | FLD_FLD_EN4 |
> -		    FLD_FLD_EN3 | FLD_FLD_EN2 | FLD_FLD_EN);
> +	rcsi2_write(priv, FLD_REG, fld);
> +
>  	rcsi2_write(priv, VCDT_REG, vcdt);
>  	if (vcdt2)
>  		rcsi2_write(priv, VCDT2_REG, vcdt2);
> @@ -591,7 +618,7 @@ static int rcsi2_s_stream(struct v4l2_subdev *sd, int enable)
>  	if (enable && priv->stream_count == 0) {
>  		pm_runtime_get_sync(priv->dev);
>  
> -		ret = rcsi2_start(priv);
> +		ret = rcsi2_start(priv, nextsd);
>  		if (ret) {
>  			pm_runtime_put(priv->dev);
>  			goto out;
> -- 
> 2.17.1
> 

-- 
Regards,
Niklas Söderlund



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux