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

From: Niklas Söderlund
Date: Tue Apr 16 2019 - 19:50:24 EST


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