gpu: ipu-csi: Swap fields according to input/output field types
Subsystems (7)
Steve Longerbeam
maintainerPATCH v6 1/1 gpu: ipu-csi: Swap fields according to input/output field types
The function ipu_csi_init_interface() was inverting the F-bit for NTSC case, in the CCIR_CODE_1/2 registers. The result being that for NTSC bottom-top field order, the CSI would swap fields and capture in top-bottom order.
Instead, base field swap on the field order of the input to the CSI, and the field order of the requested output. If the input/output fields are sequential but different, swap fields, otherwise do not swap. This requires passing both the input and output mbus frame formats to ipu_csi_init_interface().
Move this code to a new private function ipu_csi_set_bt_interlaced_codes() that programs the CCIR_CODE_1/2 registers for interlaced BT.656 (and possibly interlaced BT.1120 in the future).
When detecting input video standard from the input frame width/height, make sure to double height if input field type is alternate, since in that case input height only includes lines for one field.
---
Changes since v5:
- Convert to const the infmt, outfmt, and mbus_cfg pointer args to ipu_csi_init_interface(), suggested by Philipp Zabel.
- Bring back if_fmt local var and don't copy outfmt to local stack in csi_setup(), suggested by Philipp.
Changes since v4:
- Cleaned up some convoluted code in ipu_csi_init_interface(), suggested by Philipp.
- Fixed a regression in csi_setup(), caught by Philipp.
--- drivers/gpu/ipu-v3/ipu-csi.c | 126 +++++++++++++++------- drivers/staging/media/imx/imx-media-csi.c | 7 +- include/video/imx-ipu-v3.h | 5 +- 3 files changed, 89 insertions(+), 49 deletions(-)
drivers/gpu/ipu-v3/ipu-csi.c +85 -41
@@ -325,12 +325,21 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,return 0 ; } +/* translate alternate field mode based on given standard */ +static inline enum v4l2_field +ipu_csi_translate_field (enum v4l2_field field,v4l2_std_id std) +{ +return (field !=V4L2_FIELD_ALTERNATE ) ? field : + ((std &V4L2_STD_525_60 ) ? +V4L2_FIELD_SEQ_BT :V4L2_FIELD_SEQ_TB ); +} +/* * Fill a CSI bus config struct from mbus_config and mbus_framefmt. */ static int fill_csi_bus_cfg (struct ipu_csi_bus_config *csicfg, -struct v4l2_mbus_config *mbus_cfg, -struct v4l2_mbus_framefmt *mbus_fmt) +const struct v4l2_mbus_config *mbus_cfg, +const struct v4l2_mbus_framefmt *mbus_fmt) {int ret;
@@ -374,22 +383,76 @@ static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,return 0 ; } +static int +ipu_csi_set_bt_interlaced_codes (struct ipu_csi *csi, +const struct v4l2_mbus_framefmt *infmt, +const struct v4l2_mbus_framefmt *outfmt, +v4l2_std_id std) +{ +enum v4l2_field infield, outfield; +bool swap_fields; + +/* get translated field type of input and output */ + infield =ipu_csi_translate_field (infmt->field, std); + outfield =ipu_csi_translate_field (outfmt->field, std); + +/* +* Write the H-V-F codes the CSI will match against the +* incoming data for start/end of active and blanking +* field intervals. If input and output field types are +* sequential but not the same (one is SEQ_BT and the other +* is SEQ_TB), swap the F-bit so that the CSI will capture +* field 1 lines before field 0 lines. +*/ + swap_fields = (V4L2_FIELD_IS_SEQUENTIAL (infield) && +V4L2_FIELD_IS_SEQUENTIAL (outfield) && + infield != outfield); + +if (!swap_fields) { +/* +* Field0BlankEnd = 110, Field0BlankStart = 010 +* Field0ActiveEnd = 100, Field0ActiveStart = 000 +* Field1BlankEnd = 111, Field1BlankStart = 011 +* Field1ActiveEnd = 101, Field1ActiveStart = 001 +*/ +ipu_csi_write (csi,0x40596 |CSI_CCIR_ERR_DET_EN , +CSI_CCIR_CODE_1 ); +ipu_csi_write (csi,0xD07DF ,CSI_CCIR_CODE_2 ); + }else { +dev_dbg (csi->ipu->dev,"capture field swap\n" ); + +/* same as above but with F-bit inverted */ +ipu_csi_write (csi,0xD07DF |CSI_CCIR_ERR_DET_EN , +CSI_CCIR_CODE_1 ); +ipu_csi_write (csi,0x40596 ,CSI_CCIR_CODE_2 ); + } + +ipu_csi_write (csi,0xFF0000 ,CSI_CCIR_CODE_3 ); + +return 0 ; +} + +int ipu_csi_init_interface (struct ipu_csi *csi, -struct v4l2_mbus_config *mbus_cfg, -struct v4l2_mbus_framefmt *mbus_fmt) +const struct v4l2_mbus_config *mbus_cfg, +const struct v4l2_mbus_framefmt *infmt, +const struct v4l2_mbus_framefmt *outfmt) {struct ipu_csi_bus_config cfg;unsigned long flags;u32 width, height, data =0 ; +v4l2_std_id std;int ret; - ret =fill_csi_bus_cfg (&cfg, mbus_cfg, mbus_fmt); + ret =fill_csi_bus_cfg (&cfg, mbus_cfg, infmt);if (ret <0 )return ret;/* set default sensor frame width and height */ - width = mbus_fmt->width; - height = mbus_fmt->height; + width = infmt->width; + height = infmt->height; +if (infmt->field ==V4L2_FIELD_ALTERNATE ) + height *=2 ;/* Set the CSI_SENS_CONF register remaining fields */ data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
@@ -416,42 +479,22 @@ int ipu_csi_init_interface(struct ipu_csi *csi,ipu_csi_write (csi,0xFF0000 ,CSI_CCIR_CODE_3 );break ;case IPU_CSI_CLK_MODE_CCIR656_INTERLACED : -if (mbus_fmt->width ==720 && mbus_fmt->height ==576 ) { -/* -* PAL case -* -* Field0BlankEnd = 0x6, Field0BlankStart = 0x2, -* Field0ActiveEnd = 0x4, Field0ActiveStart = 0 -* Field1BlankEnd = 0x7, Field1BlankStart = 0x3, -* Field1ActiveEnd = 0x5, Field1ActiveStart = 0x1 -*/ - height =625 ;/* framelines for PAL */ - -ipu_csi_write (csi,0x40596 |CSI_CCIR_ERR_DET_EN , -CSI_CCIR_CODE_1 ); -ipu_csi_write (csi,0xD07DF ,CSI_CCIR_CODE_2 ); -ipu_csi_write (csi,0xFF0000 ,CSI_CCIR_CODE_3 ); - }else if (mbus_fmt->width ==720 && mbus_fmt->height ==480 ) { -/* -* NTSC case -* -* Field0BlankEnd = 0x7, Field0BlankStart = 0x3, -* Field0ActiveEnd = 0x5, Field0ActiveStart = 0x1 -* Field1BlankEnd = 0x6, Field1BlankStart = 0x2, -* Field1ActiveEnd = 0x4, Field1ActiveStart = 0 -*/ - height =525 ;/* framelines for NTSC */ - -ipu_csi_write (csi,0xD07DF |CSI_CCIR_ERR_DET_EN , -CSI_CCIR_CODE_1 ); -ipu_csi_write (csi,0x40596 ,CSI_CCIR_CODE_2 ); -ipu_csi_write (csi,0xFF0000 ,CSI_CCIR_CODE_3 ); +if (width ==720 && height ==480 ) { + std =V4L2_STD_NTSC ; + height =525 ; + }else if (width ==720 && height ==576 ) { + std =V4L2_STD_PAL ; + height =625 ; }else {dev_err (csi->ipu->dev, -"Unsupported CCIR656 interlaced video mode\n" ); -spin_unlock_irqrestore (&csi->lock, flags); -return -EINVAL ; +"Unsupported interlaced video mode\n" ); + ret = -EINVAL ; + goto out_unlock; } + + ret =ipu_csi_set_bt_interlaced_codes (csi, infmt, outfmt, std); +if (ret) + goto out_unlock;break ;case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR :case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR :
@@ -476,9 +519,10 @@ int ipu_csi_init_interface(struct ipu_csi *csi,dev_dbg (csi->ipu->dev,"CSI_ACT_FRM_SIZE = 0x%08X\n" ,ipu_csi_read (csi,CSI_ACT_FRM_SIZE )); +out_unlock:spin_unlock_irqrestore (&csi->lock, flags); -return 0 ; +return ret; }EXPORT_SYMBOL_GPL (ipu_csi_init_interface);
drivers/staging/media/imx/imx-media-csi.c +1 -6
@@ -679,12 +679,7 @@ static int csi_setup(struct csi_priv *priv) priv->upstream_ep.bus.parallel.flags : priv->upstream_ep.bus.mipi_csi2.flags; -/* -* we need to pass input frame to CSI interface, but -* with translated field type from output format -*/ if_fmt = *infmt; - if_fmt.field = outfmt->field; crop = priv->crop;/*
@@ -702,7 +697,7 @@ static int csi_setup(struct csi_priv *priv) priv->crop.width ==2 * priv->compose.width, priv->crop.height == 2 * priv->compose.height); -ipu_csi_init_interface (priv->csi, &mbus_cfg, &if_fmt); +ipu_csi_init_interface (priv->csi, &mbus_cfg, &if_fmt, outfmt);ipu_csi_set_dest (priv->csi, priv->dest);
include/video/imx-ipu-v3.h +3 -2
@@ -351,8 +351,9 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,*/ struct ipu_csi ;int ipu_csi_init_interface (struct ipu_csi *csi, -struct v4l2_mbus_config *mbus_cfg, -struct v4l2_mbus_framefmt *mbus_fmt); +const struct v4l2_mbus_config *mbus_cfg, +const struct v4l2_mbus_framefmt *infmt, +const struct v4l2_mbus_framefmt *outfmt);bool ipu_csi_is_interlaced (struct ipu_csi *csi);void ipu_csi_get_window (struct ipu_csi *csi,struct v4l2_rect *w);void ipu_csi_set_window (struct ipu_csi *csi,struct v4l2_rect *w);
Signature · 1 line
2.17.1
kbuild test robot
build botI love your patch! Yet something to improve:
Hi Steve,
I love your patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v4.20-rc6 next-20181214]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Steve-Longerbeam/gpu-ipu-csi-Swap-fields-according-to-input-output-field-types/20181215-135741
config: nds32-allmodconfig (attached as .config)
compiler: nds32le-linux-gcc (GCC) 6.4.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=6.4.0 make.cross ARCH=nds32
All errors (new ones prefixed by >>):
drivers/gpu/ipu-v3/ipu-csi.c: In function 'ipu_csi_set_bt_interlaced_codes':
>> drivers/gpu/ipu-v3/ipu-csi.c:407:17: error: implicit declaration of function 'V4L2_FIELD_IS_SEQUENTIAL' [-Werror=implicit-function-declaration]
swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
^~~~~~~~~~~~~~~~~~~~~~~~cc1: some warnings being treated as errors
vim +/V4L2_FIELD_IS_SEQUENTIAL +407 drivers/gpu/ipu-v3/ipu-csi.c
385
386 static int
387 ipu_csi_set_bt_interlaced_codes(struct ipu_csi *csi,
388 const struct v4l2_mbus_framefmt *infmt,
389 const struct v4l2_mbus_framefmt *outfmt,
390 v4l2_std_id std)
391 {
392 enum v4l2_field infield, outfield;
393 bool swap_fields;
394
395 /* get translated field type of input and output */
396 infield = ipu_csi_translate_field(infmt->field, std);
397 outfield = ipu_csi_translate_field(outfmt->field, std);
398
399 /*
400 * Write the H-V-F codes the CSI will match against the
401 * incoming data for start/end of active and blanking
402 * field intervals. If input and output field types are
403 * sequential but not the same (one is SEQ_BT and the other
404 * is SEQ_TB), swap the F-bit so that the CSI will capture
405 * field 1 lines before field 0 lines.
406 */
> 407 swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
408 V4L2_FIELD_IS_SEQUENTIAL(outfield) &&
409 infield != outfield);
410
411 if (!swap_fields) {
412 /*
413 * Field0BlankEnd = 110, Field0BlankStart = 010
414 * Field0ActiveEnd = 100, Field0ActiveStart = 000
415 * Field1BlankEnd = 111, Field1BlankStart = 011
416 * Field1ActiveEnd = 101, Field1ActiveStart = 001
417 */
418 ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
419 CSI_CCIR_CODE_1);
420 ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
421 } else {
422 dev_dbg(csi->ipu->dev, "capture field swap\n");
423
424 /* same as above but with F-bit inverted */
425 ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
426 CSI_CCIR_CODE_1);
427 ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
428 }
429
430 ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
431
432 return 0;
433 }
434
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
kbuild test robot
build botI love your patch! Yet something to improve:
Hi Steve,
I love your patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v4.20-rc6 next-20181214]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Steve-Longerbeam/gpu-ipu-csi-Swap-fields-according-to-input-output-field-types/20181215-135741
config: xtensa-allmodconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 8.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=8.1.0 make.cross ARCH=xtensa
All errors (new ones prefixed by >>):
drivers/gpu//ipu-v3/ipu-csi.c: In function 'ipu_csi_set_bt_interlaced_codes':
>> drivers/gpu//ipu-v3/ipu-csi.c:407:17: error: implicit declaration of function 'V4L2_FIELD_IS_SEQUENTIAL'; did you mean 'V4L2_CID_RDS_RECEPTION'? [-Werror=implicit-function-declaration]
swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
^~~~~~~~~~~~~~~~~~~~~~~~
V4L2_CID_RDS_RECEPTIONcc1: some warnings being treated as errors
vim +407 drivers/gpu//ipu-v3/ipu-csi.c
385
386 static int
387 ipu_csi_set_bt_interlaced_codes(struct ipu_csi *csi,
388 const struct v4l2_mbus_framefmt *infmt,
389 const struct v4l2_mbus_framefmt *outfmt,
390 v4l2_std_id std)
391 {
392 enum v4l2_field infield, outfield;
393 bool swap_fields;
394
395 /* get translated field type of input and output */
396 infield = ipu_csi_translate_field(infmt->field, std);
397 outfield = ipu_csi_translate_field(outfmt->field, std);
398
399 /*
400 * Write the H-V-F codes the CSI will match against the
401 * incoming data for start/end of active and blanking
402 * field intervals. If input and output field types are
403 * sequential but not the same (one is SEQ_BT and the other
404 * is SEQ_TB), swap the F-bit so that the CSI will capture
405 * field 1 lines before field 0 lines.
406 */
> 407 swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
408 V4L2_FIELD_IS_SEQUENTIAL(outfield) &&
409 infield != outfield);
410
411 if (!swap_fields) {
412 /*
413 * Field0BlankEnd = 110, Field0BlankStart = 010
414 * Field0ActiveEnd = 100, Field0ActiveStart = 000
415 * Field1BlankEnd = 111, Field1BlankStart = 011
416 * Field1ActiveEnd = 101, Field1ActiveStart = 001
417 */
418 ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
419 CSI_CCIR_CODE_1);
420 ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
421 } else {
422 dev_dbg(csi->ipu->dev, "capture field swap\n");
423
424 /* same as above but with F-bit inverted */
425 ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
426 CSI_CCIR_CODE_1);
427 ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
428 }
429
430 ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
431
432 return 0;
433 }
434
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Please disregard. This patch can't be submitted stand-alone, I will re-submit as part of a v6 of "imx-media: Fixes for interlaced capture" patchset.
Steve
Quoted 258 lines · Steve Longerbeam
The function
ipu_csi_init_interface()was inverting the F-bit for NTSC case, in the CCIR_CODE_1/2 registers. The result being that for NTSC bottom-top field order, the CSI would swap fields and capture in top-bottom order.Instead, base field swap on the field order of the input to the CSI, and the field order of the requested output. If the input/output fields are sequential but different, swap fields, otherwise do not swap. This requires passing both the input and output mbus frame formats to
ipu_csi_init_interface().Move this code to a new private function
ipu_csi_set_bt_interlaced_codes()that programs the CCIR_CODE_1/2 registers for interlaced BT.656 (and possibly interlaced BT.1120 in the future).When detecting input video standard from the input frame width/height, make sure to double height if input field type is alternate, since in that case input height only includes lines for one field.
Signed-off-by Steve Longerbeam <[email protected]>Reviewed-by Philipp Zabel <[email protected]>---
Changes since v5:
- Convert to const the infmt, outfmt, andmbus_cfgpointer args toipu_csi_init_interface(), suggested by Philipp Zabel.
- Bring backif_fmtlocal var and don't copy outfmt to local stack incsi_setup(), suggested by Philipp.Changes since v4:
- Cleaned up some convoluted code inipu_csi_init_interface(), suggested by Philipp.
- Fixed a regression incsi_setup(), caught by Philipp.--- drivers/gpu/ipu-v3/ipu-csi.c | 126 +++++++++++++++------- drivers/staging/media/imx/imx-media-csi.c | 7 +- include/video/imx-ipu-v3.h | 5 +- 3 files changed, 89 insertions(+), 49 deletions(-)drivers/gpu/ipu-v3/ipu-csi.c +85
-41@@ -325,12 +325,21 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,return 0 ; } +/* translate alternate field mode based on given standard */ +static inline enum v4l2_field +ipu_csi_translate_field (enum v4l2_field field,v4l2_std_id std) +{ +return (field !=V4L2_FIELD_ALTERNATE ) ? field : + ((std &V4L2_STD_525_60 ) ? +V4L2_FIELD_SEQ_BT :V4L2_FIELD_SEQ_TB ); +} +/* * Fill a CSI bus config struct from mbus_config and mbus_framefmt. */ static int fill_csi_bus_cfg (struct ipu_csi_bus_config *csicfg, -struct v4l2_mbus_config *mbus_cfg, -struct v4l2_mbus_framefmt *mbus_fmt) +const struct v4l2_mbus_config *mbus_cfg, +const struct v4l2_mbus_framefmt *mbus_fmt) {int ret;@@ -374,22 +383,76 @@ static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,return 0 ; } +static int +ipu_csi_set_bt_interlaced_codes (struct ipu_csi *csi, +const struct v4l2_mbus_framefmt *infmt, +const struct v4l2_mbus_framefmt *outfmt, +v4l2_std_id std) +{ +enum v4l2_field infield, outfield; +bool swap_fields; + +/* get translated field type of input and output */ + infield =ipu_csi_translate_field (infmt->field, std); + outfield =ipu_csi_translate_field (outfmt->field, std); + +/* +* Write the H-V-F codes the CSI will match against the +* incoming data for start/end of active and blanking +* field intervals. If input and output field types are +* sequential but not the same (one is SEQ_BT and the other +* is SEQ_TB), swap the F-bit so that the CSI will capture +* field 1 lines before field 0 lines. +*/ + swap_fields = (V4L2_FIELD_IS_SEQUENTIAL (infield) && +V4L2_FIELD_IS_SEQUENTIAL (outfield) && + infield != outfield); + +if (!swap_fields) { +/* +* Field0BlankEnd = 110, Field0BlankStart = 010 +* Field0ActiveEnd = 100, Field0ActiveStart = 000 +* Field1BlankEnd = 111, Field1BlankStart = 011 +* Field1ActiveEnd = 101, Field1ActiveStart = 001 +*/ +ipu_csi_write (csi,0x40596 |CSI_CCIR_ERR_DET_EN , +CSI_CCIR_CODE_1 ); +ipu_csi_write (csi,0xD07DF ,CSI_CCIR_CODE_2 ); + }else { +dev_dbg (csi->ipu->dev,"capture field swap\n" ); + +/* same as above but with F-bit inverted */ +ipu_csi_write (csi,0xD07DF |CSI_CCIR_ERR_DET_EN , +CSI_CCIR_CODE_1 ); +ipu_csi_write (csi,0x40596 ,CSI_CCIR_CODE_2 ); + } + +ipu_csi_write (csi,0xFF0000 ,CSI_CCIR_CODE_3 ); + +return 0 ; +} + +int ipu_csi_init_interface (struct ipu_csi *csi, -struct v4l2_mbus_config *mbus_cfg, -struct v4l2_mbus_framefmt *mbus_fmt) +const struct v4l2_mbus_config *mbus_cfg, +const struct v4l2_mbus_framefmt *infmt, +const struct v4l2_mbus_framefmt *outfmt) {struct ipu_csi_bus_config cfg;unsigned long flags;u32 width, height, data =0 ; +v4l2_std_id std;int ret; - ret =fill_csi_bus_cfg (&cfg, mbus_cfg, mbus_fmt); + ret =fill_csi_bus_cfg (&cfg, mbus_cfg, infmt);if (ret <0 )return ret;/* set default sensor frame width and height */ - width = mbus_fmt->width; - height = mbus_fmt->height; + width = infmt->width; + height = infmt->height; +if (infmt->field ==V4L2_FIELD_ALTERNATE ) + height *=2 ;/* Set the CSI_SENS_CONF register remaining fields */ data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |@@ -416,42 +479,22 @@ int ipu_csi_init_interface(struct ipu_csi *csi,ipu_csi_write (csi,0xFF0000 ,CSI_CCIR_CODE_3 );break ;case IPU_CSI_CLK_MODE_CCIR656_INTERLACED : -if (mbus_fmt->width ==720 && mbus_fmt->height ==576 ) { -/* -* PAL case -* -* Field0BlankEnd = 0x6, Field0BlankStart = 0x2, -* Field0ActiveEnd = 0x4, Field0ActiveStart = 0 -* Field1BlankEnd = 0x7, Field1BlankStart = 0x3, -* Field1ActiveEnd = 0x5, Field1ActiveStart = 0x1 -*/ - height =625 ;/* framelines for PAL */ - -ipu_csi_write (csi,0x40596 |CSI_CCIR_ERR_DET_EN , -CSI_CCIR_CODE_1 ); -ipu_csi_write (csi,0xD07DF ,CSI_CCIR_CODE_2 ); -ipu_csi_write (csi,0xFF0000 ,CSI_CCIR_CODE_3 ); - }else if (mbus_fmt->width ==720 && mbus_fmt->height ==480 ) { -/* -* NTSC case -* -* Field0BlankEnd = 0x7, Field0BlankStart = 0x3, -* Field0ActiveEnd = 0x5, Field0ActiveStart = 0x1 -* Field1BlankEnd = 0x6, Field1BlankStart = 0x2, -* Field1ActiveEnd = 0x4, Field1ActiveStart = 0 -*/ - height =525 ;/* framelines for NTSC */ - -ipu_csi_write (csi,0xD07DF |CSI_CCIR_ERR_DET_EN , -CSI_CCIR_CODE_1 ); -ipu_csi_write (csi,0x40596 ,CSI_CCIR_CODE_2 ); -ipu_csi_write (csi,0xFF0000 ,CSI_CCIR_CODE_3 ); +if (width ==720 && height ==480 ) { + std =V4L2_STD_NTSC ; + height =525 ; + }else if (width ==720 && height ==576 ) { + std =V4L2_STD_PAL ; + height =625 ; }else {dev_err (csi->ipu->dev, -"Unsupported CCIR656 interlaced video mode\n" ); -spin_unlock_irqrestore (&csi->lock, flags); -return -EINVAL ; +"Unsupported interlaced video mode\n" ); + ret = -EINVAL ; + goto out_unlock; } + + ret =ipu_csi_set_bt_interlaced_codes (csi, infmt, outfmt, std); +if (ret) + goto out_unlock;break ;case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR :case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR :@@ -476,9 +519,10 @@ int ipu_csi_init_interface(struct ipu_csi *csi,dev_dbg (csi->ipu->dev,"CSI_ACT_FRM_SIZE = 0x%08X\n" ,ipu_csi_read (csi,CSI_ACT_FRM_SIZE )); +out_unlock:spin_unlock_irqrestore (&csi->lock, flags); -return 0 ; +return ret; }EXPORT_SYMBOL_GPL (ipu_csi_init_interface);drivers/staging/media/imx/imx-media-csi.c +1
-6@@ -679,12 +679,7 @@ static int csi_setup(struct csi_priv *priv) priv->upstream_ep.bus.parallel.flags : priv->upstream_ep.bus.mipi_csi2.flags; -/* -* we need to pass input frame to CSI interface, but -* with translated field type from output format -*/ if_fmt = *infmt; - if_fmt.field = outfmt->field; crop = priv->crop;/* @@ -702,7 +697,7 @@ static int csi_setup(struct csi_priv *priv) priv->crop.width ==2 * priv->compose.width, priv->crop.height == 2 * priv->compose.height); -ipu_csi_init_interface (priv->csi, &mbus_cfg, &if_fmt); +ipu_csi_init_interface (priv->csi, &mbus_cfg, &if_fmt, outfmt);ipu_csi_set_dest (priv->csi, priv->dest);include/video/imx-ipu-v3.h +3
-2@@ -351,8 +351,9 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,*/ struct ipu_csi ;int ipu_csi_init_interface (struct ipu_csi *csi, -struct v4l2_mbus_config *mbus_cfg, -struct v4l2_mbus_framefmt *mbus_fmt); +const struct v4l2_mbus_config *mbus_cfg, +const struct v4l2_mbus_framefmt *infmt, +const struct v4l2_mbus_framefmt *outfmt);bool ipu_csi_is_interlaced (struct ipu_csi *csi);void ipu_csi_get_window (struct ipu_csi *csi,struct v4l2_rect *w);void ipu_csi_set_window (struct ipu_csi *csi,struct v4l2_rect *w);