RE: [PATCH v5 2/6] media: platform: visconti: Add Toshiba Visconti Video Input Interface driver

From: yuji2.ishikawa
Date: Tue Jan 31 2023 - 21:09:16 EST


Hello Sakari,

Sorry for sending the reply again.
My mail agent posted the previous one with HTML format.

Thank you for reviewing and your comments.

> -----Original Message-----
> From: Sakari Ailus sakari.ailus@xxxxxx
> Sent: Wednesday, January 18, 2023 7:40 AM
> To: ishikawa yuji(石川 悠司 ○RDC□AITC○EA開)
> yuji2.ishikawa@xxxxxxxxxxxxx
> Cc: Hans Verkuil hverkuil@xxxxxxxxx; Laurent Pinchart
> laurent.pinchart@xxxxxxxxxxxxxxxx; Mauro Carvalho Chehab
> mchehab@xxxxxxxxxx; iwamatsu nobuhiro(岩松 信洋 □SWC◯ACT)
> nobuhiro1.iwamatsu@xxxxxxxxxxxxx; Rob Herring robh+dt@xxxxxxxxxx;
> Krzysztof Kozlowski krzysztof.kozlowski+dt@xxxxxxxxxx; Rafael J . Wysocki
> rafael.j.wysocki@xxxxxxxxx; Mark Brown broonie@xxxxxxxxxx;
> linux-media@xxxxxxxxxxxxxxx; linux-arm-kernel@xxxxxxxxxxxxxxxxxxx;
> linux-kernel@xxxxxxxxxxxxxxx; devicetree@xxxxxxxxxxxxxxx
> Subject: Re: [PATCH v5 2/6] media: platform: visconti: Add Toshiba Visconti
> Video Input Interface driver
>
> Dear Ishikawa-san,
>
> Thanks for the patchset.
>
> I'd say this is a partial review based on a quick glance, I may have
> further comments later on. It's a big patch, some 8000 lines. Please see
> the comments below.
>
> On Wed, Jan 11, 2023 at 11:24:29AM +0900, Yuji Ishikawa wrote:
> > Add support to Video Input Interface on Toshiba Visconti ARM SoCs.
> > The interface device includes CSI2 Receiver,
> > frame grabber, video DMAC and image signal processor.
> > This patch provides operations to handle registers of HW listed above.
> >
> > The Video DMACs have 32bit address space
> > and currently corresponding IOMMU driver is not provided.
> > Therefore, memory-block address for captured image is 32bit IOVA
> > which is equal to 32bit-truncated phisical address.
> > When the Visconti IOMMU driver (currently under development) is accepted,
> > the hardware layer will use 32bit IOVA mapped by the attached IOMMU.
> >
> > Signed-off-by: Yuji Ishikawa yuji2.ishikawa@xxxxxxxxxxxxx
> > ---
> > Changelog v2:
> > - Resend v1 because a patch exceeds size limit.
> >
> > Changelog v3:
> > - Adapted to media control framework
> > - Introduced ISP subdevice, capture device
> > - Remove private IOCTLs and add vendor specific V4L2 controls
> > - Change function name avoiding camelcase and uppercase letters
> >
> > Changelog v4:
> > - Split patches because the v3 patch exceeds size limit
> > - Stop using ID number to identify driver instance:
> > - Use dynamically allocated structure to hold driver's context,
> > instead of static one indexed by ID number.
> > - Functions accept driver's context structure instead of ID number.
> >
> > Changelog v5:
> > - no change
> > ---
> > drivers/media/platform/Kconfig | 1 +
> > drivers/media/platform/Makefile | 1 +
> > drivers/media/platform/visconti/Kconfig | 9 +
> > drivers/media/platform/visconti/Makefile | 8 +
> > drivers/media/platform/visconti/hwd_viif.c | 1690 ++++++++++
> > drivers/media/platform/visconti/hwd_viif.h | 710 +++++
> > .../media/platform/visconti/hwd_viif_csi2rx.c | 610 ++++
> > .../platform/visconti/hwd_viif_internal.h | 340 ++
> > .../media/platform/visconti/hwd_viif_reg.h | 2802
> +++++++++++++++++
> > include/uapi/linux/visconti_viif.h | 1724 ++++++++++
> > 10 files changed, 7895 insertions(+)
> > create mode 100644 drivers/media/platform/visconti/Kconfig
> > create mode 100644 drivers/media/platform/visconti/Makefile
> > create mode 100644 drivers/media/platform/visconti/hwd_viif.c
> > create mode 100644 drivers/media/platform/visconti/hwd_viif.h
> > create mode 100644 drivers/media/platform/visconti/hwd_viif_csi2rx.c
> > create mode 100644 drivers/media/platform/visconti/hwd_viif_internal.h
> > create mode 100644 drivers/media/platform/visconti/hwd_viif_reg.h
> > create mode 100644 include/uapi/linux/visconti_viif.h
> >
> > diff --git a/drivers/media/platform/Kconfig
> b/drivers/media/platform/Kconfig
> > index a9334263fa9..0908158036d 100644
> > --- a/drivers/media/platform/Kconfig
> > +++ b/drivers/media/platform/Kconfig
> > @@ -83,6 +83,7 @@ source "drivers/media/platform/sunxi/Kconfig"
> > source "drivers/media/platform/ti/Kconfig"
> > source "drivers/media/platform/verisilicon/Kconfig"
> > source "drivers/media/platform/via/Kconfig"
> > +source "drivers/media/platform/visconti/Kconfig"
> > source "drivers/media/platform/xilinx/Kconfig"
> >
> > endif # MEDIA_PLATFORM_DRIVERS
> > diff --git a/drivers/media/platform/Makefile
> b/drivers/media/platform/Makefile
> > index a91f4202427..1c67cb56244 100644
> > --- a/drivers/media/platform/Makefile
> > +++ b/drivers/media/platform/Makefile
> > @@ -26,6 +26,7 @@ obj-y += sunxi/
> > obj-y += ti/
> > obj-y += verisilicon/
> > obj-y += via/
> > +obj-y += visconti/
> > obj-y += xilinx/
> >
> > # Please place here only ancillary drivers that aren't SoC-specific
> > diff --git a/drivers/media/platform/visconti/Kconfig
> b/drivers/media/platform/visconti/Kconfig
> > new file mode 100644
> > index 00000000000..031e4610809
> > --- /dev/null
> > +++ b/drivers/media/platform/visconti/Kconfig
> > @@ -0,0 +1,9 @@
> > +config VIDEO_VISCONTI_VIIF
> > + tristate "Visconti Camera Interface driver"
> > + depends on V4L_PLATFORM_DRIVERS && MEDIA_CONTROLLER &&
> VIDEO_DEV
> > + depends on ARCH_VISCONTI
> > + select VIDEOBUF2_DMA_CONTIG
> > + select V4L2_FWNODE
> > + help
> > + This is V4L2 driver for Toshiba Visconti Camera Interface driver
> > +
> > diff --git a/drivers/media/platform/visconti/Makefile
> b/drivers/media/platform/visconti/Makefile
> > new file mode 100644
> > index 00000000000..e14b904df75
> > --- /dev/null
> > +++ b/drivers/media/platform/visconti/Makefile
> > @@ -0,0 +1,8 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +#
> > +# Makefile for the Visconti video input device driver
> > +#
> > +
> > +visconti-viif-objs += hwd_viif_csi2rx.o hwd_viif.o
> > +
> > +obj-$(CONFIG_VIDEO_VISCONTI_VIIF) += visconti-viif.o
> > diff --git a/drivers/media/platform/visconti/hwd_viif.c
> b/drivers/media/platform/visconti/hwd_viif.c
> > new file mode 100644
> > index 00000000000..260293fa4d0
> > --- /dev/null
> > +++ b/drivers/media/platform/visconti/hwd_viif.c
> > @@ -0,0 +1,1690 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > +/* Toshiba Visconti Video Capture Support
> > + *
> > + * (C) Copyright 2022 TOSHIBA CORPORATION
> > + * (C) Copyright 2022 Toshiba Electronic Devices & Storage Corporation
>
> Happy new year!

Oh! Another year has come.
I'll update copyright notice.

> > + */
> > +
> > +#include <linux/delay.h>
> > +#include <linux/io.h>
> > +#include <linux/platform_device.h>
> > +
> > +#include "hwd_viif.h"
> > +#include "hwd_viif_internal.h"
> > +
> > +/* MIPI CSI2 DataType definition */
> > +#define CSI2_DT_YUV4228B VISCONTI_CSI2_DT_YUV4228B
> > +#define CSI2_DT_YUV42210B VISCONTI_CSI2_DT_YUV42210B
> > +#define CSI2_DT_RGB565 VISCONTI_CSI2_DT_RGB565
> > +#define CSI2_DT_RGB888 VISCONTI_CSI2_DT_RGB888
> > +#define CSI2_DT_RAW8 VISCONTI_CSI2_DT_RAW8
> > +#define CSI2_DT_RAW10 VISCONTI_CSI2_DT_RAW10
> > +#define CSI2_DT_RAW12 VISCONTI_CSI2_DT_RAW12
> > +#define CSI2_DT_RAW14 VISCONTI_CSI2_DT_RAW14
>
> These are generic MIPI CSI-2 definitions, no need to re-define them for
> this driver only.

I'll use definitions in mipi-csi2.h

> > +
> > +struct hwd_viif_res *allocate_viif_res(struct device *dev, void
> *csi2host_vaddr,
> > + void *capture_vaddr)
> > +{
> > + struct hwd_viif_res *res = devm_kzalloc(dev, sizeof(struct hwd_viif_res),
> GFP_KERNEL);
> > +
> > + res->csi2host_reg = csi2host_vaddr;
> > + res->capture_reg = capture_vaddr;
> > + res->run_flag_main = (bool)false;
>
> What happens here if res is NULL?
>
> I'd advise to perform the allocation outside variable declarations, that
> way it is more obvious it may fail (and needs to be checked for).
>
> No need for a cast.

I'll fix them.

> > + return res;
> > +}
> > +
> > +/* Convert the unit of time-period (from sysclk, to num lines in the image) */
> > +static u32 sysclk_to_numlines(u64 time_in_sysclk, const struct
> hwd_viif_input_img *img)
>
> Please run:
>
> $ ./scripts/checkpatch.pl --strict --max-line-length=80
>
> on the set.

I found that extra newlines inserted by a mailer surely made the patch difficult to read.

Currently, a source file has maximum 100 characters for a line.
I’ll limit to 80 characters.
Is it just for review process, or the source files should always have maximum 80 characters for a line?

> > +{
> > + u64 v1 = time_in_sysclk * (u64)img->pixel_clock;
>
> You can drop the cast.

I'll drop the cast.

> > + u64 v2 = (u64)img->htotal_size * HWD_VIIF_SYS_CLK;
> > +
> > + return (u32)(v1 / v2);
>
> div_u64()?

I'll use div_u64().

> > +}
> > +
> > +static u32 lineperiod_in_sysclk(u64 hsize, u64 pixel_clock)
> > +{
> > + return (u32)(hsize * HWD_VIIF_SYS_CLK / pixel_clock);
>
> You can drop the cast.
>
> And I think you need div_u64() instead.

I'll use div_u64().

> > +}
> > +
> > +/**
> > + * hwd_viif_main_set_unit() - Set static configuration of MAIN unit(CH0 or
> CH1)
> > + *
> > + * @dt_image: DT of image [0x10-0x17, 0x1B, 0x1E, 0x1F, 0x22, 0x24-0x27,
> 0x2A-0x3F])
> > + * @in_img: Pointer to input image information
> > + * @color_type: Color type of image [0x0, 0x1E, 0x1F, 0x22, 0x24, 0x2A-0x2D]
> > + * @rawpack: RAW pack mode. For more refer @ref
> hwd_viif_raw_pack_mode
> > + * @yuv_conv: YUV422 to YUV444 conversion mode. For more refer @ref
> hwd_viif_yuv_conversion_mode
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] "dt_image" is out of range
> > + * - [2] "in_img" is NULL
> > + * - [3] member of "in_img" is invalid
> > + * - [4] "color_type" is out of range
> > + * - [5] "color_type" doesn't meet the condition shown in the below note
> > + * - [6] "rawpack" is out of range
> > + * - [7] "rawpack" is not HWD_VIIF_RAWPACK_DISABLE when color_type is
> other than RAW(0x2A-0x2C)
> > + * - [8] "yuv_conv" is out of range
> > + * - [9] "yuv_conv" is not HWD_VIIF_YUV_CONV_REPEAT
> > + * when color_type is other than YUV422(0x1E or 0x1F)
> > + *
> > + * Note: valid combination between "dt_image" and "color_type" is
> > + * - when "dt_image" is [0x10-0x17, 0x1B, 0x25-0x27, 0x2E-0x3F],
> "color_type" must be [0x2A-0x2D].
> > + * - when "dt_image" is valid value and other than [0x10-0x17, 0x1B,
> 0x25-0x27, 0x2E-0x3F],
> > + * "color_type" must be "dt_image"
> > + */
> > +s32 hwd_viif_main_set_unit(struct hwd_viif_res *res, u32 dt_image,
> > + const struct hwd_viif_input_img *in_img, u32
> color_type, u32 rawpack,
> > + u32 yuv_conv)
> > +{
> > + u32 total_hact_size = 0U, total_vact_size = 0U;
> > + u32 sw_delay0, sw_delay1, hw_delay;
> > + u32 val, color, sysclk_num;
> > + u32 i;
> > +
> > + /*
> > + * 0x00-0x09: ShortPacket/Undefined
> > + * 0x18-0x1A: YUV420
> > + * 0x1C,0x1D: YUV420 CSPS
> > + * 0x20,0x21,0x23: RGB444, RGB555, RGB666
> > + * 0x28,0x29: RAW6, RAW7
> > + */
> > + if (dt_image <= 0x09U || (dt_image >= 0x18U && dt_image <= 0x1AU)
> || dt_image == 0x1CU ||
> > + dt_image == 0x1DU || dt_image == 0x20U || dt_image == 0x21U
> || dt_image == 0x23U ||
> > + dt_image == 0x28U || dt_image == 0x29U || dt_image >
> HWD_VIIF_CSI2_MAX_DT) {
> > + return -EINVAL;
> > + }
> > +
> > + /*Case: Generic Long Packet, Reserved, User-Defined*/
> > + if ((dt_image >= 0x10U && dt_image <= 0x17U) || dt_image == 0x1bU
> ||
> > + (dt_image >= 0x25U && dt_image <= 0x27U) || dt_image >=
> 0x2eU) {
> > + if (color_type != CSI2_DT_RAW8 && color_type !=
> CSI2_DT_RAW10 &&
> > + color_type != CSI2_DT_RAW12 && color_type !=
> CSI2_DT_RAW14) {
>
> Could you use the data type defines where applicable? Same above.

I'll use definitions in mipi-csi2.h .

> > + return -EINVAL;
> > + }
> > + } else {
> > + /*Case: Otherwise: YUV, RGB, RAW*/
> > + /*Constraint: color_type must be dt_image*/
> > + if (color_type != dt_image)
> > + return -EINVAL;
> > + }
> > +
> > + if (!in_img)
> > + return -EINVAL;
> > + if (rawpack != HWD_VIIF_RAWPACK_DISABLE && rawpack !=
> HWD_VIIF_RAWPACK_MSBFIRST &&
> > + rawpack != HWD_VIIF_RAWPACK_LSBFIRST) {
> > + return -EINVAL;
> > + }
> > + if (color_type != CSI2_DT_RAW8 && color_type != CSI2_DT_RAW10 &&
> > + color_type != CSI2_DT_RAW12 && rawpack !=
> HWD_VIIF_RAWPACK_DISABLE) {
> > + return -EINVAL;
> > + }
> > +
> > + if (in_img->pixel_clock < HWD_VIIF_MIN_PIXEL_CLOCK ||
> > + in_img->pixel_clock > HWD_VIIF_MAX_PIXEL_CLOCK ||
> > + in_img->htotal_size < HWD_VIIF_MIN_HTOTAL_PIXEL ||
> > + in_img->htotal_size > HWD_VIIF_MAX_HTOTAL_PIXEL ||
> > + in_img->vtotal_size < HWD_VIIF_MIN_VTOTAL_LINE ||
> > + in_img->vtotal_size > HWD_VIIF_MAX_VTOTAL_LINE ||
> > + in_img->vbp_size < HWD_VIIF_MIN_VBP_LINE ||
> in_img->vbp_size > HWD_VIIF_MAX_VBP_LINE ||
> > + ((in_img->hactive_size % 2U) != 0U) || ((in_img->vactive_size %
> 2U) != 0U)) {
> > + return -EINVAL;
> > + }
> > +
> > + if (in_img->interpolation_mode !=
> HWD_VIIF_L1_INPUT_INTERPOLATION_LINE &&
> > + in_img->interpolation_mode !=
> HWD_VIIF_L1_INPUT_INTERPOLATION_PIXEL) {
> > + return -EINVAL;
> > + }
> > +
> > + if (in_img->input_num < HWD_VIIF_L1_INPUT_NUM_MIN ||
> > + in_img->input_num > HWD_VIIF_L1_INPUT_NUM_MAX) {
> > + return -EINVAL;
> > + }
> > +
> > + if (in_img->hobc_width != 0U && in_img->hobc_width != 16U &&
> in_img->hobc_width != 32U &&
> > + in_img->hobc_width != 64U && in_img->hobc_width != 128U) {
> > + return -EINVAL;
> > + }
> > +
> > + if (in_img->hobc_margin > 30U || ((in_img->hobc_margin % 2U) !=
> 0U))
> > + return -EINVAL;
> > +
> > + if (in_img->hobc_width == 0U && in_img->hobc_margin != 0U)
> > + return -EINVAL;
> > +
> > + if (in_img->hobc_width != 0U && in_img->hobc_margin == 0U)
> > + return -EINVAL;
> > +
> > + if (color_type == CSI2_DT_RAW8 || color_type == CSI2_DT_RAW10 ||
> > + color_type == CSI2_DT_RAW12 || color_type == CSI2_DT_RAW14)
> {
> > + /* parameter check in case of L1ISP(in case of RAW) */
> > + if (in_img->hactive_size <
> HWD_VIIF_MIN_HACTIVE_PIXEL_W_L1ISP ||
> > + in_img->hactive_size >
> HWD_VIIF_MAX_HACTIVE_PIXEL_W_L1ISP ||
> > + in_img->vactive_size <
> HWD_VIIF_MIN_VACTIVE_LINE_W_L1ISP ||
> > + in_img->vactive_size >
> HWD_VIIF_MAX_VACTIVE_LINE_W_L1ISP ||
> > + ((in_img->hactive_size % 8U) != 0U)) {
> > + return -EINVAL;
> > + }
> > +
> > + /* check vbp range in case of L1ISP on */
> > + /* the constant value "7" is configuration margin */
> > + val = sysclk_to_numlines(
> > + HWD_VIIF_TABLE_LOAD_TIME +
> HWD_VIIF_REGBUF_ACCESS_TIME * 2U, in_img) +
> > + HWD_VIIF_L1_DELAY_W_HDRC + 7U;
> > + if (in_img->vbp_size < val)
> > + return -EINVAL;
> > +
> > + /* calculate total of horizontal active size and vertical active size
> */
> > + if (rawpack != HWD_VIIF_RAWPACK_DISABLE) {
> > + val = (in_img->hactive_size + in_img->hobc_width +
> in_img->hobc_margin) *
> > + 2U;
> > + } else {
> > + val = in_img->hactive_size + in_img->hobc_width +
> in_img->hobc_margin;
> > + }
> > + if (in_img->interpolation_mode ==
> HWD_VIIF_L1_INPUT_INTERPOLATION_LINE) {
> > + total_hact_size = val;
> > + total_vact_size = in_img->vactive_size *
> in_img->input_num;
> > + } else {
> > + total_hact_size = val * in_img->input_num;
> > + total_vact_size = in_img->vactive_size;
> > + }
> > + } else {
> > + /* OTHER input than RAW(L1ISP is off) */
> > + if (in_img->hactive_size <
> HWD_VIIF_MIN_HACTIVE_PIXEL_WO_L1ISP ||
> > + in_img->hactive_size >
> HWD_VIIF_MAX_HACTIVE_PIXEL_WO_L1ISP ||
> > + in_img->vactive_size <
> HWD_VIIF_MIN_VACTIVE_LINE_WO_L1ISP ||
> > + in_img->vactive_size >
> HWD_VIIF_MAX_VACTIVE_LINE_WO_L1ISP ||
> > + in_img->interpolation_mode !=
> HWD_VIIF_L1_INPUT_INTERPOLATION_LINE ||
> > + in_img->input_num != HWD_VIIF_L1_INPUT_NUM_MIN
> || in_img->hobc_width != 0U) {
> > + return -EINVAL;
> > + }
> > +
> > + /* check vbp range in case of L1ISP off */
> > + /* the constant value "16" is configuration margin */
> > + val = sysclk_to_numlines(HWD_VIIF_TABLE_LOAD_TIME +
> HWD_VIIF_REGBUF_ACCESS_TIME,
> > + in_img) +
> > + 16U;
> > + if (in_img->vbp_size < val)
> > + return -EINVAL;
> > +
> > + total_hact_size = in_img->hactive_size;
> > + total_vact_size = in_img->vactive_size;
> > + }
> > +
> > + if (in_img->htotal_size <= total_hact_size ||
> > + (in_img->vtotal_size <= (in_img->vbp_size + total_vact_size))) {
> > + return -EINVAL;
> > + }
> > +
> > + if (yuv_conv != HWD_VIIF_YUV_CONV_REPEAT && yuv_conv !=
> HWD_VIIF_YUV_CONV_INTERPOLATION)
> > + return -EINVAL;
> > +
> > + if (color_type != CSI2_DT_YUV4228B && color_type !=
> CSI2_DT_YUV42210B &&
> > + yuv_conv != HWD_VIIF_YUV_CONV_REPEAT) {
> > + return -EINVAL;
> > + }
> > +
> > + /* Set DT and color type of image data */
> > + writel((color_type << 8U) | dt_image,
> &res->capture_reg->sys.IPORTM_MAIN_DT);
> > + writel(0x00, &res->capture_reg->sys.IPORTM_OTHER);
> > + res->dt_image_main_w_isp = dt_image;
> > +
> > + /* Set back porch*/
> > + writel((in_img->vbp_size << 16U) | HWD_VIIF_HBP_SYSCLK,
> > + &res->capture_reg->sys.BACK_PORCH_M);
> > +
> > + /* single pulse of vsync is input to DPGM */
> > + writel(HWD_VIIF_DPGM_VSYNC_PULSE,
> &res->capture_reg->sys.DPGM_VSYNC_SOURCE);
> > +
> > + /* image data will be input */
> > + /* set preprocess type before L2ISP based on color_type. */
> > + if (color_type == CSI2_DT_YUV4228B || color_type ==
> CSI2_DT_YUV42210B) {
> > + /* YUV422 */
> > + color = 3U;
> > + } else if (color_type == CSI2_DT_RGB565 || color_type ==
> CSI2_DT_RGB888) {
> > + /* RGB */
> > + color = 0U;
> > + } else {
> > + /* RGB or YUV444 from L1ISP */
> > + color = 1U;
> > + }
> > + writel(color << 4U, &res->capture_reg->sys.PREPROCCESS_FMTM);
> > +
> > + /* set Total size and valid size information of image data */
> > + sysclk_num = lineperiod_in_sysclk(in_img->htotal_size,
> in_img->pixel_clock);
> > + sysclk_num &= GENMASK(15, 0);
> > + writel((in_img->vtotal_size << 16U) | sysclk_num,
> &res->capture_reg->sys.TOTALSIZE_M);
> > + writel((total_vact_size << 16U) | total_hact_size,
> &res->capture_reg->sys.VALSIZE_M);
> > +
> > + /* set image size information to L2ISP */
> > + writel(in_img->vactive_size,
> &res->capture_reg->l2isp.L2_SENSOR_CROP_VSIZE);
> > + writel(in_img->hactive_size,
> &res->capture_reg->l2isp.L2_SENSOR_CROP_HSIZE);
> > +
> > + /* RAW input case */
> > + if (color_type >= CSI2_DT_RAW8) {
> > + val = (in_img->interpolation_mode << 3U) |
> (in_img->input_num);
> > + writel(val,
> &res->capture_reg->l1isp.L1_IBUF_INPUT_ORDER);
> > + writel(in_img->vactive_size,
> &res->capture_reg->l1isp.L1_SYSM_HEIGHT);
> > + writel(in_img->hactive_size,
> &res->capture_reg->l1isp.L1_SYSM_WIDTH);
> > + val = (in_img->hobc_margin << 8U) | in_img->hobc_width;
> > + writel(val, &res->capture_reg->l1isp.L1_HOBC_MARGIN);
> > + }
> > +
> > + /* Set rawpack */
> > + writel(rawpack, &res->capture_reg->sys.IPORTM_MAIN_RAW);
> > +
> > + /* Set yuv_conv */
> > + writel(yuv_conv, &res->capture_reg->sys.PREPROCCESS_C24M);
> > +
> > + /* Set vsync delay */
> > + hw_delay = in_img->vbp_size -
> sysclk_to_numlines(HWD_VIIF_TABLE_LOAD_TIME, in_img) + 4U;
> > + hw_delay = min(hw_delay, 255U);
> > +
> > + sw_delay0 = hw_delay -
> sysclk_to_numlines(HWD_VIIF_REGBUF_ACCESS_TIME, in_img) + 2U;
> > +
> > + if (color_type == CSI2_DT_RAW8 || color_type == CSI2_DT_RAW10 ||
> > + color_type == CSI2_DT_RAW12 || color_type == CSI2_DT_RAW14)
> {
> > + sw_delay1 =
> sysclk_to_numlines(HWD_VIIF_REGBUF_ACCESS_TIME, in_img) +
> > + HWD_VIIF_L1_DELAY_WO_HDRC + 1U;
> > + } else {
> > + sw_delay1 = 10U;
> > + }
> > + writel(sw_delay0 << 16U, &res->capture_reg->sys.INT_M0_LINE);
> > + writel((sw_delay1 << 16U) | hw_delay,
> &res->capture_reg->sys.INT_M1_LINE);
> > +
> > + /* M2_LINE is the same condition as M1_LINE */
> > + writel((sw_delay1 << 16U) | hw_delay,
> &res->capture_reg->sys.INT_M2_LINE);
> > +
> > + /* Update internal information of pixel clock, htotal_size, information of
> L2 ROI */
> > + res->pixel_clock = in_img->pixel_clock;
> > + res->htotal_size = in_img->htotal_size;
> > + res->l2_roi_path_info.roi_num = 0;
> > + for (i = 0; i < HWD_VIIF_MAX_POST_NUM; i++) {
> > + res->l2_roi_path_info.post_enable_flag[i] = false;
> > + res->l2_roi_path_info.post_crop_x[i] = 0;
> > + res->l2_roi_path_info.post_crop_y[i] = 0;
> > + res->l2_roi_path_info.post_crop_w[i] = 0;
> > + res->l2_roi_path_info.post_crop_h[i] = 0;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_main_mask_vlatch() - Control Vlatch mask of MAIN unit
> > + *
> > + * @enable: or disable Vlatch mask of MAIN unit. For more refer @ref
> hwd_viif_enable_flag.
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - "enable" is out of range
> > + */
> > +s32 hwd_viif_main_mask_vlatch(struct hwd_viif_res *res, u32 enable)
> > +{
> > + if (enable != HWD_VIIF_ENABLE && enable != HWD_VIIF_DISABLE)
> > + return -EINVAL;
>
> The function would be nicer to use if it took bool as the argument. You
> could remove this check, too.

I'll use bool type. Same for other functions.

> > +
> > + if (enable == HWD_VIIF_ENABLE)
> > + enable |= HWD_VIIF_ISP_VLATCH_MASK;
> > +
> > + /* Control Vlatch mask */
> > + writel(enable, &res->capture_reg->sys.IPORTM0_LD);
> > + writel(enable, &res->capture_reg->sys.IPORTM1_LD);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_main_status_err_set_irq_mask() - Set mask condition for
> STATUS error of MAIN unit
> > + *
> > + * @mask: STATUS error mask condition
> > + * Return: None
> > + */
> > +void hwd_viif_main_status_err_set_irq_mask(struct hwd_viif_res *res, u32
> mask)
> > +{
> > + writel(mask, &res->capture_reg->sys.INT_M_MASK);
> > +}
> > +
> > +/**
> > + * hwd_viif_main_vsync_set_irq_mask() - Set mask condition for Vsync of
> MAIN unit
> > + *
> > + * @mask: Vsync mask condition
> > + * Return: None
> > + */
> > +void hwd_viif_main_vsync_set_irq_mask(struct hwd_viif_res *res, u32 mask)
> > +{
> > + writel(mask, &res->capture_reg->sys.INT_M_SYNC_MASK);
> > +}
> > +
> > +#define VDM_BIT_W00 BIT(0)
> > +#define VDM_BIT_W01 BIT(1)
> > +#define VDM_BIT_W02 BIT(2)
> > +#define VDM_BIT_W03 BIT(3)
> > +#define VDM_BIT_W04 BIT(4)
> > +#define VDM_BIT_W05 BIT(5)
> > +#define VDM_BIT_R00 BIT(0)
> > +#define VDM_BIT_R01 BIT(1)
> > +#define VDM_BIT_R02 BIT(2)
> > +
> > +#define VDM_ABORT_MASK_SUB_W (VDM_BIT_W03 | VDM_BIT_W04 |
> VDM_BIT_W05)
> > +#define VDM_ABORT_MASK_MAIN_W (VDM_BIT_W00 | VDM_BIT_W01 |
> VDM_BIT_W02)
> > +#define VDM_ABORT_MASK_MAIN_R (VDM_BIT_R00 | VDM_BIT_R01 |
> VDM_BIT_R02)
> > +
> > +/**
> > + * hwd_viif_sub_set_unit() - Set static configuration of SUB unit
> > + *
> > + * @dt_image: DT of image [0x1E, 0x1F, 0x22, 0x24, 0x2A-0x2D]
> > + * @in_img: Pointer to input image information
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] "dt_image" is out of range
> > + * - [2] "in_img" is NULL
> > + * - [3] member of "in_img" is invalid
> > + */
> > +s32 hwd_viif_sub_set_unit(struct hwd_viif_res *res, u32 dt_image,
> > + const struct hwd_viif_input_img *in_img)
> > +{
> > + u32 sysclk_num, temp_delay;
> > +
> > + if (dt_image < 0x2aU || dt_image > 0x2dU)
> > + return -EINVAL;
> > +
> > + if (!in_img)
> > + return -EINVAL;
> > +
> > + if (in_img->hactive_size != 0U ||
> > + in_img->interpolation_mode !=
> HWD_VIIF_L1_INPUT_INTERPOLATION_LINE ||
> > + in_img->input_num != HWD_VIIF_L1_INPUT_NUM_MIN ||
> in_img->hobc_width != 0U ||
> > + in_img->hobc_margin != 0U) {
> > + return -EINVAL;
> > + }
> > +
> > + if (in_img->pixel_clock < HWD_VIIF_MIN_PIXEL_CLOCK ||
> > + in_img->pixel_clock > HWD_VIIF_MAX_PIXEL_CLOCK ||
> > + in_img->htotal_size < HWD_VIIF_MIN_HTOTAL_PIXEL ||
> > + in_img->htotal_size > HWD_VIIF_MAX_HTOTAL_PIXEL ||
> > + in_img->vtotal_size < HWD_VIIF_MIN_VTOTAL_LINE ||
> > + in_img->vtotal_size > HWD_VIIF_MAX_VTOTAL_LINE ||
> > + in_img->vbp_size < HWD_VIIF_MIN_VBP_LINE ||
> in_img->vbp_size > HWD_VIIF_MAX_VBP_LINE ||
> > + in_img->vactive_size <
> HWD_VIIF_MIN_VACTIVE_LINE_WO_L1ISP ||
> > + in_img->vactive_size >
> HWD_VIIF_MAX_VACTIVE_LINE_WO_L1ISP ||
> > + ((in_img->vactive_size % 2U) != 0U)) {
> > + return -EINVAL;
> > + }
> > +
> > + if (in_img->vtotal_size <= (in_img->vbp_size + in_img->vactive_size))
> > + return -EINVAL;
> > +
> > + /* Set DT of image data and DT of long packet data*/
> > + writel(dt_image, &res->capture_reg->sys.IPORTS_MAIN_DT);
> > + writel(0x00, &res->capture_reg->sys.IPORTS_OTHER);
> > +
> > + /* Set line size and delay value of delayed Vsync */
> > + sysclk_num = lineperiod_in_sysclk(in_img->htotal_size,
> in_img->pixel_clock);
> > + writel(sysclk_num & GENMASK(15, 0),
> &res->capture_reg->sys.INT_SA0_LINE);
> > + temp_delay = in_img->vbp_size - 4U;
> > + if (temp_delay > 255U) {
> > + /* Replace the value with HW max spec */
> > + temp_delay = 255U;
> > + }
> > + writel(temp_delay, &res->capture_reg->sys.INT_SA1_LINE);
> > +
> > + return 0;
> > +}
> > +
> > +/* DMA settings */
> > +#define VDMAC_SRAM_BASE_ADDR_W03 0x440U
> > +#define SRAM_SIZE_W_PORT 0x200
> > +#define PORT_SEL_SUB_IMAGE 3
> > +
> > +/**
> > + * hwd_viif_sub_set_img_transmission() - Set image transfer condition of
> SUB unit
> > + *
> > + * @img: Pointer to output image information
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] Member of "img" is invalid
> > + */
> > +s32 hwd_viif_sub_set_img_transmission(struct hwd_viif_res *res, const
> struct hwd_viif_img *img)
> > +{
> > + struct hwd_viif_vdm_write_port_reg *wport;
> > + u32 img_start_addr, img_end_addr;
> > + u32 data_width, pitch, height;
> > + u32 k, port_control;
> > +
> > + /* disable VDMAC when img is NULL */
> > + if (!img) {
> > + writel(HWD_VIIF_DISABLE,
> &res->capture_reg->sys.IPORTS_IMGEN);
> > + port_control = ~((u32)1U << 3U) &
> readl(&res->capture_reg->vdm.VDM_W_ENABLE);
> > + writel(port_control,
> &res->capture_reg->vdm.VDM_W_ENABLE);
> > + return 0;
> > + }
> > +
> > + if (((img->width % 2U) != 0U) || ((img->height % 2U) != 0U))
> > + return -EINVAL;
> > +
> > + if (img->width < HWD_VIIF_MIN_OUTPUT_IMG_WIDTH ||
> > + img->height < HWD_VIIF_MIN_OUTPUT_IMG_HEIGHT ||
> > + img->width > HWD_VIIF_MAX_OUTPUT_IMG_WIDTH_SUB ||
> > + img->height > HWD_VIIF_MAX_OUTPUT_IMG_HEIGHT_SUB) {
> > + return -EINVAL;
> > + }
> > +
> > + img_start_addr = (u32)img->pixelmap[0].pmap_paddr;
> > + pitch = img->pixelmap[0].pitch;
> > + height = img->height;
> > +
> > + switch (img->format) {
> > + case HWD_VIIF_ONE_COLOR_8:
> > + data_width = 0U;
> > + img_end_addr = img_start_addr + img->width - 1U;
> > + k = 1;
> > + break;
> > + case HWD_VIIF_ONE_COLOR_16:
> > + data_width = 1U;
> > + img_end_addr = img_start_addr + (img->width * 2U) - 1U;
> > + k = 2;
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> > +
> > + if ((img_start_addr % 4U) != 0U)
> > + return -EINVAL;
> > +
> > + if ((pitch < (img->width * k)) || pitch > HWD_VIIF_MAX_PITCH ||
> ((pitch % 4U) != 0U))
> > + return -EINVAL;
> > +
> > + wport = &res->capture_reg->vdm.w_port[PORT_SEL_SUB_IMAGE];
> > + writel(VDMAC_SRAM_BASE_ADDR_W03,
> &wport->VDM_W_SRAM_BASE);
> > + writel(SRAM_SIZE_W_PORT, &wport->VDM_W_SRAM_SIZE);
> > + writel(img_start_addr, &wport->VDM_W_STADR);
> > + writel(img_end_addr, &wport->VDM_W_ENDADR);
> > + writel(height, &wport->VDM_W_HEIGHT);
> > + writel(pitch, &wport->VDM_W_PITCH);
> > + writel(data_width << 8U, &wport->VDM_W_CFG0);
> > + port_control = BIT(3) |
> readl(&res->capture_reg->vdm.VDM_W_ENABLE);
> > + writel(port_control, &res->capture_reg->vdm.VDM_W_ENABLE);
> > + writel(HWD_VIIF_ENABLE, &res->capture_reg->sys.IPORTS_IMGEN);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_sub_status_err_set_irq_mask() -
> > + * Set mask condition for STATUS error of SUB unit or VOIF loopback
> > + *
> > + * @mask: STATUS error mask condition
> > + * Return: None
> > + */
> > +void hwd_viif_sub_status_err_set_irq_mask(struct hwd_viif_res *res, u32
> mask)
> > +{
> > + writel(mask, &res->capture_reg->sys.INT_S_MASK);
> > +}
> > +
> > +/**
> > + * hwd_viif_sub_vsync_set_irq_mask() - Set mask condition for Vsync of SUB
> unit or VOIF loopback
> > + *
> > + * @mask: Vsync mask condition
> > + * Return: None
> > + */
> > +void hwd_viif_sub_vsync_set_irq_mask(struct hwd_viif_res *res, const u32
> mask)
> > +{
> > + writel(mask, &res->capture_reg->sys.INT_S_SYNC_MASK);
> > +}
> > +
> > +/**
> > + * hwd_viif_isp_set_regbuf_auto_transmission() - Set register buffer auto
> transmission
> > + *
> > + * Return: None
> > + */
> > +void hwd_viif_isp_set_regbuf_auto_transmission(struct hwd_viif_res *res)
> > +{
> > + u32 val;
> > +
> > + /* Set parameters for auto read transmission of register buffer */
> > +
> > + if (res->dt_image_main_w_isp != 0x0U) {
> > + /*
> > + * configuration is done
> > + * only when dt_image is not 0, means image data is input to
> ISP.
> > + */
> > + writel(0x0,
> &res->capture_reg->l1isp.L1_CRGBF_TRN_A_CONF);
> > + writel(0x0,
> &res->capture_reg->l2isp.L2_CRGBF_TRN_A_CONF);
> > + writel(HWD_VIIF_L1_CRGBF_R_START_ADDR_LIMIT,
> > + &res->capture_reg->l1isp.L1_CRGBF_TRN_RBADDR);
> > + writel(HWD_VIIF_L1_CRGBF_R_END_ADDR_LIMIT,
> > + &res->capture_reg->l1isp.L1_CRGBF_TRN_READDR);
> > + writel(HWD_VIIF_L2_CRGBF_R_START_ADDR_LIMIT,
> > + &res->capture_reg->l2isp.L2_CRGBF_TRN_RBADDR);
> > + writel(HWD_VIIF_L2_CRGBF_R_END_ADDR_LIMIT,
> > + &res->capture_reg->l2isp.L2_CRGBF_TRN_READDR);
> > + val = BIT(16);
> > + writel(val,
> &res->capture_reg->l2isp.L2_CRGBF_TRN_A_CONF);
> > + writel(val,
> &res->capture_reg->l1isp.L1_CRGBF_TRN_A_CONF);
> > + }
> > +}
> > +
> > +/**
> > + * hwd_viif_isp_disable_regbuf_auto_transmission() - Disable register buffer
> auto transmission
> > + *
> > + * Return: None
> > + */
> > +void hwd_viif_isp_disable_regbuf_auto_transmission(struct hwd_viif_res
> *res)
> > +{
> > + if (res->dt_image_main_w_isp != 0x0U) {
> > + writel(0x0,
> &res->capture_reg->l1isp.L1_CRGBF_TRN_A_CONF);
> > + writel(0x0,
> &res->capture_reg->l2isp.L2_CRGBF_TRN_A_CONF);
> > + }
> > +}
> > +
> > +/**
> > + * hwd_viif_isp_guard_start() - stop register auto update
> > + *
> > + *
> > + * This function call stops update of some hardware registers
> > + * while the manual setup of VIIF, L1ISP registers is in progress.
> > + *
> > + * * regbuf control: load/store HW register (settings, status) values to backup
> SRAM.
> > + * * vlatch control: copy timer-counter register value to status register.
> > + */
> > +void hwd_viif_isp_guard_start(struct hwd_viif_res *res)
> > +{
> > + hwd_viif_isp_disable_regbuf_auto_transmission(res);
> > + ndelay(500);
> > + hwd_viif_main_mask_vlatch(res, HWD_VIIF_ENABLE);
> > +}
> > +
> > +/**
> > + * hwd_viif_isp_guard_start() - restart register auto update
> > + *
> > + *
> > + * see also hwd_viif_isp_guard_start().
> > + */
> > +void hwd_viif_isp_guard_end(struct hwd_viif_res *res)
> > +{
> > + hwd_viif_main_mask_vlatch(res, HWD_VIIF_DISABLE);
> > + hwd_viif_isp_set_regbuf_auto_transmission(res);
> > +}
> > +
> > +#define L2_STATUS_REPORT_MASK 0x1eU
> > +
> > +/**
> > + * hwd_viif_isp_get_info() - Get processing information of L1ISP and L2ISP
> > + *
> > + * @l1_info: L1ISP processing information
> > + * @l2_transfer_status: status of L2ISP transmission
> > + * Return: None
> > + */
> > +void hwd_viif_isp_get_info(struct hwd_viif_res *res, struct hwd_viif_l1_info
> *l1_info,
> > + u32 *l2_transfer_status)
> > +{
> > + u32 val, l2_status;
> > + int i, j;
> > +
> > + if (l1_info) {
> > + /* change register buffer to regbuf0 where driver gets
> information */
> > + writel(HWD_VIIF_ISP_REGBUF_MODE_BUFFER,
> &res->capture_reg->l1isp.L1_CRGBF_ACC_CONF);
> > +
> > + /* get AWB info */
> > + l1_info->awb_ave_u =
> readl(&res->capture_reg->l1isp.L1_AWHB_AVE_USIG);
> > + l1_info->awb_ave_v =
> readl(&res->capture_reg->l1isp.L1_AWHB_AVE_VSIG);
> > + l1_info->awb_accumulated_pixel =
> readl(&res->capture_reg->l1isp.L1_AWHB_NUM_UVON);
> > + l1_info->awb_gain_r =
> readl(&res->capture_reg->l1isp.L1_AWHB_AWBGAINR);
> > + l1_info->awb_gain_g =
> readl(&res->capture_reg->l1isp.L1_AWHB_AWBGAING);
> > + l1_info->awb_gain_b =
> readl(&res->capture_reg->l1isp.L1_AWHB_AWBGAINB);
> > + val =
> readl(&res->capture_reg->l1isp.L1_AWHB_R_CTR_STOP);
> > + l1_info->awb_status_u = (FIELD_GET(BIT(1), val) != 0);
> > + l1_info->awb_status_v = (FIELD_GET(BIT(0), val) != 0);
> > +
> > + /* get average luminance info */
> > + l1_info->avg_lum_weight =
> readl(&res->capture_reg->l1isp.L1_AEXP_RESULT_AVE);
> > + val =
> readl(&res->capture_reg->l1isp.L1_AEXP_SATUR_BLACK_PIXNUM);
> > + l1_info->avg_satur_pixnum = FIELD_GET(GENMASK(31, 16),
> val);
> > + l1_info->avg_black_pixnum = FIELD_GET(GENMASK(15, 0),
> val);
> > + for (i = 0; i < 8; i++) {
> > + for (j = 0; j < 8; j++) {
> > + l1_info->avg_lum_block[i][j] =
> > +
> readl(&res->capture_reg->l1isp.L1_AEXP_AVE[i][j]);
> > + }
> > + }
> > + l1_info->avg_lum_four_line_lum[0] =
> > +
> readl(&res->capture_reg->l1isp.L1_AEXP_AVE4LINES0);
> > + l1_info->avg_lum_four_line_lum[1] =
> > +
> readl(&res->capture_reg->l1isp.L1_AEXP_AVE4LINES1);
> > + l1_info->avg_lum_four_line_lum[2] =
> > +
> readl(&res->capture_reg->l1isp.L1_AEXP_AVE4LINES2);
> > + l1_info->avg_lum_four_line_lum[3] =
> > +
> readl(&res->capture_reg->l1isp.L1_AEXP_AVE4LINES3);
> > +
> > + /* revert to register access from register buffer access */
> > + writel(HWD_VIIF_ISP_REGBUF_MODE_BYPASS,
> &res->capture_reg->l1isp.L1_CRGBF_ACC_CONF);
> > + }
> > +
> > + if (l2_transfer_status) {
> > + /* get L2ISP abort information */
> > + l2_status =
> readl(&res->capture_reg->l2isp.L2_CRGBF_ISP_INT);
> > + writel(l2_status,
> &res->capture_reg->l2isp.L2_CRGBF_ISP_INT);
> > + *l2_transfer_status = l2_status &
> L2_STATUS_REPORT_MASK;
> > + }
> > +}
> > +
> > +/**
> > + * hwd_viif_isp_set_regbuf_irq_mask() - Set mask condition for ISP register
> buffer
> > + *
> > + * @mask_l1: Pointer to mask configuration for L1ISP register buffer
> interruption
> > + * @mask_l2: Pointer to mask configuration for L2ISP register buffer
> interruption
> > + * Return: None
> > + */
> > +void hwd_viif_isp_set_regbuf_irq_mask(struct hwd_viif_res *res, const u32
> *mask_l1,
> > + const u32 *mask_l2)
> > +{
> > + writel(*mask_l1, &res->capture_reg->l1isp.L1_CRGBF_INT_MASK);
> > + writel(*mask_l2, &res->capture_reg->l2isp.L2_CRGBF_INT_MASK);
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_input_csc() - Set input CSC parameters of L2ISP
> > + *
> > + * @param: Pointer to input csc parameters of L2ISP
> > + * @is_l1_rgb: input information of L2ISP
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] Member of "param" is invalid
> > + */
> > +s32 hwd_viif_l2_set_input_csc(struct hwd_viif_res *res, const struct
> hwd_viif_csc_param *param,
> > + bool is_l1_rgb)
> > +{
> > + struct hwd_viif_csc_param hwd_param;
> > + u32 enable = HWD_VIIF_ENABLE;
> > + bool csc_enable_flag = true;
> > + u32 i, val;
> > +
> > + if (param) {
> > + if (param->r_cr_in_offset > HWD_VIIF_CSC_MAX_OFFSET ||
> > + param->g_y_in_offset > HWD_VIIF_CSC_MAX_OFFSET ||
> > + param->b_cb_in_offset > HWD_VIIF_CSC_MAX_OFFSET
> ||
> > + param->r_cr_out_offset > HWD_VIIF_CSC_MAX_OFFSET
> ||
> > + param->g_y_out_offset > HWD_VIIF_CSC_MAX_OFFSET
> ||
> > + param->b_cb_out_offset >
> HWD_VIIF_CSC_MAX_OFFSET) {
> > + return -EINVAL;
> > + }
> > +
> > + for (i = 0; i < HWD_VIIF_CSC_MAX_COEF_NUM; i++) {
> > + if (param->coef[i] >
> HWD_VIIF_CSC_MAX_COEF_VALUE)
> > + return -EINVAL;
> > + }
> > +
> > + if (is_l1_rgb) {
> > + /* translated parameters are used */
> > + hwd_param.r_cr_in_offset = param->b_cb_in_offset;
> > + hwd_param.g_y_in_offset = param->r_cr_in_offset;
> > + hwd_param.b_cb_in_offset = param->g_y_in_offset;
> > + hwd_param.r_cr_out_offset = param->r_cr_out_offset;
> > + hwd_param.g_y_out_offset = param->g_y_out_offset;
> > + hwd_param.b_cb_out_offset =
> param->b_cb_out_offset;
> > + hwd_param.coef[0] = param->coef[2];
> > + hwd_param.coef[1] = param->coef[0];
> > + hwd_param.coef[2] = param->coef[1];
> > + hwd_param.coef[3] = param->coef[5];
> > + hwd_param.coef[4] = param->coef[3];
> > + hwd_param.coef[5] = param->coef[4];
> > + hwd_param.coef[6] = param->coef[8];
> > + hwd_param.coef[7] = param->coef[6];
> > + hwd_param.coef[8] = param->coef[7];
> > + } else {
> > + /* original parameters are used */
> > + hwd_param.r_cr_in_offset = param->r_cr_in_offset;
> > + hwd_param.g_y_in_offset = param->g_y_in_offset;
> > + hwd_param.b_cb_in_offset = param->b_cb_in_offset;
> > + hwd_param.r_cr_out_offset = param->r_cr_out_offset;
> > + hwd_param.g_y_out_offset = param->g_y_out_offset;
> > + hwd_param.b_cb_out_offset =
> param->b_cb_out_offset;
> > + hwd_param.coef[0] = param->coef[0];
> > + hwd_param.coef[1] = param->coef[1];
> > + hwd_param.coef[2] = param->coef[2];
> > + hwd_param.coef[3] = param->coef[3];
> > + hwd_param.coef[4] = param->coef[4];
> > + hwd_param.coef[5] = param->coef[5];
> > + hwd_param.coef[6] = param->coef[6];
> > + hwd_param.coef[7] = param->coef[7];
> > + hwd_param.coef[8] = param->coef[8];
> > + }
> > + } else {
> > + if (is_l1_rgb) {
> > + /* fixed parameters are used */
> > + hwd_param.r_cr_in_offset = 0U;
> > + hwd_param.g_y_in_offset = 0U;
> > + hwd_param.b_cb_in_offset = 0U;
> > + hwd_param.r_cr_out_offset = 0U;
> > + hwd_param.g_y_out_offset = 0U;
> > + hwd_param.b_cb_out_offset = 0U;
> > + hwd_param.coef[0] = 0U;
> > + hwd_param.coef[1] = 0x1000U;
> > + hwd_param.coef[2] = 0U;
> > + hwd_param.coef[3] = 0U;
> > + hwd_param.coef[4] = 0U;
> > + hwd_param.coef[5] = 0x1000U;
> > + hwd_param.coef[6] = 0x1000U;
> > + hwd_param.coef[7] = 0U;
> > + hwd_param.coef[8] = 0U;
> > + } else {
> > + /* csc is disabled */
> > + enable = HWD_VIIF_DISABLE;
> > + csc_enable_flag = false;
> > + }
> > + }
> > +
> > + if (csc_enable_flag) {
> > + writel(hwd_param.g_y_in_offset,
> > +
> &res->capture_reg->sys.l2isp_input_csc.MTB_YG_OFFSETI);
> > + writel(hwd_param.coef[0],
> &res->capture_reg->sys.l2isp_input_csc.MTB_YG1);
> > + val = (hwd_param.coef[1] <<
> HWD_VIIF_MTB_CB_YG_COEF_OFFSET) |
> > + (hwd_param.coef[2] <<
> HWD_VIIF_MTB_CR_YG_COEF_OFFSET);
> > + writel(val, &res->capture_reg->sys.l2isp_input_csc.MTB_YG2);
> > + writel(hwd_param.g_y_out_offset,
> > +
> &res->capture_reg->sys.l2isp_input_csc.MTB_YG_OFFSETO);
> > + writel(hwd_param.b_cb_in_offset,
> > +
> &res->capture_reg->sys.l2isp_input_csc.MTB_CB_OFFSETI);
> > + writel(hwd_param.coef[3],
> &res->capture_reg->sys.l2isp_input_csc.MTB_CB1);
> > + val = (hwd_param.coef[4] <<
> HWD_VIIF_MTB_CB_CB_COEF_OFFSET) |
> > + (hwd_param.coef[5] <<
> HWD_VIIF_MTB_CR_CB_COEF_OFFSET);
> > + writel(val, &res->capture_reg->sys.l2isp_input_csc.MTB_CB2);
> > + writel(hwd_param.b_cb_out_offset,
> > +
> &res->capture_reg->sys.l2isp_input_csc.MTB_CB_OFFSETO);
> > + writel(hwd_param.r_cr_in_offset,
> > +
> &res->capture_reg->sys.l2isp_input_csc.MTB_CR_OFFSETI);
> > + writel(hwd_param.coef[6],
> &res->capture_reg->sys.l2isp_input_csc.MTB_CR1);
> > + val = (hwd_param.coef[7] <<
> HWD_VIIF_MTB_CB_CR_COEF_OFFSET) |
> > + (hwd_param.coef[8] <<
> HWD_VIIF_MTB_CR_CR_COEF_OFFSET);
> > + writel(val, &res->capture_reg->sys.l2isp_input_csc.MTB_CR2);
> > + writel(hwd_param.r_cr_out_offset,
> > +
> &res->capture_reg->sys.l2isp_input_csc.MTB_CR_OFFSETO);
> > + }
> > +
> > + writel(enable, &res->capture_reg->sys.l2isp_input_csc.MTB);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_undist() - Set undistortion parameters of L2ISP
> > + *
> > + * @param: Pointer to undistortion parameters of L2ISP
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] "param" is NULL
> > + * - [2] Member of "param" is invalid
> > + */
> > +s32 hwd_viif_l2_set_undist(struct hwd_viif_res *res, const struct
> viif_l2_undist *param)
> > +{
> > + u32 grid_num_h, grid_num_v;
> > + u32 i, val;
> > +
> > + if (!param)
> > + return -EINVAL;
> > +
> > + if (param->through_mode != HWD_VIIF_ENABLE &&
> param->through_mode != HWD_VIIF_DISABLE)
> > + return -EINVAL;
> > +
> > + if (param->roi_mode[0] != HWD_VIIF_L2_UNDIST_POLY &&
> > + param->roi_mode[0] != HWD_VIIF_L2_UNDIST_GRID &&
> > + param->roi_mode[0] != HWD_VIIF_L2_UNDIST_POLY_TO_GRID
> &&
> > + param->roi_mode[0] != HWD_VIIF_L2_UNDIST_GRID_TO_POLY)
> {
> > + return -EINVAL;
> > + }
> > + if (param->roi_mode[1] != HWD_VIIF_L2_UNDIST_POLY &&
> > + param->roi_mode[1] != HWD_VIIF_L2_UNDIST_GRID &&
> > + param->roi_mode[1] != HWD_VIIF_L2_UNDIST_POLY_TO_GRID
> &&
> > + param->roi_mode[1] != HWD_VIIF_L2_UNDIST_GRID_TO_POLY)
> {
> > + return -EINVAL;
> > + }
> > + if (param->roi_write_area_delta[0] >=
> HWD_VIIF_L2_UNDIST_MAX_ROI_WRITE_AREA_DELTA ||
> > + param->roi_write_area_delta[1] >=
> HWD_VIIF_L2_UNDIST_MAX_ROI_WRITE_AREA_DELTA ||
> > + param->sensor_crop_ofs_h <
> HWD_VIIF_L2_UNDIST_MIN_SENSOR_CROP_OFS_H ||
> > + param->sensor_crop_ofs_h >
> HWD_VIIF_L2_UNDIST_MAX_SENSOR_CROP_OFS_H ||
> > + param->sensor_crop_ofs_v <
> HWD_VIIF_L2_UNDIST_MIN_SENSOR_CROP_OFS_V ||
> > + param->sensor_crop_ofs_v >
> HWD_VIIF_L2_UNDIST_MAX_SENSOR_CROP_OFS_V ||
> > + param->norm_scale >
> HWD_VIIF_L2_UNDIST_MAX_NORM_SCALE ||
> > + param->valid_r_norm2_poly >=
> HWD_VIIF_L2_UNDIST_MAX_VALID_R_NORM2 ||
> > + param->valid_r_norm2_grid >=
> HWD_VIIF_L2_UNDIST_MAX_VALID_R_NORM2) {
> > + return -EINVAL;
> > + }
> > +
> > + for (i = 0; i < HWD_VIIF_L2_UNDIST_POLY_NUM; i++) {
> > + if (param->poly_write_g_coef[i] <
> HWD_VIIF_L2_UNDIST_MIN_POLY_COEF ||
> > + param->poly_write_g_coef[i] >
> HWD_VIIF_L2_UNDIST_MAX_POLY_COEF ||
> > + param->poly_read_b_coef[i] <
> HWD_VIIF_L2_UNDIST_MIN_POLY_COEF ||
> > + param->poly_read_b_coef[i] >
> HWD_VIIF_L2_UNDIST_MAX_POLY_COEF ||
> > + param->poly_read_g_coef[i] <
> HWD_VIIF_L2_UNDIST_MIN_POLY_COEF ||
> > + param->poly_read_g_coef[i] >
> HWD_VIIF_L2_UNDIST_MAX_POLY_COEF ||
> > + param->poly_read_r_coef[i] <
> HWD_VIIF_L2_UNDIST_MIN_POLY_COEF ||
> > + param->poly_read_r_coef[i] >
> HWD_VIIF_L2_UNDIST_MAX_POLY_COEF) {
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + if (param->grid_node_num_h <
> HWD_VIIF_L2_UNDIST_MIN_GRID_NUM ||
> > + param->grid_node_num_h >
> HWD_VIIF_L2_UNDIST_MAX_GRID_NUM ||
> > + param->grid_node_num_v <
> HWD_VIIF_L2_UNDIST_MIN_GRID_NUM ||
> > + param->grid_node_num_v >
> HWD_VIIF_L2_UNDIST_MAX_GRID_NUM) {
> > + return -EINVAL;
> > + }
> > +
> > + grid_num_h = param->grid_node_num_h;
> > + grid_num_v = param->grid_node_num_v;
> > + if ((grid_num_h % 2U) != 0U)
> > + grid_num_h += 1U;
> > +
> > + if ((grid_num_v % 2U) != 0U)
> > + grid_num_v += 1U;
> > +
> > + if ((grid_num_v * grid_num_h) >
> HWD_VIIF_L2_UNDIST_MAX_GRID_TOTAL_NUM ||
> > + param->grid_patch_hsize_inv >=
> HWD_VIIF_L2_UNDIST_MAX_GRID_PATCH_SIZE_INV ||
> > + param->grid_patch_vsize_inv >=
> HWD_VIIF_L2_UNDIST_MAX_GRID_PATCH_SIZE_INV) {
> > + return -EINVAL;
> > + }
> > +
> > + val = readl(&res->capture_reg->l2isp.L2_SENSOR_CROP_HSIZE) &
> GENMASK(12, 0);
> > + if (((param->sensor_crop_ofs_h / 2) + ((s16)val)) > 4095)
> > + return -EINVAL;
> > +
> > + val = readl(&res->capture_reg->l2isp.L2_SENSOR_CROP_VSIZE) &
> GENMASK(11, 0);
> > + if (((param->sensor_crop_ofs_v / 2) + ((s16)val)) > 2047)
> > + return -EINVAL;
> > +
> > + /* set parameters related to L2ISP UNDIST */
> > + if (param->through_mode == HWD_VIIF_ENABLE) {
> > + /* Enable through mode */
> > + writel(HWD_VIIF_ENABLE,
> &res->capture_reg->l2isp.L2_MODE);
> > + } else {
> > + val = (param->roi_mode[0] << 1U) | (param->roi_mode[1] <<
> 3U);
> > + writel(val, &res->capture_reg->l2isp.L2_MODE);
> > + val = (u32)param->sensor_crop_ofs_h & GENMASK(13, 0);
> > + writel(val,
> &res->capture_reg->l2isp.L2_SENSOR_CROP_OFS_H);
> > + val = (u32)param->sensor_crop_ofs_v & GENMASK(12, 0);
> > + writel(val,
> &res->capture_reg->l2isp.L2_SENSOR_CROP_OFS_V);
> > + writel(param->norm_scale,
> &res->capture_reg->l2isp.L2_NORM_SCALE);
> > + writel(param->valid_r_norm2_poly,
> &res->capture_reg->l2isp.L2_VALID_R_NORM2_POLY);
> > + writel(param->valid_r_norm2_grid,
> &res->capture_reg->l2isp.L2_VALID_R_NORM2_GRID);
> > + writel(param->roi_write_area_delta[0],
> > +
> &res->capture_reg->l2isp.L2_ROI_WRITE_AREA_DELTA[0]);
> > + writel(param->roi_write_area_delta[1],
> > +
> &res->capture_reg->l2isp.L2_ROI_WRITE_AREA_DELTA[1]);
> > +
> > + for (i = 0; i < HWD_VIIF_L2_UNDIST_POLY_NUM; i++) {
> > + val = (u32)param->poly_write_g_coef[i];
> > + writel(val,
> &res->capture_reg->l2isp.L2_POLY10_WRITE_G_COEF[i]);
> > + val = (u32)param->poly_read_b_coef[i];
> > + writel(val,
> &res->capture_reg->l2isp.L2_POLY10_READ_B_COEF[i]);
> > + val = (u32)param->poly_read_g_coef[i];
> > + writel(val,
> &res->capture_reg->l2isp.L2_POLY10_READ_G_COEF[i]);
> > + val = (u32)param->poly_read_r_coef[i];
> > + writel(val,
> &res->capture_reg->l2isp.L2_POLY10_READ_R_COEF[i]);
> > + }
> > + writel(param->grid_node_num_h,
> &res->capture_reg->l2isp.L2_GRID_NODE_NUM_H);
> > + writel(param->grid_node_num_v,
> &res->capture_reg->l2isp.L2_GRID_NODE_NUM_V);
> > + writel(param->grid_patch_hsize_inv,
> > +
> &res->capture_reg->l2isp.L2_GRID_PATCH_HSIZE_INV);
> > + writel(param->grid_patch_vsize_inv,
> > +
> &res->capture_reg->l2isp.L2_GRID_PATCH_VSIZE_INV);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_undist_table_transmission() -
> > + * Configure L2ISP transferring grid table for undistortion.
> > + *
> > + * @write_g: grid table address for G-WRITE(physical address)
> > + * @read_b: grid table address for B-READ(physical address)
> > + * @read_g: grid table address for G-READ(physical address)
> > + * @read_r: grid table address for R-READ(physical address)
> > + * @size: of each table [1024..8192] [byte]
> > + * Return: 0 operation completed successfully
> > + * Return: -EINVAL Parameter error
> > + * - "write_g", "read_b", "read_g" or "read_r" is not 4byte alignment
> > + * - "size" is out of range
> > + * - "size" is not 0 when all table addresses are 0
> > + */
> > +s32 hwd_viif_l2_set_undist_table_transmission(struct hwd_viif_res *res,
> uintptr_t write_g,
> > + uintptr_t read_b, uintptr_t
> read_g, uintptr_t read_r,
> > + u32 size)
> > +{
> > + u32 val = 0U;
> > +
> > + if (((write_g % HWD_VIIF_L2_VDM_ALIGN) != 0U) || ((read_b %
> HWD_VIIF_L2_VDM_ALIGN) != 0U) ||
> > + ((read_g % HWD_VIIF_L2_VDM_ALIGN) != 0U) || ((read_r %
> HWD_VIIF_L2_VDM_ALIGN) != 0U)) {
> > + return -EINVAL;
> > + }
> > +
> > + if ((size != 0U && size < HWD_VIIF_L2_UNDIST_MIN_TABLE_SIZE) ||
> > + size > HWD_VIIF_L2_UNDIST_MAX_TABLE_SIZE) {
> > + return -EINVAL;
> > + }
> > +
> > + if ((size % 4U) != 0U)
>
> size % 4 is enough.

I'll drop comparison with zero.

> > + return -EINVAL;
> > +
> > + if (write_g == 0U && read_b == 0U && read_g == 0U && read_r == 0U
> && size != 0U)
> > + return -EINVAL;
> > +
> > + if ((write_g != 0U || read_b != 0U || read_g != 0U || read_r != 0U) &&
> size == 0U)
> > + return -EINVAL;
>
> No explicit comparison with zero is needed here. Same below.

I'll drop explicit comparison with zero. Same for other lines.

> > +
> > + /* read_b: t_port[8], read_g: t_port[9], read_r: t_port[10], write_g:
> t_port[11] */
> > + if (read_b != 0U) {
> > + writel((u32)read_b,
> &res->capture_reg->vdm.t_port[8].VDM_T_STADR);
> > + writel(size, &res->capture_reg->vdm.t_port[8].VDM_T_SIZE);
> > + val |= BIT(8);
> > + }
> > + if (read_g != 0U) {
> > + writel((u32)read_g,
> &res->capture_reg->vdm.t_port[9].VDM_T_STADR);
> > + writel(size, &res->capture_reg->vdm.t_port[9].VDM_T_SIZE);
> > + val |= BIT(9);
> > + }
> > + if (read_r != 0U) {
> > + writel((u32)read_r,
> &res->capture_reg->vdm.t_port[10].VDM_T_STADR);
> > + writel(size, &res->capture_reg->vdm.t_port[10].VDM_T_SIZE);
> > + val |= BIT(10);
> > + }
> > + if (write_g != 0U) {
> > + writel((u32)write_g,
> &res->capture_reg->vdm.t_port[11].VDM_T_STADR);
> > + writel(size, &res->capture_reg->vdm.t_port[11].VDM_T_SIZE);
> > + val |= BIT(11);
> > + }
> > +
> > + if (val != 0U) {
> > + /*
> > + * Set SRAM base address and size.
> > + * t_group[1] is used only to transfer UNDIST table
> > + */
> > + writel(HWD_VIIF_VDM_CFG_PARAM,
> &res->capture_reg->vdm.t_group[1].VDM_T_CFG);
> > + writel(HWD_VIIF_L2_VDM_GRID_SRAM_BASE,
> > +
> &res->capture_reg->vdm.t_group[1].VDM_T_SRAM_BASE);
> > + writel(HWD_VIIF_L2_VDM_GRID_SRAM_SIZE,
> > +
> &res->capture_reg->vdm.t_group[1].VDM_T_SRAM_SIZE);
> > + }
> > +
> > + val |= (readl(&res->capture_reg->vdm.VDM_T_ENABLE) &
> ~((u32)0xfU << 8U));
> > + writel(val, &res->capture_reg->vdm.VDM_T_ENABLE);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_roi_num_1() - Set ROI path condition when ROI num is 1
> > + */
> > +static void hwd_viif_l2_set_roi_num_1(struct hwd_viif_res *res)
> > +{
> > + struct hwd_viif_l2_roi_path_info *info = &res->l2_roi_path_info;
> > + u32 val, x_min, x_max, y_min, y_max;
> > + u32 i, x, y, w, h;
> > +
> > + /* ROI0 is input to POST0 and POST1 */
> > + if (info->post_enable_flag[0]) {
> > + /* POST0 is enabled */
> > + x_min = info->post_crop_x[0];
> > + x_max = info->post_crop_x[0] + info->post_crop_w[0];
> > + y_min = info->post_crop_y[0];
> > + y_max = info->post_crop_y[0] + info->post_crop_h[0];
> > + if (info->post_enable_flag[1]) {
> > + /* POST1 is enabled */
> > + x_min = min(x_min, info->post_crop_x[1]);
> > + val = info->post_crop_x[1] + info->post_crop_w[1];
> > + x_max = max(x_max, val);
> > + y_min = min(y_min, info->post_crop_y[1]);
> > + val = info->post_crop_y[1] + info->post_crop_h[1];
> > + y_max = max(y_max, val);
> > + }
> > + x = x_min;
> > + y = y_min;
> > + w = x_max - x_min;
> > + h = y_max - y_min;
> > + } else if (info->post_enable_flag[1]) {
> > + /* POST0 is disabled and POST1 is enabled */
> > + x = info->post_crop_x[1];
> > + w = info->post_crop_w[1];
> > + y = info->post_crop_y[1];
> > + h = info->post_crop_h[1];
> > + } else {
> > + /* All POSTs are disabled */
> > + x = 0;
> > + y = 0;
> > + w = HWD_VIIF_CROP_MIN_W;
> > + h = HWD_VIIF_CROP_MIN_H;
> > + }
> > + writel(x, &res->capture_reg->l2isp.roi[0].L2_ROI_OUT_OFS_H);
> > + writel(y, &res->capture_reg->l2isp.roi[0].L2_ROI_OUT_OFS_V);
> > + writel(w, &res->capture_reg->l2isp.roi[0].L2_ROI_OUT_HSIZE);
> > + writel(h, &res->capture_reg->l2isp.roi[0].L2_ROI_OUT_VSIZE);
> > +
> > + for (i = 0; i < HWD_VIIF_MAX_POST_NUM; i++) {
> > + if (info->post_enable_flag[i])
> > + writel(0,
> &res->capture_reg->l2isp.L2_ROI_TO_POST[i]);
> > + else
> > + writel(HWD_VIIF_L2_ROI_NONE,
> &res->capture_reg->l2isp.L2_ROI_TO_POST[i]);
>
> This might be more readable as
>
> writel (info->post_enable_flag[i] ? 0 : HWD_VIIF_L2_ROI_NONE,
> ...);
>
> Up to you.

Thank you for an advice. I'll try.

> > + }
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_roi_num_2() - Set ROI path condition when ROI num is 2
> > + */
> > +static void hwd_viif_l2_set_roi_num_2(struct hwd_viif_res *res)
> > +{
> > + struct hwd_viif_l2_roi_path_info *info = &res->l2_roi_path_info;
> > + u32 i;
> > +
> > + for (i = 0; i < HWD_VIIF_L2_ROI_MAX_NUM; i++) {
> > + /* ROI-n is the same as CROP area of POST-n */
> > + if (info->post_enable_flag[i]) {
> > + writel(info->post_crop_x[i],
> > +
> &res->capture_reg->l2isp.roi[i].L2_ROI_OUT_OFS_H);
> > + writel(info->post_crop_y[i],
> > +
> &res->capture_reg->l2isp.roi[i].L2_ROI_OUT_OFS_V);
> > + writel(info->post_crop_w[i],
> > +
> &res->capture_reg->l2isp.roi[i].L2_ROI_OUT_HSIZE);
> > + writel(info->post_crop_h[i],
> > +
> &res->capture_reg->l2isp.roi[i].L2_ROI_OUT_VSIZE);
> > + writel(i,
> &res->capture_reg->l2isp.L2_ROI_TO_POST[i]);
> > + } else {
> > + writel(0,
> &res->capture_reg->l2isp.roi[i].L2_ROI_OUT_OFS_H);
> > + writel(0,
> &res->capture_reg->l2isp.roi[i].L2_ROI_OUT_OFS_V);
> > + writel(HWD_VIIF_CROP_MIN_W,
> > +
> &res->capture_reg->l2isp.roi[i].L2_ROI_OUT_HSIZE);
> > + writel(HWD_VIIF_CROP_MIN_H,
> > +
> &res->capture_reg->l2isp.roi[i].L2_ROI_OUT_VSIZE);
> > + writel(HWD_VIIF_L2_ROI_NONE,
> &res->capture_reg->l2isp.L2_ROI_TO_POST[i]);
> > + }
> > + }
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_roi_path() - Set ROI path condition
> > + */
> > +static void hwd_viif_l2_set_roi_path(struct hwd_viif_res *res)
> > +{
> > + if (res->l2_roi_path_info.roi_num == 1U)
> > + hwd_viif_l2_set_roi_num_1(res);
> > + else
> > + hwd_viif_l2_set_roi_num_2(res);
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_roi() - Set ROI parameters of L2ISP
> > + *
> > + * @param: Pointer to ROI parameters of L2ISP
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] "param" is NULL
> > + * - [2] Member of "param" is invalid
> > + *
> > + * see also: #hwd_viif_l2_set_roi_path
> > + */
> > +s32 hwd_viif_l2_set_roi(struct hwd_viif_res *res, const struct
> viif_l2_roi_config *param)
> > +{
> > + u32 val;
> > + int i;
> > +
> > + if (!param)
> > + return -EINVAL;
> > +
> > + if (param->roi_num < 1 || param->roi_num > 2)
> > + return -EINVAL;
> > +
> > + for (i = 0; i < 2; i++) {
> > + if (param->roi_scale[i] < HWD_VIIF_L2_ROI_MIN_SCALE ||
> > + param->roi_scale[i] > HWD_VIIF_L2_ROI_MAX_SCALE ||
> > + param->roi_scale_inv[i] <
> HWD_VIIF_L2_ROI_MIN_SCALE_INV ||
> > + param->roi_scale_inv[i] >
> HWD_VIIF_L2_ROI_MAX_SCALE_INV ||
> > + param->corrected_wo_scale_hsize[i] <
> > +
> HWD_VIIF_L2_ROI_MIN_CORRECTED_WO_SCALE_HSIZE ||
> > + param->corrected_wo_scale_hsize[i] >
> > +
> HWD_VIIF_L2_ROI_MAX_CORRECTED_WO_SCALE_HSIZE ||
> > + param->corrected_wo_scale_vsize[i] <
> > +
> HWD_VIIF_L2_ROI_MIN_CORRECTED_WO_SCALE_VSIZE ||
> > + param->corrected_wo_scale_vsize[i] >
> > +
> HWD_VIIF_L2_ROI_MAX_CORRECTED_WO_SCALE_VSIZE ||
> > + param->corrected_hsize[i] <
> HWD_VIIF_L2_ROI_MIN_CORRECTED_HSIZE ||
> > + param->corrected_hsize[i] >
> HWD_VIIF_L2_ROI_MAX_CORRECTED_HSIZE ||
> > + param->corrected_vsize[i] <
> HWD_VIIF_L2_ROI_MIN_CORRECTED_VSIZE ||
> > + param->corrected_vsize[i] >
> HWD_VIIF_L2_ROI_MAX_CORRECTED_VSIZE) {
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + /* Set the number of ROI and update resource info with roi_num */
> > + writel(param->roi_num, &res->capture_reg->l2isp.L2_ROI_NUM);
> > + res->l2_roi_path_info.roi_num = param->roi_num;
> > +
> > + /* Update ROI area and input to each POST */
> > + hwd_viif_l2_set_roi_path(res);
> > +
> > + /* Set the remaining parameters */
> > + for (i = 0; i < 2; i++) {
> > + writel(param->roi_scale[i],
> &res->capture_reg->l2isp.roi[i].L2_ROI_SCALE);
> > + writel(param->roi_scale_inv[i],
> &res->capture_reg->l2isp.roi[i].L2_ROI_SCALE_INV);
> > + val = (param->corrected_wo_scale_hsize[i] << 13U) |
> param->corrected_hsize[i];
> > + writel(val,
> &res->capture_reg->l2isp.roi[i].L2_ROI_CORRECTED_HSIZE);
> > + val = (param->corrected_wo_scale_vsize[i] << 12U) |
> param->corrected_vsize[i];
> > + writel(val,
> &res->capture_reg->l2isp.roi[i].L2_ROI_CORRECTED_VSIZE);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_gamma() - Set Gamma correction parameters of L2ISP
> > + *
> > + * @post_id: POST ID [0..1]
> > + * @enable: or disable gamma correction of L2ISP. For more refer @ref
> hwd_viif_enable_flag.
> > + * @vsplit: changing line position from 1st table to 2nd table [0..4094]
> > + * @mode: Gamma correction mode. For more refer @ref
> hwd_viif_gamma_table_mode.
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] "post_id", "enable", "vsplit" or "mode" is out of range
> > + * - [2] "vsplit" is not 0 when "enable" is HWD_VIIF_DISABLE
> > + * - [3] "mode" is not HWD_VIIF_GAMMA_COMPRESSED when enable is
> HWD_VIIF_DISABLE
> > + *
> > + * see also: #hwd_viif_l2_set_gamma
> > + */
> > +s32 hwd_viif_l2_set_gamma(struct hwd_viif_res *res, u32 post_id, u32
> enable, u32 vsplit, u32 mode)
> > +{
> > + u32 val;
> > +
> > + if (post_id >= HWD_VIIF_MAX_POST_NUM ||
> > + (enable != HWD_VIIF_ENABLE && enable != HWD_VIIF_DISABLE)
> ||
> > + vsplit > HWD_VIIF_GAMMA_MAX_VSPLIT ||
> > + (mode != HWD_VIIF_GAMMA_COMPRESSED && mode !=
> HWD_VIIF_GAMMA_LINEAR) ||
> > + (enable == HWD_VIIF_DISABLE && vsplit != 0x0U) ||
> > + (enable == HWD_VIIF_DISABLE && mode !=
> HWD_VIIF_GAMMA_COMPRESSED)) {
> > + return -EINVAL;
> > + }
> > +
> > + /* Set gamma parameters of L2ISP */
> > + val = (vsplit << 16U) | (mode << 4U) | enable;
> > + writel(val,
> &res->capture_reg->l2isp.post[post_id].L2_POST_GAMMA_M);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_gamma_table_transmission() - Configure L2ISP
> transferring gamma table.
> > + *
> > + * @post_id: POST ID [0..1]
> > + * @gamma_table: Pointer to gamma table information
> > + * Return: 0 operation completed successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] "post_id" is out of range
> > + * - [2] Member of "gamma_table" is invalid
> > + */
> > +s32 hwd_viif_l2_set_gamma_table_transmission(struct hwd_viif_res *res,
> u32 post_id,
> > + const struct
> hwd_viif_l2_gamma_table *gamma_table)
> > +{
> > + u32 vdm_enable = 0U;
> > + u32 i, base_addr;
> > +
> > + if (post_id >= HWD_VIIF_MAX_POST_NUM)
> > + return -EINVAL;
> > +
> > + for (i = 0; i < 6U; i++) {
> > + if ((gamma_table->table[i] % HWD_VIIF_L2_VDM_ALIGN) !=
> 0U)
> > + return -EINVAL;
> > + }
> > +
> > + /* table[0]: LUT0-G/Y: t_port[12 + post_id * 6] */
> > + /* table[1]: LUT1-G/Y: t_port[13 + post_id * 6] */
> > + /* table[2]: LUT0-B/U: t_port[14 + post_id * 6] */
> > + /* table[3]: LUT1-B/U: t_port[15 + post_id * 6] */
> > + /* table[4]: LUT0-R/V: t_port[16 + post_id * 6] */
> > + /* table[5]: LUT1-R/V: t_port[17 + post_id * 6] */
> > + for (i = 0; i < 6U; i++) {
> > + if (gamma_table->table[i] != 0U) {
> > + int idx = 12U + i + post_id * 6U;
> > +
> > + writel((u32)gamma_table->table[i],
> > +
> &res->capture_reg->vdm.t_port[idx].VDM_T_STADR);
> > + writel(HWD_VIIF_L2_VDM_GAMMA_TABLE_SIZE,
> > +
> &res->capture_reg->vdm.t_port[idx].VDM_T_SIZE);
> > + vdm_enable |= BIT(i);
> > + }
> > + }
> > + if (vdm_enable != 0U) {
> > + /* t_group[2..3] is used only to transfer GAMMA table */
> > + /* [2]: POST0, [3]: POST1 */
> > + writel(HWD_VIIF_VDM_CFG_PARAM,
> > + &res->capture_reg->vdm.t_group[(post_id +
> 2U)].VDM_T_CFG);
> > + base_addr = HWD_VIIF_L2_VDM_GAMMA_SRAM_BASE +
> > + (HWD_VIIF_L2_VDM_GAMMA_SRAM_SIZE *
> post_id);
> > + writel(base_addr, &res->capture_reg->vdm.t_group[(post_id +
> 2U)].VDM_T_SRAM_BASE);
> > + writel(HWD_VIIF_L2_VDM_GAMMA_SRAM_SIZE,
> > + &res->capture_reg->vdm.t_group[(post_id +
> 2U)].VDM_T_SRAM_SIZE);
> > + vdm_enable = vdm_enable << (12U + (post_id * 6U));
> > + }
> > + vdm_enable |= (readl(&res->capture_reg->vdm.VDM_T_ENABLE) &
> > + ~((u32)0x3fU << (12U + (post_id * 6U))));
> > + writel(vdm_enable, &res->capture_reg->vdm.VDM_T_ENABLE);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_output_csc() - Set output CSC parameters of L2ISP
> > + *
> > + * @post_id: POST ID [0..1]
> > + * @param: Pointer to output csc parameters of L2ISP
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] "post_id" is out of range
> > + * - [2] Member of "param" is invalid
> > + */
> > +s32 hwd_viif_l2_set_output_csc(struct hwd_viif_res *res, u32 post_id,
> > + const struct hwd_viif_csc_param *param)
> > +{
> > + struct hwd_viif_l2isp_post_reg *reg_l2isp_post;
> > + u32 i, val;
> > +
> > + if (post_id >= HWD_VIIF_MAX_POST_NUM)
> > + return -EINVAL;
> > +
> > + /* disable csc matrix when param is NULL */
> > + if (!param) {
> > + writel(HWD_VIIF_DISABLE,
> &res->capture_reg->l2isp.post[post_id].csc.MTB);
> > + return 0;
> > + }
> > +
> > + /* param is specified: go further check */
> > + if (param->r_cr_in_offset > HWD_VIIF_CSC_MAX_OFFSET ||
> > + param->g_y_in_offset > HWD_VIIF_CSC_MAX_OFFSET ||
> > + param->b_cb_in_offset > HWD_VIIF_CSC_MAX_OFFSET ||
> > + param->r_cr_out_offset > HWD_VIIF_CSC_MAX_OFFSET ||
> > + param->g_y_out_offset > HWD_VIIF_CSC_MAX_OFFSET ||
> > + param->b_cb_out_offset > HWD_VIIF_CSC_MAX_OFFSET) {
> > + return -EINVAL;
> > + }
> > +
> > + for (i = 0; i < HWD_VIIF_CSC_MAX_COEF_NUM; i++) {
> > + if (param->coef[i] > HWD_VIIF_CSC_MAX_COEF_VALUE)
> > + return -EINVAL;
> > + }
> > +
> > + reg_l2isp_post = &res->capture_reg->l2isp.post[post_id];
> > +
> > + writel(param->g_y_in_offset,
> &reg_l2isp_post->csc.MTB_YG_OFFSETI);
> > + writel(param->coef[0], &reg_l2isp_post->csc.MTB_YG1);
> > + val = (param->coef[1] << HWD_VIIF_MTB_CB_YG_COEF_OFFSET) |
> > + (param->coef[2] << HWD_VIIF_MTB_CR_YG_COEF_OFFSET);
> > + writel(val, &reg_l2isp_post->csc.MTB_YG2);
> > + writel(param->g_y_out_offset,
> &reg_l2isp_post->csc.MTB_YG_OFFSETO);
> > + writel(param->b_cb_in_offset,
> &reg_l2isp_post->csc.MTB_CB_OFFSETI);
> > + writel(param->coef[3], &reg_l2isp_post->csc.MTB_CB1);
> > + val = (param->coef[4] << HWD_VIIF_MTB_CB_CB_COEF_OFFSET) |
> > + (param->coef[5] << HWD_VIIF_MTB_CR_CB_COEF_OFFSET);
> > + writel(val, &reg_l2isp_post->csc.MTB_CB2);
> > + writel(param->b_cb_out_offset,
> &reg_l2isp_post->csc.MTB_CB_OFFSETO);
> > + writel(param->r_cr_in_offset,
> &reg_l2isp_post->csc.MTB_CR_OFFSETI);
> > + writel(param->coef[6], &reg_l2isp_post->csc.MTB_CR1);
> > + val = (param->coef[7] << HWD_VIIF_MTB_CB_CR_COEF_OFFSET) |
> > + (param->coef[8] << HWD_VIIF_MTB_CR_CR_COEF_OFFSET);
> > + writel(val, &reg_l2isp_post->csc.MTB_CR2);
> > + writel(param->r_cr_out_offset,
> &reg_l2isp_post->csc.MTB_CR_OFFSETO);
> > + writel(HWD_VIIF_ENABLE, &reg_l2isp_post->csc.MTB);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_img_transmission() - Set image transfer condition of
> L2ISP
> > + *
> > + * @post_id: POST ID [0..1]
> > + * @enable: or disable image transfer of MAIN unit. For more refer @ref
> hwd_viif_enable_flag.
> > + * @src: Pointer to crop area information
> > + * @out_process: Pointer to output process information
> > + * @img: Pointer to output image information
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] "post_id" or "enable" is out of range
> > + * - [2] "src" or "out_process" is NULL when "enable" is HWD_VIIF_ENABLE
> > + * - [3] "src" or "out_process" is not NULL when "enable" is
> HWD_VIIF_DISABLE
> > + * - [4] Member of "src" is out of range
> > + * - [5] "w" of "src" is not equal to 2 * "width" of "image"
> > + * when "half_scal" of "out_process" is HWD_VIIF_ENABLE
> > + * - [6] "h" of "src" is not equal to 2 * "height" of "image"
> > + * when "half_scal" of "out_process" is HWD_VIIF_ENABLE
> > + * - [7] "w" of "src" is not equal to "width" of "image"
> > + * when "half_scal" of "out_process" is HWD_VIIF_DISABLE
> > + * - [8] "h" of "src" is not equal to "height" of "image"
> > + * when "half_scal" of "out_process" is HWD_VIIF_DISABLE
> > + * - [9] Member of "out_process" is invalid
> > + * - [10] "alpha" of "out_process" is not 0 when "format" of "img" is not
> HWD_VIIF_ARGB8888_PACKED
> > + * - [11] "format" of "img" is not HWD_VIIF_ONE_COLOR_8 or
> HWD_VIIF_ONE_COLOR_16
> > + * when "select_color" of "out_process"
> > + * is HWD_VIIF_COLOR_Y_G, HWD_VIIF_COLOR_U_B or
> HWD_VIIF_COLOR_V_R
> > + * - [12] Member of "img" is invalid
> > + *
> > + * see also: #hwd_viif_l2_set_roi_path
> > + */
> > +s32 hwd_viif_l2_set_img_transmission(struct hwd_viif_res *res, u32 post_id,
> u32 enable,
> > + const struct hwd_viif_img_area *src,
> > + const struct hwd_viif_out_process
> *out_process,
> > + const struct hwd_viif_img *img)
> > +{
> > + u32 pitch[HWD_VIIF_MAX_PLANE_NUM],
> img_start_addr[HWD_VIIF_MAX_PLANE_NUM];
> > + u32 i, val, loop, k, r[HWD_VIIF_MAX_PLANE_NUM];
> > + s32 ret = 0;
> > +
> > + /* pitch alignment for planar or one color format */
> > + u32 pitch_align = 128U;
> > +
> > + if (post_id >= HWD_VIIF_MAX_POST_NUM ||
> > + (enable != HWD_VIIF_ENABLE && enable != HWD_VIIF_DISABLE)
> ||
> > + (enable == HWD_VIIF_ENABLE && (!src || !out_process)) ||
> > + (enable == HWD_VIIF_DISABLE && (src || out_process))) {
> > + return -EINVAL;
> > + }
> > +
> > + /* DISABLE: no DMA transmission setup, set minimum crop rectangle
> */
> > + if (enable == HWD_VIIF_DISABLE) {
> > + res->l2_roi_path_info.post_enable_flag[post_id] = false;
> > + res->l2_roi_path_info.post_crop_x[post_id] = 0U;
> > + res->l2_roi_path_info.post_crop_y[post_id] = 0U;
> > + res->l2_roi_path_info.post_crop_w[post_id] =
> HWD_VIIF_CROP_MIN_W;
> > + res->l2_roi_path_info.post_crop_h[post_id] =
> HWD_VIIF_CROP_MIN_H;
> > + hwd_viif_l2_set_roi_path(res);
> > +
> > + return 0;
> > + }
> > +
> > + /* further parameter check for ENABLE */
> > + if (out_process->half_scale != HWD_VIIF_ENABLE &&
> > + out_process->half_scale != HWD_VIIF_DISABLE) {
> > + return -EINVAL;
> > + }
> > +
> > + if (out_process->select_color != HWD_VIIF_COLOR_Y_G &&
> > + out_process->select_color != HWD_VIIF_COLOR_U_B &&
> > + out_process->select_color != HWD_VIIF_COLOR_V_R &&
> > + out_process->select_color != HWD_VIIF_COLOR_YUV_RGB) {
> > + return -EINVAL;
> > + }
> > +
> > + if (img->format != HWD_VIIF_ARGB8888_PACKED &&
> out_process->alpha != 0U)
> > + return -EINVAL;
> > +
> > + if (((img->width % 2U) != 0U) || ((img->height % 2U) != 0U) ||
> > + img->width < HWD_VIIF_MIN_OUTPUT_IMG_WIDTH ||
> > + img->height < HWD_VIIF_MIN_OUTPUT_IMG_HEIGHT ||
> > + img->width > HWD_VIIF_MAX_OUTPUT_IMG_WIDTH_ISP ||
> > + img->height > HWD_VIIF_MAX_OUTPUT_IMG_HEIGHT_ISP) {
> > + return -EINVAL;
> > + }
> > +
> > + if (src->x > HWD_VIIF_CROP_MAX_X_ISP || src->y >
> HWD_VIIF_CROP_MAX_Y_ISP ||
> > + src->w < HWD_VIIF_CROP_MIN_W || src->w >
> HWD_VIIF_CROP_MAX_W_ISP ||
> > + src->h < HWD_VIIF_CROP_MIN_H || src->h >
> HWD_VIIF_CROP_MAX_H_ISP) {
> > + return -EINVAL;
> > + }
> > +
> > + if (out_process->half_scale == HWD_VIIF_ENABLE) {
> > + if ((src->w != (img->width * 2U)) || (src->h != (img->height *
> 2U)))
> > + return -EINVAL;
> > + } else {
> > + if (src->w != img->width || src->h != img->height)
> > + return -EINVAL;
> > + }
> > +
> > + if (out_process->select_color == HWD_VIIF_COLOR_Y_G ||
> > + out_process->select_color == HWD_VIIF_COLOR_U_B ||
> > + out_process->select_color == HWD_VIIF_COLOR_V_R) {
> > + if (img->format != HWD_VIIF_ONE_COLOR_8 &&
> img->format != HWD_VIIF_ONE_COLOR_16)
> > + return -EINVAL;
> > + }
> > +
> > + /* build DMAC parameter */
> > + switch (img->format) {
> > + case HWD_VIIF_YCBCR422_8_PACKED:
> > + img_start_addr[0] = (u32)img->pixelmap[0].pmap_paddr;
> > + pitch[0] = img->pixelmap[0].pitch;
> > + loop = 1U;
> > + k = 2U;
> > + r[0] = 1U;
> > + pitch_align = 256U;
> > + break;
> > + case HWD_VIIF_RGB888_PACKED:
> > + img_start_addr[0] = (u32)img->pixelmap[0].pmap_paddr;
> > + pitch[0] = img->pixelmap[0].pitch;
> > + loop = 1U;
> > + k = 3U;
> > + r[0] = 1U;
> > + pitch_align = 384U;
> > + break;
> > + case HWD_VIIF_ARGB8888_PACKED:
> > + img_start_addr[0] = (u32)img->pixelmap[0].pmap_paddr;
> > + pitch[0] = img->pixelmap[0].pitch;
> > + loop = 1U;
> > + k = 4U;
> > + r[0] = 1U;
> > + pitch_align = 512U;
> > + break;
> > + case HWD_VIIF_ONE_COLOR_8:
> > + img_start_addr[0] = (u32)img->pixelmap[0].pmap_paddr;
> > + pitch[0] = img->pixelmap[0].pitch;
> > + loop = 1U;
> > + k = 1U;
> > + r[0] = 1U;
> > + break;
> > + case HWD_VIIF_ONE_COLOR_16:
> > + img_start_addr[0] = (u32)img->pixelmap[0].pmap_paddr;
> > + pitch[0] = img->pixelmap[0].pitch;
> > + loop = 1U;
> > + k = 2U;
> > + r[0] = 1U;
> > + break;
> > + case HWD_VIIF_YCBCR422_8_PLANAR:
> > + img_start_addr[0] = (u32)img->pixelmap[0].pmap_paddr;
> > + img_start_addr[1] = (u32)img->pixelmap[1].pmap_paddr;
> > + img_start_addr[2] = (u32)img->pixelmap[2].pmap_paddr;
> > + pitch[0] = img->pixelmap[0].pitch;
> > + pitch[1] = img->pixelmap[1].pitch;
> > + pitch[2] = img->pixelmap[2].pitch;
> > + loop = HWD_VIIF_MAX_PLANE_NUM;
> > + k = 1U;
> > + r[0] = 1U;
> > + r[1] = 2U;
> > + r[2] = 2U;
> > + break;
> > + case HWD_VIIF_RGB888_YCBCR444_8_PLANAR:
> > + img_start_addr[0] = (u32)img->pixelmap[0].pmap_paddr;
> > + img_start_addr[1] = (u32)img->pixelmap[1].pmap_paddr;
> > + img_start_addr[2] = (u32)img->pixelmap[2].pmap_paddr;
> > + pitch[0] = img->pixelmap[0].pitch;
> > + pitch[1] = img->pixelmap[1].pitch;
> > + pitch[2] = img->pixelmap[2].pitch;
> > + loop = HWD_VIIF_MAX_PLANE_NUM;
> > + k = 1U;
> > + r[0] = 1U;
> > + r[1] = 1U;
> > + r[2] = 1U;
> > + break;
> > + case HWD_VIIF_YCBCR422_16_PLANAR:
> > + img_start_addr[0] = (u32)img->pixelmap[0].pmap_paddr;
> > + img_start_addr[1] = (u32)img->pixelmap[1].pmap_paddr;
> > + img_start_addr[2] = (u32)img->pixelmap[2].pmap_paddr;
> > + pitch[0] = img->pixelmap[0].pitch;
> > + pitch[1] = img->pixelmap[1].pitch;
> > + pitch[2] = img->pixelmap[2].pitch;
> > + loop = HWD_VIIF_MAX_PLANE_NUM;
> > + k = 2U;
> > + r[0] = 1U;
> > + r[1] = 2U;
> > + r[2] = 2U;
> > + break;
> > + case HWD_VIIF_RGB161616_YCBCR444_16_PLANAR:
> > + img_start_addr[0] = (u32)img->pixelmap[0].pmap_paddr;
> > + img_start_addr[1] = (u32)img->pixelmap[1].pmap_paddr;
> > + img_start_addr[2] = (u32)img->pixelmap[2].pmap_paddr;
> > + pitch[0] = img->pixelmap[0].pitch;
> > + pitch[1] = img->pixelmap[1].pitch;
> > + pitch[2] = img->pixelmap[2].pitch;
> > + loop = HWD_VIIF_MAX_PLANE_NUM;
> > + k = 2U;
> > + r[0] = 1U;
> > + r[1] = 1U;
> > + r[2] = 1U;
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> > +
> > + for (i = 0; i < loop; i++) {
> > + val = max(((img->width * k) / r[i]), 128U);
> > + if (pitch[i] < val || pitch[i] > HWD_VIIF_MAX_PITCH_ISP ||
> > + ((pitch[i] % pitch_align) != 0U) || ((img_start_addr[i] %
> 4U) != 0U)) {
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + writel(img_start_addr[0],
> &res->capture_reg->l2isp.post[post_id].L2_POST_OUT_STADR_G);
> > + writel(pitch[0],
> &res->capture_reg->l2isp.post[post_id].L2_POST_OUT_PITCH_G);
> > + if (loop == HWD_VIIF_MAX_PLANE_NUM) {
> > + writel(img_start_addr[1],
> > +
> &res->capture_reg->l2isp.post[post_id].L2_POST_OUT_STADR_B);
> > + writel(img_start_addr[2],
> > +
> &res->capture_reg->l2isp.post[post_id].L2_POST_OUT_STADR_R);
> > + writel(pitch[1],
> &res->capture_reg->l2isp.post[post_id].L2_POST_OUT_PITCH_B);
> > + writel(pitch[2],
> &res->capture_reg->l2isp.post[post_id].L2_POST_OUT_PITCH_R);
> > + }
> > +
> > + /* Set CROP */
> > + val = (src->y << 16U) | src->x;
> > + writel(val,
> &res->capture_reg->l2isp.post[post_id].L2_POST_CAP_OFFSET);
> > + val = (src->h << 16U) | src->w;
> > + writel(val,
> &res->capture_reg->l2isp.post[post_id].L2_POST_CAP_SIZE);
> > +
> > + /* Set output process */
> > + writel(out_process->half_scale,
> > +
> &res->capture_reg->l2isp.post[post_id].L2_POST_HALF_SCALE_EN);
> > + writel(out_process->select_color,
> &res->capture_reg->l2isp.post[post_id].L2_POST_C_SELECT);
> > + writel((u32)out_process->alpha,
> &res->capture_reg->l2isp.post[post_id].L2_POST_OPORTALP);
> > + writel(img->format,
> &res->capture_reg->l2isp.post[post_id].L2_POST_OPORTFMT);
> > +
> > + /* Update ROI area and input to each POST */
> > + res->l2_roi_path_info.post_enable_flag[post_id] = true;
> > + res->l2_roi_path_info.post_crop_x[post_id] = src->x;
> > + res->l2_roi_path_info.post_crop_y[post_id] = src->y;
> > + res->l2_roi_path_info.post_crop_w[post_id] = src->w;
> > + res->l2_roi_path_info.post_crop_h[post_id] = src->h;
> > + hwd_viif_l2_set_roi_path(res);
> > +
> > + return ret;
> > +}
> > +
> > +/**
> > + * hwd_viif_l2_set_irq_mask() - Set mask condition for L2ISP
> > + *
> > + * @mask: L2ISP mask condition
> > + * Return: None
> > + */
> > +void hwd_viif_l2_set_irq_mask(struct hwd_viif_res *res, u32 mask)
> > +{
> > + writel(mask, &res->capture_reg->l2isp.L2_CRGBF_ISP_INT_MASK);
> > +}
> > +
> > +/**
> > + * hwd_viif_csi2rx_err_irq_handler() - CSI-2 RX error interruption handler
> > + *
> > + * Return: event information of CSI-2 RX error interruption
> > + */
> > +u32 hwd_viif_csi2rx_err_irq_handler(struct hwd_viif_res *res)
> > +{
> > + return readl(&res->csi2host_reg->CSI2RX_INT_ST_MAIN);
> > +}
> > +
> > +/**
> > + * hwd_viif_status_err_irq_handler() - STATUS error interruption handler
> > + *
> > + * @event_main: information of STATUS error interruption of MAIN unit
> > + * @event_sub: information of STATUS error interruption of SUB unit(CH0
> and CH1)
> > + * Return: None
> > + */
> > +void hwd_viif_status_err_irq_handler(struct hwd_viif_res *res, u32
> *event_main, u32 *event_sub)
> > +{
> > + u32 val, mask;
> > +
> > + *event_main = HWD_VIIF_NO_EVENT;
> > + *event_sub = HWD_VIIF_NO_EVENT;
> > +
> > + val = readl(&res->capture_reg->sys.INT_M_STATUS);
> > + mask = readl(&res->capture_reg->sys.INT_M_MASK);
> > + val = val & ~mask;
> > + if (val != HWD_VIIF_NO_EVENT) {
> > + writel(val, &res->capture_reg->sys.INT_M_STATUS);
> > + *event_main = val;
> > + }
> > +
> > + val = readl(&res->capture_reg->sys.INT_S_STATUS);
> > + mask = readl(&res->capture_reg->sys.INT_S_MASK);
> > + val = val & ~mask;
> > + if (val != HWD_VIIF_NO_EVENT) {
> > + writel(val, &res->capture_reg->sys.INT_S_STATUS);
> > + *event_sub = val;
> > + }
> > +}
> > +
> > +/**
> > + * hwd_viif_vsync_irq_handler() - Vsync interruption handler
> > + *
> > + * @event_main: information of Vsync interruption of MAIN unit
> > + * @event_sub: information of Vsync interruption of SUB unit(CH0 and CH1)
> > + * Return: None
> > + */
> > +void hwd_viif_vsync_irq_handler(struct hwd_viif_res *res, u32 *event_main,
> u32 *event_sub)
> > +{
> > + u32 val, mask;
> > +
> > + *event_main = HWD_VIIF_NO_EVENT;
> > + *event_sub = HWD_VIIF_NO_EVENT;
> > +
> > + val = readl(&res->capture_reg->sys.INT_M_SYNC);
> > + mask = readl(&res->capture_reg->sys.INT_M_SYNC_MASK);
> > + val = val & ~mask;
> > + if (val != HWD_VIIF_NO_EVENT) {
> > + writel(val, &res->capture_reg->sys.INT_M_SYNC);
> > + *event_main = val;
> > + }
> > +
> > + val = readl(&res->capture_reg->sys.INT_S_SYNC);
> > + mask = readl(&res->capture_reg->sys.INT_S_SYNC_MASK);
> > + val = val & ~mask;
> > + if (val != HWD_VIIF_NO_EVENT) {
> > + writel(val, &res->capture_reg->sys.INT_S_SYNC);
> > + *event_sub = val;
> > + }
> > +}
> > +
> > +/**
> > + * hwd_viif_isp_regbuf_irq_handler() - ISP register buffer interruption
> handler
> > + *
> > + * @event_l1: information of register buffer interruption of L1ISP
> > + * @event_l2: information of register buffer interruption of L2ISP
> > + * Return: None
> > + */
> > +void hwd_viif_isp_regbuf_irq_handler(struct hwd_viif_res *res, u32 *event_l1,
> u32 *event_l2)
> > +{
> > + u32 val;
> > +
> > + *event_l1 = HWD_VIIF_NO_EVENT;
> > + *event_l2 = HWD_VIIF_NO_EVENT;
> > +
> > + val =
> readl(&res->capture_reg->l1isp.L1_CRGBF_INT_MASKED_STAT);
> > + if (val != HWD_VIIF_NO_EVENT) {
> > + *event_l1 = val;
> > + writel(val, &res->capture_reg->l1isp.L1_CRGBF_INT_STAT);
> > + }
> > +
> > + val =
> readl(&res->capture_reg->l2isp.L2_CRGBF_INT_MASKED_STAT);
> > + if (val != HWD_VIIF_NO_EVENT) {
> > + *event_l2 = val;
> > + writel(val, &res->capture_reg->l2isp.L2_CRGBF_INT_STAT);
> > + }
> > +}
> > diff --git a/drivers/media/platform/visconti/hwd_viif.h
> b/drivers/media/platform/visconti/hwd_viif.h
> > new file mode 100644
> > index 00000000000..100afda8436
> > --- /dev/null
> > +++ b/drivers/media/platform/visconti/hwd_viif.h
> > @@ -0,0 +1,710 @@
> > +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
> > +/* Toshiba Visconti Video Capture Support
> > + *
> > + * (C) Copyright 2022 TOSHIBA CORPORATION
> > + * (C) Copyright 2022 Toshiba Electronic Devices & Storage Corporation
> > + */
> > +
> > +#ifndef HWD_VIIF_H
> > +#define HWD_VIIF_H
> > +
> > +#include <linux/errno.h>
> > +#include <linux/types.h>
> > +
> > +#include <linux/visconti_viif.h>
> > +
> > +enum hwd_power_ctrl {
> > + HWD_POWER_OFF = 0, /**< Power off */
> > + HWD_POWER_ON /**< Power on */
> > +};
> > +
> > +/* MIPI CSI2 Data Types */
> > +#define VISCONTI_CSI2_DT_YUV4228B 0x1E
> > +#define VISCONTI_CSI2_DT_YUV42210B 0x1F
> > +#define VISCONTI_CSI2_DT_RGB565 0x22
> > +#define VISCONTI_CSI2_DT_RGB888 0x24
> > +#define VISCONTI_CSI2_DT_RAW8 0x2A
> > +#define VISCONTI_CSI2_DT_RAW10 0x2B
> > +#define VISCONTI_CSI2_DT_RAW12 0x2C
> > +#define VISCONTI_CSI2_DT_RAW14 0x2D
>
> Please use the definitions in media/mipi-csi2.h .

I'll use definitions in mipi-csi2.h .

> > +
> > +/* hwd_viif_enable_flag */
> > +#define HWD_VIIF_DISABLE (0U)
> > +#define HWD_VIIF_ENABLE (1U)
> > +
> > +/* hwd_viif_memory_sync_type */
> > +#define HWD_VIIF_MEM_SYNC_INTERNAL (0U)
> > +#define HWD_VIIF_MEM_SYNC_CSI2 (1U)
> > +
> > +/* hwd_viif_color_format */
> > +#define HWD_VIIF_YCBCR422_8_PACKED (0U)
> > +#define HWD_VIIF_RGB888_PACKED (1U)
> > +#define HWD_VIIF_ARGB8888_PACKED (3U)
> > +#define HWD_VIIF_YCBCR422_8_PLANAR (8U)
> > +#define HWD_VIIF_RGB888_YCBCR444_8_PLANAR (9U)
> > +#define HWD_VIIF_ONE_COLOR_8 (11U)
> > +#define HWD_VIIF_YCBCR422_16_PLANAR (12U)
> > +#define HWD_VIIF_RGB161616_YCBCR444_16_PLANAR (13U)
> > +#define HWD_VIIF_ONE_COLOR_16 (15U)
> > +
> > +/* hwd_viif_raw_pack_mode */
> > +#define HWD_VIIF_RAWPACK_DISABLE (0U)
> > +#define HWD_VIIF_RAWPACK_MSBFIRST (2U)
> > +#define HWD_VIIF_RAWPACK_LSBFIRST (3U)
> > +
> > +/* hwd_viif_yuv_conversion_mode */
> > +#define HWD_VIIF_YUV_CONV_REPEAT (0U)
> > +#define HWD_VIIF_YUV_CONV_INTERPOLATION (1U)
> > +
> > +/* hwd_viif_gamma_table_mode */
> > +#define HWD_VIIF_GAMMA_COMPRESSED (0U)
> > +#define HWD_VIIF_GAMMA_LINEAR (1U)
> > +
> > +/* hwd_viif_output_color_mode */
> > +#define HWD_VIIF_COLOR_Y_G (0U)
> > +#define HWD_VIIF_COLOR_U_B (1U)
> > +#define HWD_VIIF_COLOR_V_R (2U)
> > +#define HWD_VIIF_COLOR_YUV_RGB (4U)
> > +
> > +/* hwd_viif_hw_params */
> > +#define HWD_VIIF_MAX_CH (6U)
> > +#define HWD_VIIF_MAX_PLANE_NUM (3U)
> > +
> > +/**
> > + * enum hwd_viif_csi2_dphy - D-PHY Lane assignment
> > + *
> > + * specifies which line(L0-L3) is assigned to D0-D3
> > + */
> > +enum hwd_viif_csi2_dphy {
> > + HWD_VIIF_CSI2_DPHY_L0L1L2L3 = 0U,
> > + HWD_VIIF_CSI2_DPHY_L0L3L1L2 = 1U,
> > + HWD_VIIF_CSI2_DPHY_L0L2L3L1 = 2U,
> > + HWD_VIIF_CSI2_DPHY_L0L1L3L2 = 4U,
> > + HWD_VIIF_CSI2_DPHY_L0L3L2L1 = 5U,
> > + HWD_VIIF_CSI2_DPHY_L0L2L1L3 = 6U
> > +};
> > +
> > +/* hwd_viif_csi2rx_cal_status */
> > +#define HWD_VIIF_CSI2_CAL_NOT_DONE (0U)
> > +#define HWD_VIIF_CSI2_CAL_SUCCESS (1U)
> > +#define HWD_VIIF_CSI2_CAL_FAIL (2U)
> > +
> > +/* hwd_viif_csi2rx_not_capture */
> > +#define HWD_VIIF_CSI2_NOT_CAPTURE (-1) /**< csi2 not capture */
> > +
> > +/* hwd_viif_l1_input_mode */
> > +#define HWD_VIIF_L1_INPUT_HDR (0U)
> > +#define HWD_VIIF_L1_INPUT_PWL (1U)
> > +#define HWD_VIIF_L1_INPUT_SDR (2U)
> > +#define HWD_VIIF_L1_INPUT_HDR_IMG_CORRECT (3U)
> > +#define HWD_VIIF_L1_INPUT_PWL_IMG_CORRECT (4U)
> > +
> > +/* hwd_viif_l1_raw_color_filter_mode */
> > +#define HWD_VIIF_L1_RAW_GR_R_B_GB (0U)
> > +#define HWD_VIIF_L1_RAW_R_GR_GB_B (1U)
> > +#define HWD_VIIF_L1_RAW_B_GB_GR_R (2U)
> > +#define HWD_VIIF_L1_RAW_GB_B_R_GR (3U)
> > +
> > +/* hwd_viif_l1_input_interpolation_mode */
> > +#define HWD_VIIF_L1_INPUT_INTERPOLATION_LINE (0U)
> > +#define HWD_VIIF_L1_INPUT_INTERPOLATION_PIXEL (1U)
> > +
> > +/* hwd_viif_l1_img_sens */
> > +#define HWD_VIIF_L1_IMG_SENSITIVITY_HIGH (0U)
> > +#define HWD_VIIF_L1_IMG_SENSITIVITY_MIDDLE_LED (1U)
> > +#define HWD_VIIF_L1_IMG_SENSITIVITY_LOW (2U)
> > +
> > +/* hwd_viif_l1_dpc */
> > +#define HWD_VIIF_L1_DPC_1PIXEL (0U)
> > +#define HWD_VIIF_L1_DPC_2PIXEL (1U)
> > +
> > +/* hwd_viif_l1_rcnr_hry_type */
> > +#define HWD_VIIF_L1_RCNR_LOW_RESOLUTION (0U)
> > +#define HWD_VIIF_L1_RCNR_MIDDLE_RESOLUTION (1U)
> > +#define HWD_VIIF_L1_RCNR_HIGH_RESOLUTION (2U)
> > +#define HWD_VIIF_L1_RCNR_ULTRA_HIGH_RESOLUTION (3U)
> > +
> > +/* hwd_viif_l1_rcnr_msf_blend_ratio */
> > +#define HWD_VIIF_L1_MSF_BLEND_RATIO_0_DIV_64 (0U)
> > +#define HWD_VIIF_L1_MSF_BLEND_RATIO_1_DIV_64 (1U)
> > +#define HWD_VIIF_L1_MSF_BLEND_RATIO_2_DIV_64 (2U)
> > +
> > +/* hwd_viif_l1_hdrs */
> > +#define HWD_VIIF_L1_HDRS_NOT_USE_MIDDLE_SENS_IMAGE (0U)
> > +#define HWD_VIIF_L1_HDRS_USE_MIDDLE_SENS_IMAGE (1U)
> > +
> > +/* hwd_viif_l1_lsc_para_mag */
> > +#define HWD_VIIF_L1_PARA_COEF_GAIN_ONE_EIGHTH (0U)
> > +#define HWD_VIIF_L1_PARA_COEF_GAIN_ONE_FOURTH (1U)
> > +#define HWD_VIIF_L1_PARA_COEF_GAIN_ONE_SECOND (2U)
> > +#define HWD_VIIF_L1_PARA_COEF_GAIN_ONE_FIRST (3U)
> > +
> > +/* hwd_viif_l1_lsc_grid_mag */
> > +#define HWD_VIIF_L1_GRID_COEF_GAIN_X1 (0U)
> > +#define HWD_VIIF_L1_GRID_COEF_GAIN_X2 (1U)
> > +
> > +/* hwd_viif_l1_demosaic */
> > +#define HWD_VIIF_L1_DEMOSAIC_ACPI (0U)
> > +#define HWD_VIIF_L1_DEMOSAIC_DMG (1U)
> > +
> > +/* hwd_viif_l1_awb_restart_cond */
> > +/* macros for L1ISP condition to restart auto white balance */
> > +#define HWD_VIIF_L1_AWB_RESTART_NO (0U)
> > +#define HWD_VIIF_L1_AWB_RESTART_128FRAME (1U)
> > +#define HWD_VIIF_L1_AWB_RESTART_64FRAME (2U)
> > +#define HWD_VIIF_L1_AWB_RESTART_32FRAME (3U)
> > +#define HWD_VIIF_L1_AWB_RESTART_16FRAME (4U)
> > +#define HWD_VIIF_L1_AWB_RESTART_8FRAME (5U)
> > +#define HWD_VIIF_L1_AWB_RESTART_4FRAME (6U)
> > +#define HWD_VIIF_L1_AWB_RESTART_2FRAME (7U)
> > +
> > +/* hwd_viif_l1_awb_mag */
> > +#define HWD_VIIF_L1_AWB_ONE_SECOND (0U)
> > +#define HWD_VIIF_L1_AWB_X1 (1U)
> > +#define HWD_VIIF_L1_AWB_X2 (2U)
> > +#define HWD_VIIF_L1_AWB_X4 (3U)
> > +
> > +/* hwd_viif_l1_awb_area_mode */
> > +#define HWD_VIIF_L1_AWB_AREA_MODE0 (0U)
> > +#define HWD_VIIF_L1_AWB_AREA_MODE1 (1U)
> > +#define HWD_VIIF_L1_AWB_AREA_MODE2 (2U)
> > +#define HWD_VIIF_L1_AWB_AREA_MODE3 (3U)
> > +
> > +/* hwd_viif_l1_hdrc_tone_type */
> > +#define HWD_VIIF_L1_HDRC_TONE_USER (0U)
> > +#define HWD_VIIF_L1_HDRC_TONE_PRESET (1U)
> > +
> > +/* hwd_viif_l1_bin_mode */
> > +#define HWD_VIIF_L1_HIST_BIN_MODE_LINEAR (0U)
> > +#define HWD_VIIF_L1_HIST_BIN_MODE_LOG (1U)
> > +
> > +/* hwd_viif_l2_undist_mode */
> > +#define HWD_VIIF_L2_UNDIST_POLY (0U)
> > +#define HWD_VIIF_L2_UNDIST_GRID (1U)
> > +#define HWD_VIIF_L2_UNDIST_POLY_TO_GRID (2U)
> > +#define HWD_VIIF_L2_UNDIST_GRID_TO_POLY (3U)
> > +
> > +/**
> > + * struct hwd_viif_csi2rx_line_err_target
> > + *
> > + * Virtual Channel and Data Type pair for CSI2RX line error monitor
> > + *
> > + * When 0 is set to dt, line error detection is disabled.
> > + *
> > + * * VC can be 0 .. 3
> > + * * DT can be 0 or 0x10 .. 0x3F
> > + */
> > +#define VISCONTI_CSI2_ERROR_MONITORS_NUM 8
> > +struct hwd_viif_csi2rx_line_err_target {
> > + u32 vc[VISCONTI_CSI2_ERROR_MONITORS_NUM];
> > + u32 dt[VISCONTI_CSI2_ERROR_MONITORS_NUM];
> > +};
> > +
> > +/**
> > + * struct hwd_viif_csi2rx_irq_mask
> > + * @mask: mask setting for CSI2RX error interruption
> > + *
> > + * * mask[0]: D-PHY fatal error
> > + * * mask[1]: Packet fatal error
> > + * * mask[2]: Frame fatal error
> > + * * mask[3]: D-PHY error
> > + * * mask[4]: Packet error
> > + * * mask[5]: Line error
> > + */
> > +#define VISCONTI_CSI2RX_IRQ_MASKS_NUM 6
> > +#define VISCONTI_CSI2RX_IRQ_MASK_DPHY_FATAL 0
> > +#define VISCONTI_CSI2RX_IRQ_MASK_PACKET_FATAL 1
> > +#define VISCONTI_CSI2RX_IRQ_MASK_FRAME_FATAL 2
> > +#define VISCONTI_CSI2RX_IRQ_MASK_DPHY_ERROR 3
> > +#define VISCONTI_CSI2RX_IRQ_MASK_PACKET_ERROR 4
> > +#define VISCONTI_CSI2RX_IRQ_MASK_LINE_ERROR 5
> > +struct hwd_viif_csi2rx_irq_mask {
> > + u32 mask[VISCONTI_CSI2RX_IRQ_MASKS_NUM];
> > +};
> > +
> > +/**
> > + * struct hwd_viif_csi2rx_packet - CSI2 packet information
> > + * @word_count: word count included in one packet[byte] [0..16384]
> > + * @packet_num: the number of packet included in one packet [0..8192]
> > + *
> > + * each element means as below.
> > + * * [0]: embedded data of MAIN unit
> > + * * [1]: long packet data of MAIN unit
> > + * * [2]: embedded data of SUB unit
> > + * * [3]: long packet data of SUB unit
> > + *
> > + * Regarding word_count of long packet data,
> > + * word count of odd line needs to be set in case of DT = 0x18, 0x19, 0x1C or
> 0x1D.
> > + */
> > +#define VISCONTI_CSI2RX_PACKET_TYPES_NUM 4
> > +#define VISCONTI_CSI2RX_PACKET_TYPE_EMB_MAIN 0
> > +#define VISCONTI_CSI2RX_PACKET_TYPE_LONG_MAIN 1
> > +#define VISCONTI_CSI2RX_PACKET_TYPE_EMB_SUB 2
> > +#define VISCONTI_CSI2RX_PACKET_TYPE_LONG_SUB 3
> > +struct hwd_viif_csi2rx_packet {
> > + u32 word_count[VISCONTI_CSI2RX_PACKET_TYPES_NUM];
> > + u32 packet_num[VISCONTI_CSI2RX_PACKET_TYPES_NUM];
> > +};
> > +
> > +/**
> > + * struct hwd_viif_pixelmap - pixelmap information
> > + * @pmap_paddr: start address of pixel data(physical address). 4byte
> alignment.
> > + * @pitch: pitch size of pixel map[byte]
> > + *
> > + * Condition of pitch in case of L2ISP output is as below.
> > + * * max: 32704[byte]
> > + * * min: the larger value of (active width of image * k / r) and 128[byte]
> > + * * alignment: 64[byte]
> > + *
> > + * Condition of pitch in the other cases is as below.
> > + * * max: 65536[byte]
> > + * * min: active width of image * k / r[byte]
> > + * * alignment: 4[byte]
> > + *
> > + * k is the size of 1 pixel and the value is as below.
> > + * * HWD_VIIF_YCBCR422_8_PACKED: 2
> > + * * HWD_VIIF_RGB888_PACKED: 3
> > + * * HWD_VIIF_ARGB8888_PACKED: 4
> > + * * HWD_VIIF_YCBCR422_8_PLANAR: 1
> > + * * HWD_VIIF_RGB888_YCBCR444_8_PLANAR: 1
> > + * * HWD_VIIF_ONE_COLOR_8: 1
> > + * * HWD_VIIF_YCBCR422_16_PLANAR: 2
> > + * * HWD_VIIF_RGB161616_YCBCR444_16_PLANAR: 2
> > + * * HWD_VIIF_ONE_COLOR_16: 2
> > + *
> > + * r is the correction factor for Cb or Cr of YCbCr422 planar and the value is
> as below.
> > + * * YCbCr422 Cb-planar: 2
> > + * * YCbCr422 Cr-planar: 2
> > + * * others: 1
> > + *
> > + */
> > +struct hwd_viif_pixelmap {
> > + uintptr_t pmap_paddr;
> > + u32 pitch;
> > +};
> > +
> > +/**
> > + * struct hwd_viif_img - image information
> > + * @width: active width of image[pixel]
> > + * * [128..5760](output from L2ISP)
> > + * * [128..4096](input to MAIN unit(memory input))
> > + * * [128..4096](output from SUB unit)
> > + * * The value should be even.
> > + *
> > + * @height: active height of image[line]
> > + * * [128..3240](output from L2ISP)
> > + * * [128..2160](input to MAIN unit(memory input))
> > + * * [128..2160](output from SUB unit)
> > + * * The value should be even.
> > + *
> > + * @format: hwd_viif_color_format "color format"
> > + * * Below color formats are supported for input and output of MAIN unit
> > + * * HWD_VIIF_YCBCR422_8_PACKED
> > + * * HWD_VIIF_RGB888_PACKED
> > + * * HWD_VIIF_ARGB8888_PACKED
> > + * * HWD_VIIF_YCBCR422_8_PLANAR
> > + * * HWD_VIIF_RGB888_YCBCR444_8_PLANAR
> > + * * HWD_VIIF_ONE_COLOR_8
> > + * * HWD_VIIF_YCBCR422_16_PLANAR
> > + * * HWD_VIIF_RGB161616_YCBCR444_16_PLANAR
> > + * * HWD_VIIF_ONE_COLOR_16
> > + * * Below color formats are supported for output of SUB unit
> > + * * HWD_VIIF_ONE_COLOR_8
> > + * * HWD_VIIF_ONE_COLOR_16
> > + *
> > + * @pixelmap: pixelmap information
> > + * * [0]: Y/G-planar, packed/Y/RAW
> > + * * [1]: Cb/B-planar
> > + * * [2]: Cr/R-planar
> > + */
> > +struct hwd_viif_img {
> > + u32 width;
> > + u32 height;
> > + u32 format;
> > + struct hwd_viif_pixelmap pixelmap[3];
> > +};
> > +
> > +/**
> > + * struct hwd_viif_input_img - input image information
> > + * @pixel_clock: pixel clock [3375..600000] [kHz]. 0 needs to be set for long
> packet data.
> > + * @htotal_size: horizontal total size
> > + * * [143..65535] [pixel] for image data
> > + * * [239..109225] [ns] for long packet data
> > + * @hactive_size: horizontal active size [pixel]
> > + * * [128..4096] without L1ISP
> > + * * [640..3840] with L1ISP
> > + * * The value should be even. In addition, the value should be a multiple of 8
> with L1ISP
> > + * * 0 needs to be set for the configuration of long packet data or SUB unit
> output.
> > + * @vtotal_size: vertical total size [line]
> > + * * [144..16383] for image data
> > + * * 0 needs to be set for the configuration of long packet data.
> > + * @vbp_size: vertical back porch size
> > + * * [5..4095] [line] for image data
> > + * * [5..4095] [the number of packet] for long packet data
> > + * @vactive_size: vertical active size [line]
> > + * * [128..2160] without L1ISP
> > + * * [480..2160] with L1ISP
> > + * * The value should be even.
> > + * * 0 needs to be set for the configuration of long packet data.
> > + * @interpolation_mode: input image interpolation mode for
> hwd_viif_l1_input_interpolation_mode
> > + * * HWD_VIIF_L1_INPUT_INTERPOLATION_LINE needs to be set in the
> below cases.
> > + * * image data(without L1ISP) or long packet data
> > + * * image data or long packet data of SUB unit
> > + * @input_num: the number of input images [1..3]
> > + * * 1 needs to be set in the below cases.
> > + * * image data(without L1ISP) or long packet data
> > + * * image data or long packet data of SUB unit
> > + * @hobc_width: the number of horizontal optical black pixels [0,16,32,64 or
> 128]
> > + * * 0 needs to be set in the below cases.
> > + * * in case of hobc_margin = 0
> > + * * image data(without L1ISP) or long packet data
> > + * * image data or long packet data of SUB unit
> > + * @hobc_margin: the number of horizontal optical black margin[0..30] (even
> number)
> > + * * 0 needs to be set in the below cases.
> > + * * in case of hobc_width = 0
> > + * * image data(without L1ISP) or long packet data
> > + * * image data or long packet data of SUB unit
> > + *
> > + * Below conditions need to be satisfied.
> > + * * interpolation_mode is HWD_VIIF_L1_INPUT_INTERPOLATION_LINE:
> > + * (htotal_size > (hactive_size + hobc_width + hobc_margin)) &&
> > + * (vtotal_size > (vbp_size + vactive_size * input_num))
> > + * * interpolation_mode is HWD_VIIF_L1_INPUT_INTERPOLATION_PIXEL:
> > + * (htotal_size > ((hactive_size + hobc_width + hobc_margin) *
> input_num)) &&
> > + * (vtotal_size > (vbp_size + vactive_size))
> > + * * L1ISP is used:
> > + * vbp_size >= (54720[cycle] / 500000[kHz]) * (pixel_clock / htotal_size)
> + 38 + ISST time
> > + * * L1ISP is not used:
> > + * vbp_size >= (39360[cycle] / 500000[kHz]) * (pixel_clock / htotal_size)
> + 16 + ISST time
> > + *
> > + * Note: L1ISP is used when RAW data is input to MAIN unit
> > + */
> > +struct hwd_viif_input_img {
> > + u32 pixel_clock;
> > + u32 htotal_size;
> > + u32 hactive_size;
> > + u32 vtotal_size;
> > + u32 vbp_size;
> > + u32 vactive_size;
> > + u32 interpolation_mode;
> > + u32 input_num;
> > + u32 hobc_width;
> > + u32 hobc_margin;
> > +};
> > +
> > +/**
> > + * struct hwd_viif_csc_param - color conversion information
> > + * @r_cr_in_offset: input offset of R/Cr[pix value] [0x0..0x1FFFF]
> > + * @g_y_in_offset: input offset of G/Y[pix value] [0x0..0x1FFFF]
> > + * @b_cb_in_offset: input offset of B/Cb[pix value] [0x0..0x1FFFF]
> > + * @coef: coefficient of matrix [0x0..0xFFFF]
> > + * * [0] : c00(YG_YG), [1] : c01(UB_YG), [2] : c02(VR_YG),
> > + * * [3] : c10(YG_UB), [4] : c11(UB_UB), [5] : c12(VR_UB),
> > + * * [6] : c20(YG_VR), [7] : c21(UB_VR), [8] : c22(VR_VR)
> > + * @r_cr_out_offset: output offset of R/Cr[pix value] [0x0..0x1FFFF]
> > + * @g_y_out_offset: output offset of G/Y[pix value] [0x0..0x1FFFF]
> > + * @b_cb_out_offset: output offset of B/Cb[pix value] [0x0..0x1FFFF]
> > + */
> > +struct hwd_viif_csc_param {
> > + u32 r_cr_in_offset;
> > + u32 g_y_in_offset;
> > + u32 b_cb_in_offset;
> > + u32 coef[9];
> > + u32 r_cr_out_offset;
> > + u32 g_y_out_offset;
> > + u32 b_cb_out_offset;
> > +};
> > +
> > +/**
> > + * struct hwd_viif_img_area - image area definition
> > + * @x: x position [0..8062] [pixel]
> > + * @y: y position [0..3966] [line]
> > + * @w: image width [128..8190] [pixel]
> > + * @h: image height [128..4094] [line]
> > + */
> > +struct hwd_viif_img_area {
> > + u32 x;
> > + u32 y;
> > + u32 w;
> > + u32 h;
> > +};
> > +
> > +/**
> > + * struct hwd_viif_out_process - configuration of output process of MAIN unit
> and L2ISP
> > + * @half_scale: hwd_viif_enable_flag "enable or disable half scale"
> > + * @select_color: hwd_viif_output_color_mode "select output color"
> > + * @alpha: alpha value used in case of ARGB8888 output [0..255]
> > + */
> > +struct hwd_viif_out_process {
> > + u32 half_scale;
> > + u32 select_color;
> > + u8 alpha;
> > +};
> > +
> > +/**
> > + * struct hwd_viif_l1_lsc - HWD L1ISP lens shading correction parameters
> > + * @lssc_parabola_param: parabola shading correction parameter
> > + * * NULL: disable parabola shading correction
> > + * * not NULL: enable parabola shading correction
> > + * @lssc_grid_param: grid shading correction parameter
> > + * * NULL: disable grid shading correction
> > + * * not NULL: enable grid shading correction
> > + * @lssc_pwhb_r_gain_max: maximum R gain of preset white balance
> correction
> > + * @lssc_pwhb_r_gain_min: minimum R gain of preset white balance
> correction
> > + * @lssc_pwhb_gr_gain_max: maximum Gr gain of preset white balance
> correction
> > + * @lssc_pwhb_gr_gain_min: minimum Gr gain of preset white balance
> correction
> > + * @lssc_pwhb_gb_gain_max: maximum Gb gain of preset white balance
> correction
> > + * @lssc_pwhb_gb_gain_min: minimum Gb gain of preset white balance
> correction
> > + * @lssc_pwhb_b_gain_max: maximum B gain of preset white balance
> correction
> > + * @lssc_pwhb_b_gain_min: minimum B gain of preset white balance
> correction
> > + *
> > + * Range and accuracy of lssc_pwhb_xxx_gain_xxx are as below.
> > + * - range: [0x0..0x7FF]
> > + * - accuracy : 1/256
> > + */
> > +struct hwd_viif_l1_lsc {
> > + struct viif_l1_lsc_parabola_param *lssc_parabola_param;
> > + struct viif_l1_lsc_grid_param *lssc_grid_param;
> > + u32 lssc_pwhb_r_gain_max;
> > + u32 lssc_pwhb_r_gain_min;
> > + u32 lssc_pwhb_gr_gain_max;
> > + u32 lssc_pwhb_gr_gain_min;
> > + u32 lssc_pwhb_gb_gain_max;
> > + u32 lssc_pwhb_gb_gain_min;
> > + u32 lssc_pwhb_b_gain_max;
> > + u32 lssc_pwhb_b_gain_min;
> > +};
> > +
> > +/**
> > + * struct hwd_viif_l1_img_quality_adjustment - HWD L1ISP image quality
> adjustment parameters
> > + * @coef_cb: Cb coefficient [0x0..0xffff] accuracy: 1/65536
> > + * @coef_cr: Cr coefficient [0x0..0xffff] accuracy: 1/65536
> > + * @brightness: brightness value [-32768..32767] (0 means off.)
> > + * @linear_contrast: linear contrast value [0x0..0xff] accuracy: 1/128 (128
> means off.)
> > + * @*nonlinear_contrast: pointer to nonlinear contrast parameter
> > + * @*lum_noise_reduction: pointer to luminance noise reduction parameter
> > + * @*edge_enhancement: pointer to edge enhancement parameter
> > + * @*uv_suppression: pointer to UV suppression parameter
> > + * @*coring_suppression: pointer to coring suppression parameter
> > + * @*edge_suppression: pointer to edge enhancement parameter
> > + * @*color_level: pointer to color level adjustment parameter
> > + * @color_noise_reduction_enable: enable/disable color noise reduction @ref
> hwd_viif_enable_flag
> > + */
> > +struct hwd_viif_l1_img_quality_adjustment {
> > + u16 coef_cb;
> > + u16 coef_cr;
> > + s16 brightness;
> > + u8 linear_contrast;
> > + struct viif_l1_nonlinear_contrast *nonlinear_contrast;
> > + struct viif_l1_lum_noise_reduction *lum_noise_reduction;
> > + struct viif_l1_edge_enhancement *edge_enhancement;
> > + struct viif_l1_uv_suppression *uv_suppression;
> > + struct viif_l1_coring_suppression *coring_suppression;
> > + struct viif_l1_edge_suppression *edge_suppression;
> > + struct viif_l1_color_level *color_level;
> > + u32 color_noise_reduction_enable;
> > +};
> > +
> > +/**
> > + * struct hwd_viif_l1_info - HWD L1ISP processing information
> > + * @context_id: context id
> > + * @ag_cont_hobc_high: analog gain for high sensitivity image of OBCC
> > + * @ag_cont_hobc_middle_led: analog gain for middle sensitivity or led image
> of OBCC
> > + * @ag_cont_hobc_low: analog gain for low sensitivity image of OBCC
> > + * @ag_cont_abpc_high: analog gain for high sensitivity image of ABPC
> > + * @ag_cont_abpc_middle_led: analog gain for middle sensitivity or led image
> of ABPC
> > + * @ag_cont_abpc_low: analog gain for low sensitivity image of ABPC
> > + * @ag_cont_rcnr_high: analog gain for high sensitivity image of RCNR
> > + * @ag_cont_rcnr_middle_led: analog gain for middle sensitivity or led image
> of RCNR
> > + * @ag_cont_rcnr_low: analog gain for low sensitivity image of RCNR
> > + * @ag_cont_lssc: analog gain for LSSC
> > + * @ag_cont_mpro: analog gain for color matrix correction
> > + * @ag_cont_vpro: analog gain for image quality adjustment
> > + * @dpc_defect_num_h:
> > + * the number of dynamically corrected defective pixel(high sensitivity
> image)
> > + * @dpc_defect_num_m:
> > + * the number of dynamically corrected defective pixel(middle
> sensitivity or led image)
> > + * @dpc_defect_num_l:
> > + * the number of dynamically corrected defective pixel(low sensitivity
> image)
> > + * @hdrc_tnp_fb_smth_max: the maximum value of luminance information
> after smoothing filter at HDRC
> > + * @avg_lum_weight: weighted average luminance value at average
> luminance generation
> > + * @avg_lum_block[8][8]:
> > + * average luminance of each block [y][x]:
> > + * y means vertical position and x means horizontal position.
> > + * @avg_lum_four_line_lum[4]:
> > + * 4-lines average luminance. avg_lum_four_line_lum[n] corresponds to
> aexp_ave4linesy[n]
> > + * @avg_satur_pixnum: the number of saturated pixel at average luminance
> generation
> > + * @avg_black_pixnum: the number of black pixel at average luminance
> generation
> > + * @awb_ave_u: average U at AWHB [pixel]
> > + * @awb_ave_v: average V at AWHB [pixel]
> > + * @awb_accumulated_pixel: the number of accumulated pixel at AWHB
> > + * @awb_gain_r: R gain applied in the next frame at AWHB
> > + * @awb_gain_g: G gain applied in the next frame at AWHB
> > + * @awb_gain_b: B gain applied in the next frame at AWHB
> > + * @awb_status_u: status of U convergence at AWHB (true: converged, false:
> not converged)
> > + * @awb_status_v: status of V convergence at AWHB (true: converged, false:
> not converged)
> > + */
> > +struct hwd_viif_l1_info {
> > + u32 context_id;
> > + u8 ag_cont_hobc_high;
> > + u8 ag_cont_hobc_middle_led;
> > + u8 ag_cont_hobc_low;
> > + u8 ag_cont_abpc_high;
> > + u8 ag_cont_abpc_middle_led;
> > + u8 ag_cont_abpc_low;
> > + u8 ag_cont_rcnr_high;
> > + u8 ag_cont_rcnr_middle_led;
> > + u8 ag_cont_rcnr_low;
> > + u8 ag_cont_lssc;
> > + u8 ag_cont_mpro;
> > + u8 ag_cont_vpro;
> > + u32 dpc_defect_num_h;
> > + u32 dpc_defect_num_m;
> > + u32 dpc_defect_num_l;
> > + u32 hdrc_tnp_fb_smth_max;
> > + u32 avg_lum_weight;
> > + u32 avg_lum_block[8][8];
> > + u32 avg_lum_four_line_lum[4];
> > + u16 avg_satur_pixnum;
> > + u16 avg_black_pixnum;
> > + u32 awb_ave_u;
> > + u32 awb_ave_v;
> > + u32 awb_accumulated_pixel;
> > + u32 awb_gain_r;
> > + u32 awb_gain_g;
> > + u32 awb_gain_b;
> > + bool awb_status_u;
> > + bool awb_status_v;
> > +};
> > +
> > +/**
> > + * struct hwd_viif_l2_gamma_table - HWD L2ISP Gamma table physical
> address
> > + * @table[6]: table address(physical address) 4byte alignment
> > + *
> > + * relation between element and table is as below.
> > + * * [0]: G/Y(1st table)
> > + * * [1]: G/Y(2nd table)
> > + * * [2]: B/U(1st table)
> > + * * [3]: B/U(2nd table)
> > + * * [4]: R/V(1st table)
> > + * * [5]: R/V(2nd table)
> > + *
> > + * when 0 is set to table address, table transfer is disabled.
> > + */
> > +struct hwd_viif_l2_gamma_table {
> > + uintptr_t table[6];
> > +};
> > +
> > +struct hwd_viif_res;
> > +
> > +/* VIIF common */
> > +u32 hwd_viif_csi2rx_err_irq_handler(struct hwd_viif_res *res);
> > +void hwd_viif_status_err_irq_handler(struct hwd_viif_res *res, u32
> *event_main, u32 *event_sub);
> > +void hwd_viif_vsync_irq_handler(struct hwd_viif_res *res, u32 *event_main,
> u32 *event_sub);
> > +void hwd_viif_isp_regbuf_irq_handler(struct hwd_viif_res *res, u32 *event_l1,
> u32 *event_l2);
> > +
> > +/* control MAIN unit */
> > +s32 hwd_viif_main_set_unit(struct hwd_viif_res *res, u32 dt_image,
> > + const struct hwd_viif_input_img *in_img, u32
> color_type, u32 rawpack,
> > + u32 yuv_conv);
> > +s32 hwd_viif_main_mask_vlatch(struct hwd_viif_res *res, u32 enable);
> > +void hwd_viif_main_status_err_set_irq_mask(struct hwd_viif_res *res, u32
> mask);
> > +void hwd_viif_main_vsync_set_irq_mask(struct hwd_viif_res *res, u32
> mask);
> > +
> > +/* conrol SUB unit */
> > +s32 hwd_viif_sub_set_unit(struct hwd_viif_res *res, u32 dt_image,
> > + const struct hwd_viif_input_img *in_img);
> > +s32 hwd_viif_sub_set_img_transmission(struct hwd_viif_res *res, const
> struct hwd_viif_img *img);
> > +void hwd_viif_sub_status_err_set_irq_mask(struct hwd_viif_res *res, u32
> mask);
> > +void hwd_viif_sub_vsync_set_irq_mask(struct hwd_viif_res *res, u32 mask);
> > +
> > +/* control MIPI CSI2 Receiver unit */
> > +s32 hwd_viif_csi2rx_initialize(struct hwd_viif_res *res, u32 num_lane, u32
> lane_assign,
> > + u32 dphy_rate, u32 rext_calibration,
> > + const struct hwd_viif_csi2rx_line_err_target
> *err_target,
> > + const struct hwd_viif_csi2rx_irq_mask *mask);
> > +s32 hwd_viif_csi2rx_uninitialize(struct hwd_viif_res *res);
> > +s32 hwd_viif_csi2rx_start(struct hwd_viif_res *res, s32 vc_main, s32 vc_sub,
> > + const struct hwd_viif_csi2rx_packet *packet);
> > +s32 hwd_viif_csi2rx_stop(struct hwd_viif_res *res);
> > +s32 hwd_viif_csi2rx_get_calibration_status(
> > + struct hwd_viif_res *res, struct viif_csi2rx_dphy_calibration_status
> *calibration_status);
> > +s32 hwd_viif_csi2rx_get_err_status(struct hwd_viif_res *res, u32
> *err_phy_fatal, u32 *err_pkt_fatal,
> > + u32 *err_frame_fatal, u32 *err_phy, u32
> *err_pkt, u32 *err_line);
> > +
> > +/* control L1 Image Signal Processor */
> > +void hwd_viif_isp_set_regbuf_auto_transmission(struct hwd_viif_res *res);
> > +void hwd_viif_isp_disable_regbuf_auto_transmission(struct hwd_viif_res
> *res);
> > +void hwd_viif_isp_get_info(struct hwd_viif_res *res, struct hwd_viif_l1_info
> *l1_info,
> > + u32 *l2_transfer_status);
> > +void hwd_viif_isp_set_regbuf_irq_mask(struct hwd_viif_res *res, const u32
> *mask_l1,
> > + const u32 *mask_l2);
> > +
> > +s32 hwd_viif_l1_set_input_mode(struct hwd_viif_res *res, u32 mode, u32
> depth, u32 raw_color_filter);
> > +s32 hwd_viif_l1_set_rgb_to_y_coef(struct hwd_viif_res *res, u16 coef_r, u16
> coef_g, u16 coef_b);
> > +s32 hwd_viif_l1_set_ag_mode(struct hwd_viif_res *res, const struct
> viif_l1_ag_mode_config *param);
> > +s32 hwd_viif_l1_set_ag(struct hwd_viif_res *res, u16 gain_h, u16 gain_m,
> u16 gain_l);
> > +s32 hwd_viif_l1_set_hdre(struct hwd_viif_res *res, const struct
> viif_l1_hdre_config *param);
> > +s32 hwd_viif_l1_set_img_extraction(struct hwd_viif_res *res, u32
> input_black_gr, u32 input_black_r,
> > + u32 input_black_b, u32 input_black_gb);
> > +s32 hwd_viif_l1_set_dpc(struct hwd_viif_res *res, const struct viif_l1_dpc
> *param_h,
> > + const struct viif_l1_dpc *param_m, const struct
> viif_l1_dpc *param_l);
> > +s32 hwd_viif_l1_set_dpc_table_transmission(struct hwd_viif_res *res,
> uintptr_t table_h,
> > + uintptr_t table_m, uintptr_t
> table_l);
> > +s32 hwd_viif_l1_set_preset_white_balance(struct hwd_viif_res *res, u32
> dstmaxval,
> > + const struct viif_l1_preset_wb
> *param_h,
> > + const struct viif_l1_preset_wb
> *param_m,
> > + const struct viif_l1_preset_wb
> *param_l);
> > +s32 hwd_viif_l1_set_raw_color_noise_reduction(
> > + struct hwd_viif_res *res, const struct viif_l1_raw_color_noise_reduction
> *param_h,
> > + const struct viif_l1_raw_color_noise_reduction *param_m,
> > + const struct viif_l1_raw_color_noise_reduction *param_l);
> > +s32 hwd_viif_l1_set_hdrs(struct hwd_viif_res *res, const struct
> viif_l1_hdrs_config *param);
> > +s32 hwd_viif_l1_set_black_level_correction(
> > + struct hwd_viif_res *res, const struct
> viif_l1_black_level_correction_config *param);
> > +s32 hwd_viif_l1_set_lsc(struct hwd_viif_res *res, const struct hwd_viif_l1_lsc
> *param);
> > +s32 hwd_viif_l1_set_lsc_table_transmission(struct hwd_viif_res *res,
> uintptr_t table_gr,
> > + uintptr_t table_r, uintptr_t table_b,
> > + uintptr_t table_gb);
> > +s32 hwd_viif_l1_set_main_process(struct hwd_viif_res *res, u32
> demosaic_mode, u32 damp_lsbsel,
> > + const struct viif_l1_color_matrix_correction
> *color_matrix,
> > + u32 dst_maxval);
> > +s32 hwd_viif_l1_set_awb(struct hwd_viif_res *res, const struct viif_l1_awb
> *param, u32 awhb_wbmrg,
> > + u32 awhb_wbmgg, u32 awhb_wbmbg);
> > +s32 hwd_viif_l1_lock_awb_gain(struct hwd_viif_res *res, u32 enable);
> > +s32 hwd_viif_l1_set_hdrc(struct hwd_viif_res *res, const struct viif_l1_hdrc
> *param,
> > + u32 hdrc_thr_sft_amt);
> > +s32 hwd_viif_l1_set_hdrc_ltm(struct hwd_viif_res *res, const struct
> viif_l1_hdrc_ltm_config *param);
> > +s32 hwd_viif_l1_set_gamma(struct hwd_viif_res *res, const struct
> viif_l1_gamma *param);
> > +s32 hwd_viif_l1_set_img_quality_adjustment(struct hwd_viif_res *res,
> > + const struct
> hwd_viif_l1_img_quality_adjustment *param);
> > +s32 hwd_viif_l1_set_avg_lum_generation(struct hwd_viif_res *res,
> > + const struct
> viif_l1_avg_lum_generation_config *param);
> > +void hwd_viif_l1_set_irq_mask(struct hwd_viif_res *res, u32 mask);
> > +
> > +/* control L2 Image Signal Processor */
> > +s32 hwd_viif_l2_set_input_csc(struct hwd_viif_res *res, const struct
> hwd_viif_csc_param *param,
> > + bool is_l1_rgb);
> > +s32 hwd_viif_l2_set_undist(struct hwd_viif_res *res, const struct
> viif_l2_undist *param);
> > +s32 hwd_viif_l2_set_undist_table_transmission(struct hwd_viif_res *res,
> uintptr_t write_g,
> > + uintptr_t read_b, uintptr_t
> read_g, uintptr_t read_r,
> > + u32 size);
> > +s32 hwd_viif_l2_set_roi(struct hwd_viif_res *res, const struct
> viif_l2_roi_config *param);
> > +s32 hwd_viif_l2_set_gamma(struct hwd_viif_res *res, u32 post_id, u32
> enable, u32 vsplit, u32 mode);
> > +s32 hwd_viif_l2_set_gamma_table_transmission(struct hwd_viif_res *res,
> u32 post_id,
> > + const struct
> hwd_viif_l2_gamma_table *gamma_table);
> > +s32 hwd_viif_l2_set_output_csc(struct hwd_viif_res *res, u32 post_id,
> > + const struct hwd_viif_csc_param *param);
> > +s32 hwd_viif_l2_set_img_transmission(struct hwd_viif_res *res, u32 post_id,
> u32 enable,
> > + const struct hwd_viif_img_area *src,
> > + const struct hwd_viif_out_process
> *out_process,
> > + const struct hwd_viif_img *img);
> > +void hwd_viif_l2_set_irq_mask(struct hwd_viif_res *res, u32 mask);
> > +
> > +void hwd_viif_isp_guard_start(struct hwd_viif_res *res);
> > +void hwd_viif_isp_guard_end(struct hwd_viif_res *res);
> > +
> > +struct hwd_viif_res *allocate_viif_res(struct device *dev, void
> *csi2host_vaddr,
> > + void *capture_vaddr);
> > +
> > +#endif /* HWD_VIIF_H */
> > diff --git a/drivers/media/platform/visconti/hwd_viif_csi2rx.c
> b/drivers/media/platform/visconti/hwd_viif_csi2rx.c
> > new file mode 100644
> > index 00000000000..f49869c5bdd
> > --- /dev/null
> > +++ b/drivers/media/platform/visconti/hwd_viif_csi2rx.c
> > @@ -0,0 +1,610 @@
> > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> > +/* Toshiba Visconti Video Capture Support
> > + *
> > + * (C) Copyright 2022 TOSHIBA CORPORATION
> > + * (C) Copyright 2022 Toshiba Electronic Devices & Storage Corporation
> > + */
> > +
> > +#include <linux/delay.h>
> > +#include <linux/io.h>
> > +#include <linux/timekeeping.h>
> > +#include "hwd_viif.h"
> > +#include "hwd_viif_internal.h"
> > +
> > +#define CSI2_DT_YUV4208 0x18
> > +#define CSI2_DT_YUV42010 0x19
> > +#define CSI2_DT_YUV4208L 0x1A
> > +#define CSI2_DT_YUV4208C 0x1C
> > +#define CSI2_DT_YUV42010C 0x1D
> > +#define CSI2_DT_YUV4228B VISCONTI_CSI2_DT_YUV4228B
> > +#define CSI2_DT_YUV42210B VISCONTI_CSI2_DT_YUV42210B
> > +#define CSI2_DT_RGB444 0x20
> > +#define CSI2_DT_RGB555 0x21
> > +#define CSI2_DT_RGB565 VISCONTI_CSI2_DT_RGB565
> > +#define CSI2_DT_RGB666 0x23
> > +#define CSI2_DT_RGB888 VISCONTI_CSI2_DT_RGB888
> > +#define CSI2_DT_RAW8 VISCONTI_CSI2_DT_RAW8
> > +#define CSI2_DT_RAW10 VISCONTI_CSI2_DT_RAW10
> > +#define CSI2_DT_RAW12 VISCONTI_CSI2_DT_RAW12
> > +#define CSI2_DT_RAW14 VISCONTI_CSI2_DT_RAW14
>
> Same here.

I'll use definitions in mipi-csi2.h

> > +
> > +#define TESTCTRL0_PHY_TESTCLK_1 0x2
> > +#define TESTCTRL0_PHY_TESTCLK_0 0x0
> > +#define TESTCTRL1_PHY_TESTEN 0x10000
> > +#define TESTCTRL1_PHY_TESTDOUT_SHIFT 8U
> > +
> > +/**
> > + * write_dphy_param() - Write CSI2RX DPHY params
> > + *
> > + * @test_mode: test code address
> > + * @test_in: test code data
> > + * Return: None
> > + */
> > +static void write_dphy_param(u32 test_mode, u8 test_in, struct hwd_viif_res
> *res)
> > +{
> > + /* select MSB address register */
> > + writel(TESTCTRL1_PHY_TESTEN,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL1);
> > +
> > + /* rise and clear the testclk */
> > + writel(TESTCTRL0_PHY_TESTCLK_1,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > + writel(TESTCTRL0_PHY_TESTCLK_0,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > +
> > + /* set MSB address of test_mode */
> > + writel(FIELD_GET(0xF00, test_mode),
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL1);
> > +
> > + /* rise and clear the testclk */
> > + writel(TESTCTRL0_PHY_TESTCLK_1,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > + writel(TESTCTRL0_PHY_TESTCLK_0,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > +
> > + /* select and set LSB address register */
> > + writel(TESTCTRL1_PHY_TESTEN | FIELD_GET(0xFF, test_mode),
> > + &res->csi2host_reg->CSI2RX_PHY_TESTCTRL1);
> > +
> > + /* rise and clear the testclk */
> > + writel(TESTCTRL0_PHY_TESTCLK_1,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > + writel(TESTCTRL0_PHY_TESTCLK_0,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > +
> > + /* set the test code data */
> > + writel((u32)test_in, &res->csi2host_reg->CSI2RX_PHY_TESTCTRL1);
> > +
> > + /* rise and clear the testclk */
> > + writel(TESTCTRL0_PHY_TESTCLK_1,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > + writel(TESTCTRL0_PHY_TESTCLK_0,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > +}
> > +
> > +/**
> > + * read_dphy_param() - Read CSI2RX DPHY params
> > + *
> > + * @test_mode: test code address
> > + * Return: test code data
> > + */
> > +static u8 read_dphy_param(u32 test_mode, struct hwd_viif_res *res)
> > +{
> > + u32 read_data;
> > +
> > + /* select MSB address register */
> > + writel(TESTCTRL1_PHY_TESTEN,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL1);
> > +
> > + /* rise and clear the testclk */
> > + writel(TESTCTRL0_PHY_TESTCLK_1,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > + writel(TESTCTRL0_PHY_TESTCLK_0,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > +
> > + /* set MSB address of test_mode */
> > + writel(FIELD_GET(0xF00, test_mode),
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL1);
> > +
> > + /* rise and clear the testclk */
> > + writel(TESTCTRL0_PHY_TESTCLK_1,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > + writel(TESTCTRL0_PHY_TESTCLK_0,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > +
> > + /* select and set LSB address register */
> > + writel(TESTCTRL1_PHY_TESTEN | FIELD_GET(0xFF, test_mode),
> > + &res->csi2host_reg->CSI2RX_PHY_TESTCTRL1);
> > +
> > + /* rise and clear the testclk */
> > + writel(TESTCTRL0_PHY_TESTCLK_1,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > + writel(TESTCTRL0_PHY_TESTCLK_0,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > +
> > + /* read the test code data */
> > + read_data = readl(&res->csi2host_reg->CSI2RX_PHY_TESTCTRL1);
> > + return (u8)(read_data >> TESTCTRL1_PHY_TESTDOUT_SHIFT);
> > +}
> > +
> > +/**
> > + * enum dphy_testcode - DPHY registers via the local communication path
> > + */
> > +enum dphy_testcode {
> > + DIG_RDWR_RX_SYS_0 = 0x001,
> > + DIG_RDWR_RX_SYS_1 = 0x002,
> > + DIG_RDWR_RX_SYS_3 = 0x004,
> > + DIG_RDWR_RX_SYS_7 = 0x008,
> > + DIG_RDWR_RX_RX_STARTUP_OVR_2 = 0x0E2,
> > + DIG_RDWR_RX_RX_STARTUP_OVR_3 = 0x0E3,
> > + DIG_RDWR_RX_RX_STARTUP_OVR_4 = 0x0E4,
> > + DIG_RDWR_RX_RX_STARTUP_OVR_5 = 0x0E5,
> > + DIG_RDWR_RX_CB_2 = 0x1AC,
> > + DIG_RD_RX_TERM_CAL_0 = 0x220,
> > + DIG_RD_RX_TERM_CAL_1 = 0x221,
> > + DIG_RD_RX_TERM_CAL_2 = 0x222,
> > + DIG_RDWR_RX_CLKLANE_LANE_6 = 0x307,
> > + DIG_RD_RX_CLKLANE_OFFSET_CAL_0 = 0x39D,
> > + DIG_RD_RX_LANE0_OFFSET_CAL_0 = 0x59F,
> > + DIG_RD_RX_LANE0_DDL_0 = 0x5E0,
> > + DIG_RD_RX_LANE1_OFFSET_CAL_0 = 0x79F,
> > + DIG_RD_RX_LANE1_DDL_0 = 0x7E0,
> > + DIG_RD_RX_LANE2_OFFSET_CAL_0 = 0x99F,
> > + DIG_RD_RX_LANE2_DDL_0 = 0x9E0,
> > + DIG_RD_RX_LANE3_OFFSET_CAL_0 = 0xB9F,
> > + DIG_RD_RX_LANE3_DDL_0 = 0xBE0,
> > +};
> > +
> > +#define SYS_0_HSFREQRANGE_OVR BIT(5)
> > +#define SYS_7_RESERVED FIELD_PREP(0x1F, 0x0C)
> > +#define SYS_7_DESKEW_POL BIT(5)
> > +#define STARTUP_OVR_4_CNTVAL FIELD_PREP(0x70, 0x01)
> > +#define STARTUP_OVR_4_DDL_EN BIT(0)
> > +#define STARTUP_OVR_5_BYPASS BIT(0)
> > +#define CB_2_LPRX_BIAS BIT(6)
> > +#define CB_2_RESERVED FIELD_PREP(0x3F, 0x0B)
> > +#define CLKLANE_RXHS_PULL_LONG BIT(7)
> > +
> > +static const struct hwd_viif_dphy_hs_info dphy_hs_info[] = {
> > + { 80, 0x0, 0x1cc }, { 85, 0x10, 0x1cc }, { 95, 0x20, 0x1cc }, { 105,
> 0x30, 0x1cc },
> > + { 115, 0x1, 0x1cc }, { 125, 0x11, 0x1cc }, { 135, 0x21, 0x1cc }, { 145,
> 0x31, 0x1cc },
> > + { 155, 0x2, 0x1cc }, { 165, 0x12, 0x1cc }, { 175, 0x22, 0x1cc }, { 185,
> 0x32, 0x1cc },
> > + { 198, 0x3, 0x1cc }, { 213, 0x13, 0x1cc }, { 228, 0x23, 0x1cc }, { 243,
> 0x33, 0x1cc },
> > + { 263, 0x4, 0x1cc }, { 288, 0x14, 0x1cc }, { 313, 0x25, 0x1cc }, { 338,
> 0x35, 0x1cc },
> > + { 375, 0x5, 0x1cc }, { 425, 0x16, 0x1cc }, { 475, 0x26, 0x1cc }, { 525,
> 0x37, 0x1cc },
> > + { 575, 0x7, 0x1cc }, { 625, 0x18, 0x1cc }, { 675, 0x28, 0x1cc }, { 725,
> 0x39, 0x1cc },
> > + { 775, 0x9, 0x1cc }, { 825, 0x19, 0x1cc }, { 875, 0x29, 0x1cc }, { 925,
> 0x3a, 0x1cc },
> > + { 975, 0xa, 0x1cc }, { 1025, 0x1a, 0x1cc }, { 1075, 0x2a, 0x1cc }, { 1125,
> 0x3b, 0x1cc },
> > + { 1175, 0xb, 0x1cc }, { 1225, 0x1b, 0x1cc }, { 1275, 0x2b, 0x1cc }, { 1325,
> 0x3c, 0x1cc },
> > + { 1375, 0xc, 0x1cc }, { 1425, 0x1c, 0x1cc }, { 1475, 0x2c, 0x1cc }
> > +};
> > +
> > +/**
> > + * get_dphy_hs_transfer_info() - Get DPHY HS info from table
> > + *
> > + * @dphy_rate: DPHY clock in MHz
> > + * @hsfreqrange: HS Frequency Range
> > + * @osc_freq_target: OSC Frequency Target
> > + * Return: None
> > + */
> > +static void get_dphy_hs_transfer_info(u32 dphy_rate, u32 *hsfreqrange, u32
> *osc_freq_target,
> > + struct hwd_viif_res *res)
> > +{
> > + int table_size = ARRAY_SIZE(dphy_hs_info);
>
> No need for a local variable.

I'll drop it.

> > + int i;
>
> unsigned int

I'll fix it. Same for similar cases.

> > +
> > + for (i = 1; i < table_size; i++) {
> > + if (dphy_rate < dphy_hs_info[i].rate) {
> > + *hsfreqrange = dphy_hs_info[i - 1].hsfreqrange;
> > + *osc_freq_target = dphy_hs_info[i - 1].osc_freq_target;
> > + return;
> > + }
> > + }
> > +
> > + /* not found; return the largest entry */
> > + *hsfreqrange = dphy_hs_info[table_size - 1].hsfreqrange;
> > + *osc_freq_target = dphy_hs_info[table_size - 1].osc_freq_target;
> > +}
> > +
> > +/**
> > + * hwd_viif_csi2rx_set_dphy_rate() - Set D-PHY rate
> > + *
> > + * @dphy_rate: D-PHY rate of 1 Lane[Mbps] [80..1500]
> > + * Return: None
> > + */
> > +static void hwd_viif_csi2rx_set_dphy_rate(u32 dphy_rate, struct hwd_viif_res
> *res)
> > +{
> > + u32 hsfreqrange, osc_freq_target;
> > +
> > + get_dphy_hs_transfer_info(dphy_rate, &hsfreqrange, &osc_freq_target,
> res);
> > +
> > + write_dphy_param(DIG_RDWR_RX_SYS_1, (u8)hsfreqrange, res);
> > + write_dphy_param(DIG_RDWR_RX_SYS_0,
> SYS_0_HSFREQRANGE_OVR, res);
> > + write_dphy_param(DIG_RDWR_RX_RX_STARTUP_OVR_5,
> STARTUP_OVR_5_BYPASS, res);
> > + write_dphy_param(DIG_RDWR_RX_RX_STARTUP_OVR_4,
> STARTUP_OVR_4_CNTVAL, res);
> > + write_dphy_param(DIG_RDWR_RX_CB_2, CB_2_LPRX_BIAS |
> CB_2_RESERVED, res);
> > + write_dphy_param(DIG_RDWR_RX_SYS_7, SYS_7_DESKEW_POL |
> SYS_7_RESERVED, res);
> > + write_dphy_param(DIG_RDWR_RX_CLKLANE_LANE_6,
> CLKLANE_RXHS_PULL_LONG, res);
> > + write_dphy_param(DIG_RDWR_RX_RX_STARTUP_OVR_2,
> FIELD_GET(0xff, osc_freq_target), res);
> > + write_dphy_param(DIG_RDWR_RX_RX_STARTUP_OVR_3,
> FIELD_GET(0xf00, osc_freq_target), res);
> > + write_dphy_param(DIG_RDWR_RX_RX_STARTUP_OVR_4,
> STARTUP_OVR_4_CNTVAL | STARTUP_OVR_4_DDL_EN,
> > + res);
> > +
> > + writel(HWD_VIIF_DPHY_CFG_CLK_25M,
> &res->capture_reg->sys.DPHY_FREQRANGE);
> > +}
> > +
> > +/**
> > + * check_dphy_calibration_status() - Check D-PHY calibration status
> > + *
> > + * @test_mode: test code related to calibration information
> > + * @shift_val_err: shift value related to error information
> > + * @shift_val_done: shift value related to done information
> > + * Return: HWD_VIIF_CSI2_CAL_NOT_DONE calibration is not done(out of
> target or not completed)
> > + * Return: HWD_VIIF_CSI2_CAL_FAIL calibration was failed
> > + * Return: HWD_VIIF_CSI2_CAL_SUCCESS calibration was succeeded
> > + */
> > +static u32 check_dphy_calibration_status(u32 test_mode, u32 shift_val_err,
> u32 shift_val_done,
> > + struct hwd_viif_res *res)
> > +{
> > + u32 read_data = (u32)read_dphy_param(test_mode, res);
> > +
> > + if (!(read_data & BIT(shift_val_done)))
> > + return HWD_VIIF_CSI2_CAL_NOT_DONE;
> > +
> > + /* error check is not required for termination calibration with
> REXT(0x221) */
> > + if (test_mode == DIG_RD_RX_TERM_CAL_1)
> > + return HWD_VIIF_CSI2_CAL_SUCCESS;
> > +
> > + /* done with error */
> > + if (read_data & BIT(shift_val_err))
> > + return HWD_VIIF_CSI2_CAL_FAIL;
> > +
> > + return HWD_VIIF_CSI2_CAL_SUCCESS;
> > +}
> > +
> > +/**
> > + * hwd_viif_csi2rx_initialize() - Initialize CSI-2 RX driver
> > + *
> > + * @num_lane: [1..4](VIIF CH0-CH1)
> > + * @lane_assign: lane connection. For more refer @ref
> hwd_viif_dphy_lane_assignment
> > + * @dphy_rate: D-PHY rate of 1 Lane[Mbps] [80..1500]
> > + * @rext_calibration: enable or disable rext calibration.
> > + * For more refer @ref hwd_viif_csi2rx_cal_status
> > + * @err_target: Pointer to configuration for Line error detection.
> > + * @mask: MASK of CSI-2 RX error interruption
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] "num_lane", "lane_assign", "dphy_rate", "rext_calibration" or
> "input_mode" is out of range
> > + * - [2] "err_target" is NULL
> > + * - [3] member of "err_target" is invalid
> > + */
> > +s32 hwd_viif_csi2rx_initialize(struct hwd_viif_res *res, u32 num_lane, u32
> lane_assign,
> > + u32 dphy_rate, u32 rext_calibration,
> > + const struct hwd_viif_csi2rx_line_err_target
> *err_target,
> > + const struct hwd_viif_csi2rx_irq_mask *mask)
> > +{
> > + u32 i, val;
> > +
> > + if (num_lane == 0U || num_lane > 4U || lane_assign >
> HWD_VIIF_CSI2_DPHY_L0L2L1L3)
> > + return -EINVAL;
> > +
> > + if (dphy_rate < HWD_VIIF_DPHY_MIN_DATA_RATE || dphy_rate >
> HWD_VIIF_DPHY_MAX_DATA_RATE ||
> > + (rext_calibration != HWD_VIIF_ENABLE && rext_calibration !=
> HWD_VIIF_DISABLE) ||
> > + !err_target) {
> > + return -EINVAL;
> > + }
> > +
> > + for (i = 0; i < 8U; i++) {
> > + if (err_target->vc[i] > HWD_VIIF_CSI2_MAX_VC ||
> > + err_target->dt[i] > HWD_VIIF_CSI2_MAX_DT ||
> > + (err_target->dt[i] < HWD_VIIF_CSI2_MIN_DT &&
> err_target->dt[i] != 0U)) {
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + /* 1st phase of initialization */
> > + writel(HWD_VIIF_ENABLE, &res->csi2host_reg->CSI2RX_RESETN);
> > + writel(HWD_VIIF_DISABLE,
> &res->csi2host_reg->CSI2RX_PHY_RSTZ);
> > + writel(HWD_VIIF_DISABLE,
> &res->csi2host_reg->CSI2RX_PHY_SHUTDOWNZ);
> > + writel(HWD_VIIF_ENABLE,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > + ndelay(15U);
> > + writel(HWD_VIIF_DISABLE,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > +
> > + /* Configure D-PHY frequency range */
> > + hwd_viif_csi2rx_set_dphy_rate(dphy_rate, res);
> > +
> > + /* 2nd phase of initialization */
> > + writel((num_lane - 1U), &res->csi2host_reg->CSI2RX_NLANES);
> > + ndelay(5U);
> > +
> > + /* configuration not to use rext */
> > + if (rext_calibration == HWD_VIIF_DISABLE) {
> > + write_dphy_param(0x004, 0x10, res);
> > + ndelay(5U);
> > + }
> > +
> > + /* Release D-PHY from Reset */
> > + writel(HWD_VIIF_ENABLE,
> &res->csi2host_reg->CSI2RX_PHY_SHUTDOWNZ);
> > + ndelay(5U);
> > + writel(HWD_VIIF_ENABLE, &res->csi2host_reg->CSI2RX_PHY_RSTZ);
> > +
> > + /* configuration of line error target */
> > + val = (err_target->vc[3] << 30U) | (err_target->dt[3] << 24U) |
> (err_target->vc[2] << 22U) |
> > + (err_target->dt[2] << 16U) | (err_target->vc[1] << 14U) |
> (err_target->dt[1] << 8U) |
> > + (err_target->vc[0] << 6U) | (err_target->dt[0]);
> > + writel(val, &res->csi2host_reg->CSI2RX_DATA_IDS_1);
> > + val = (err_target->vc[7] << 30U) | (err_target->dt[7] << 24U) |
> (err_target->vc[6] << 22U) |
> > + (err_target->dt[6] << 16U) | (err_target->vc[5] << 14U) |
> (err_target->dt[5] << 8U) |
> > + (err_target->vc[4] << 6U) | (err_target->dt[4]);
> > + writel(val, &res->csi2host_reg->CSI2RX_DATA_IDS_2);
> > +
> > + /* configuration of mask */
> > + writel(mask->mask[0],
> &res->csi2host_reg->CSI2RX_INT_MSK_PHY_FATAL);
> > + writel(mask->mask[1],
> &res->csi2host_reg->CSI2RX_INT_MSK_PKT_FATAL);
> > + writel(mask->mask[2],
> &res->csi2host_reg->CSI2RX_INT_MSK_FRAME_FATAL);
> > + writel(mask->mask[3], &res->csi2host_reg->CSI2RX_INT_MSK_PHY);
> > + writel(mask->mask[4], &res->csi2host_reg->CSI2RX_INT_MSK_PKT);
> > + writel(mask->mask[5],
> &res->csi2host_reg->CSI2RX_INT_MSK_LINE);
> > +
> > + /* configuration of lane assignment */
> > + writel(lane_assign, &res->capture_reg->sys.DPHY_LANE);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_csi2rx_uninitialize() - Uninitialize CSI-2 RX driver
> > + *
> > + * Return: 0 Operation completes successfully
> > + */
> > +s32 hwd_viif_csi2rx_uninitialize(struct hwd_viif_res *res)
> > +{
> > + writel(HWD_VIIF_DISABLE,
> &res->csi2host_reg->CSI2RX_PHY_SHUTDOWNZ);
> > + writel(HWD_VIIF_DISABLE,
> &res->csi2host_reg->CSI2RX_PHY_RSTZ);
> > + writel(HWD_VIIF_ENABLE,
> &res->csi2host_reg->CSI2RX_PHY_TESTCTRL0);
> > + writel(HWD_VIIF_DISABLE, &res->csi2host_reg->CSI2RX_RESETN);
> > +
> > + return 0;
> > +}
> > +
> > +#define PORT_SEL_MAIN_LONG 0
> > +#define PORT_SEL_MAIN_EMBED 1
> > +#define PORT_SEL_SUB_LONG 4
> > +#define PORT_SEL_SUB_EMBED 5
> > +
> > +static void config_vdm_wport(struct hwd_viif_res *res, int port_sel, u32
> height, u32 pitch)
> > +{
> > + struct hwd_viif_vdm_write_port_reg *wport;
> > + u32 start_addr, end_addr;
> > +
> > + wport = &res->capture_reg->vdm.w_port[port_sel];
> > +
> > + writel(pitch, &wport->VDM_W_PITCH);
> > + writel(height, &wport->VDM_W_HEIGHT);
> > + start_addr = readl(&wport->VDM_W_STADR);
> > + end_addr = start_addr + pitch - 1U;
> > + writel(end_addr, &wport->VDM_W_ENDADR);
> > +}
> > +
> > +/**
> > + * hwd_viif_csi2rx_start() - Start CSI-2 input
> > + *
> > + * @vc_main: control CSI-2 input of MAIN unit.
> > + * enable with configured VC: 0, 1, 2 or 3, keep disabling:
> > + * @vc_sub: control CSI-2 input of SUB unit.
> > + * enable with configured VC: 0, 1, 2 or 3, keep disabling:
> > + * @packet: Pointer to packet information of embedded data and long packet
> data
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * HWD_VIIF_CSI2_NOT_CAPTURE
> > + * HWD_VIIF_CSI2_NOT_CAPTURE
> > + * - [1] "vc_main" or "vc_sub" is out of range
> > + * - [2] member of "packet" is invalid
> > + */
> > +s32 hwd_viif_csi2rx_start(struct hwd_viif_res *res, s32 vc_main, s32 vc_sub,
> > + const struct hwd_viif_csi2rx_packet *packet)
> > +{
> > + u32 val, i, pitch, height, dt;
> > + u32 enable_vc0 = HWD_VIIF_DISABLE;
> > + u32 enable_vc1 = HWD_VIIF_DISABLE;
> > +
> > + if (vc_main > 3 || vc_main < HWD_VIIF_CSI2_NOT_CAPTURE || vc_sub
> > 3 ||
> > + vc_sub < HWD_VIIF_CSI2_NOT_CAPTURE) {
> > + return -EINVAL;
> > + }
> > +
> > + for (i = 0; i < VISCONTI_CSI2RX_PACKET_TYPES_NUM; i++) {
> > + if (packet->word_count[i] >
> HWD_VIIF_CSI2_MAX_WORD_COUNT ||
> > + packet->packet_num[i] >
> HWD_VIIF_CSI2_MAX_PACKET_NUM) {
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + writel(HWD_VIIF_INPUT_CSI2, &res->capture_reg->sys.IPORTM);
> > +
> > + if (vc_main != HWD_VIIF_CSI2_NOT_CAPTURE) {
> > + writel((u32)vc_main, &res->capture_reg->sys.VCID0SELECT);
> > + enable_vc0 = HWD_VIIF_ENABLE;
> > + }
> > + if (vc_sub != HWD_VIIF_CSI2_NOT_CAPTURE) {
> > + writel((u32)vc_sub, &res->capture_reg->sys.VCID1SELECT);
> > + enable_vc1 = HWD_VIIF_ENABLE;
> > + }
> > +
> > + /* configure Embedded Data transfer of MAIN unit */
> > + height =
> packet->packet_num[VISCONTI_CSI2RX_PACKET_TYPE_EMB_MAIN];
> > + pitch =
> ALIGN(packet->word_count[VISCONTI_CSI2RX_PACKET_TYPE_EMB_MAIN],
> 4);
> > + config_vdm_wport(res, PORT_SEL_MAIN_EMBED, height, pitch);
> > +
> > + /* configure Long Packet transfer of MAIN unit */
> > + dt = readl(&res->capture_reg->sys.IPORTM_OTHER);
> > + if (dt == CSI2_DT_YUV4208 || dt == CSI2_DT_YUV4208 || dt ==
> CSI2_DT_YUV4208C ||
> > + dt == CSI2_DT_YUV42010C) {
> > + pitch =
> ALIGN(packet->word_count[VISCONTI_CSI2RX_PACKET_TYPE_LONG_MAIN],
> 4) +
> > +
> ALIGN(packet->word_count[VISCONTI_CSI2RX_PACKET_TYPE_LON
> G_MAIN] * 2U, 4);
> > + height =
> packet->packet_num[VISCONTI_CSI2RX_PACKET_TYPE_LONG_MAIN] >>
> 1U;
> > + } else {
> > + pitch =
> ALIGN(packet->word_count[VISCONTI_CSI2RX_PACKET_TYPE_LONG_MAIN],
> 4);
> > + height =
> packet->packet_num[VISCONTI_CSI2RX_PACKET_TYPE_LONG_MAIN];
> > + }
> > + config_vdm_wport(res, PORT_SEL_MAIN_LONG, height, pitch);
> > +
> > + /* configure Embedded Data transfer of SUB unit */
> > + height =
> packet->packet_num[VISCONTI_CSI2RX_PACKET_TYPE_EMB_SUB];
> > + pitch =
> ALIGN(packet->word_count[VISCONTI_CSI2RX_PACKET_TYPE_EMB_SUB],
> 4);
> > + config_vdm_wport(res, PORT_SEL_SUB_EMBED, height, pitch);
> > +
> > + /* configure Long Packet transfer of SUB unit */
> > + dt = readl(&res->capture_reg->sys.IPORTS_OTHER);
> > + if (dt == CSI2_DT_YUV4208 || dt == CSI2_DT_YUV42010 || dt ==
> CSI2_DT_YUV4208C ||
> > + dt == CSI2_DT_YUV42010C) {
> > + pitch =
> ALIGN(packet->word_count[VISCONTI_CSI2RX_PACKET_TYPE_LONG_SUB],
> 4) +
> > +
> ALIGN(packet->word_count[VISCONTI_CSI2RX_PACKET_TYPE_LON
> G_SUB] * 2U, 4);
> > + height =
> packet->packet_num[VISCONTI_CSI2RX_PACKET_TYPE_LONG_SUB] >> 1U;
> > + } else {
> > + pitch =
> ALIGN(packet->word_count[VISCONTI_CSI2RX_PACKET_TYPE_LONG_SUB],
> 4);
> > + height =
> packet->packet_num[VISCONTI_CSI2RX_PACKET_TYPE_LONG_SUB];
> > + }
> > + config_vdm_wport(res, PORT_SEL_SUB_LONG, height, pitch);
> > +
> > + /* Control VC port enable */
> > + val = enable_vc0 | (enable_vc1 << 4U);
> > + writel(val, &res->capture_reg->sys.VCPORTEN);
> > +
> > + if (enable_vc0 == HWD_VIIF_ENABLE) {
> > + /* Update flag information for run status of MAIN unit */
> > + res->run_flag_main = true;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_csi2rx_stop() - Stop CSI-2 input
> > + *
> > + * Return: 0 Operation completes successfully
> > + * Return: -ETIMEDOUT Driver timeout error
> > + */
> > +s32 hwd_viif_csi2rx_stop(struct hwd_viif_res *res)
> > +{
> > + u32 status_r, status_w, status_t, l2_status;
> > + u64 timeout_ns, cur_ns;
> > + bool run_flag = true;
> > + s32 ret = 0;
>
> int, please. The same for return type.
>
> This applies to the rest of the patch. Use s32 if you're e.g. dealing with
> hardware registers with a sign bit.

I'll fix it. Same for other functions.

> > +
> > + /* Disable auto transmission of register buffer */
> > + writel(0, &res->capture_reg->l1isp.L1_CRGBF_TRN_A_CONF);
> > + writel(0, &res->capture_reg->l2isp.L2_CRGBF_TRN_A_CONF);
> > +
> > + /* Wait for completion of register buffer transmission */
> > + udelay(HWD_VIIF_WAIT_ISP_REGBF_TRNS_COMPLETE_TIME);
> > +
> > + /* Stop all VCs, long packet input and emb data input of MAIN unit */
> > + writel(HWD_VIIF_DISABLE, &res->capture_reg->sys.VCPORTEN);
> > + writel(HWD_VIIF_DISABLE,
> &res->capture_reg->sys.IPORTM_OTHEREN);
> > + writel(HWD_VIIF_DISABLE,
> &res->capture_reg->sys.IPORTM_EMBEN);
> > +
> > + /* Stop image data input, long packet input and emb data input of SUB
> unit */
> > + writel(HWD_VIIF_DISABLE,
> &res->capture_reg->sys.IPORTS_OTHEREN);
> > + writel(HWD_VIIF_DISABLE,
> &res->capture_reg->sys.IPORTS_EMBEN);
> > + writel(HWD_VIIF_DISABLE, &res->capture_reg->sys.IPORTS_IMGEN);
> > +
> > + /* Stop VDMAC for all table ports, input ports and write ports */
> > + writel(HWD_VIIF_DISABLE,
> &res->capture_reg->vdm.VDM_T_ENABLE);
> > + writel(HWD_VIIF_DISABLE,
> &res->capture_reg->vdm.VDM_R_ENABLE);
> > + writel(HWD_VIIF_DISABLE,
> &res->capture_reg->vdm.VDM_W_ENABLE);
> > +
> > + /* Stop all groups(g00, g01 and g02) of VDMAC */
> > + writel(0x7, &res->capture_reg->vdm.VDM_ABORTSET);
> > +
> > + timeout_ns = ktime_get_ns() +
> HWD_VIIF_WAIT_ABORT_COMPLETE_TIME * 1000;
>
> Wouldn't it be better to calculate how long you expect to busy loop here?

Sorry I couldn't catch the point.
The maximum time to spend at busy loop is HWD_VIIF_WAIT_ABORT_COMPLETE_TIME * 1000 [ns].
Do you mean that it is better to clearly show the timeout? Like...

ret = -ETIMEOUT;
do {
if (...) {
ret = 0;
break;
}
} while (timeout_ns > cur_ns);


> > +
> > + do {
> > + /* Get VDMAC transfer status */
> > + status_r = readl(&res->capture_reg->vdm.VDM_R_RUN);
> > + status_w = readl(&res->capture_reg->vdm.VDM_W_RUN);
> > + status_t = readl(&res->capture_reg->vdm.VDM_T_RUN);
> > +
> > + l2_status =
> readl(&res->capture_reg->l2isp.L2_BUS_L2_STATUS);
> > +
> > + if (status_r == 0U && status_w == 0U && status_t == 0U &&
> l2_status == 0U)
> > + run_flag = false;
> > +
> > + cur_ns = ktime_get_ns();
> > +
> > + if (cur_ns > timeout_ns) {
> > + ret = -ETIMEDOUT;
> > + run_flag = false;
> > + }
> > + } while (run_flag);
> > +
> > + if (ret == 0) {
> > + /* Clear run flag of MAIN unit */
> > + res->run_flag_main = false;
> > + }
> > +
> > + return ret;
> > +}
> > +
> > +/**
> > + * hwd_viif_csi2rx_get_calibration_status() - Get CSI-2 RX calibration status
> > + *
> > + * @calibration_status: Pointer to D-PHY calibration status information
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error
> > + * - [1] "calibration_status" is NULL
> > + */
> > +s32 hwd_viif_csi2rx_get_calibration_status(
> > + struct hwd_viif_res *res, struct viif_csi2rx_dphy_calibration_status
> *calibration_status)
> > +{
> > + if (!calibration_status)
> > + return -EINVAL;
> > +
> > + /* arg0; test register, arg1: error bit, arg2: done bit */
> > + /* 0x221: termination calibration with REXT */
> > + calibration_status->term_cal_with_rext =
> > + check_dphy_calibration_status(DIG_RD_RX_TERM_CAL_1, 0, 7,
> res);
> > + /* 0x39D: clock lane offset calibration */
> > + calibration_status->clock_lane_offset_cal =
> > +
> check_dphy_calibration_status(DIG_RD_RX_CLKLANE_OFFSET_CAL_
> 0, 4, 0, res);
> > + /* 0x59F: data lane0 offset calibration */
> > + calibration_status->data_lane0_offset_cal =
> > +
> check_dphy_calibration_status(DIG_RD_RX_LANE0_OFFSET_CAL_0, 2,
> 1, res);
> > + /* 0x79F: data lane1 offset calibration */
> > + calibration_status->data_lane1_offset_cal =
> > +
> check_dphy_calibration_status(DIG_RD_RX_LANE1_OFFSET_CAL_0, 2,
> 1, res);
> > + /* 0x99F: data lane2 offset calibration */
> > + calibration_status->data_lane2_offset_cal =
> > +
> check_dphy_calibration_status(DIG_RD_RX_LANE2_OFFSET_CAL_0, 2,
> 1, res);
> > + /* 0xB9F: data lane3 offset calibration */
> > + calibration_status->data_lane3_offset_cal =
> > +
> check_dphy_calibration_status(DIG_RD_RX_LANE3_OFFSET_CAL_0, 2,
> 1, res);
> > +
> > + /* 0x5E0: data lane0 DDL(Digital Delay Line) calibration */
> > + calibration_status->data_lane0_ddl_tuning_cal =
> > + check_dphy_calibration_status(DIG_RD_RX_LANE0_DDL_0, 1,
> 2, res);
> > + /* 0x7E0: data lane1 DDL calibration */
> > + calibration_status->data_lane1_ddl_tuning_cal =
> > + check_dphy_calibration_status(DIG_RD_RX_LANE1_DDL_0, 1,
> 2, res);
> > + /* 0x9E0: data lane2 DDL calibration */
> > + calibration_status->data_lane2_ddl_tuning_cal =
> > + check_dphy_calibration_status(DIG_RD_RX_LANE2_DDL_0, 1,
> 2, res);
> > + /* 0xBE0: data lane3 DDL calibration */
> > + calibration_status->data_lane3_ddl_tuning_cal =
> > + check_dphy_calibration_status(DIG_RD_RX_LANE3_DDL_0, 1,
> 2, res);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * hwd_viif_csi2rx_get_err_status() - Get CSI-2 RX error status
> > + *
> > + * @err_phy_fatal: Pointer to D-PHY fatal error information
> > + * @err_pkt_fatal: Pointer to Packet fatal error information
> > + * @err_frame_fatal: Pointer to Frame fatal error information
> > + * @err_phy: Pointer to D-PHY error information
> > + * @err_pkt: Pointer to Packet error information
> > + * @err_line: Pointer to Line error information
> > + * Return: 0 Operation completes successfully
> > + * Return: -EINVAL Parameter error,
> > + * when "err_phy_fatal", "err_pkt_fatal", "err_frame_fatal",
> > + * "err_phy", "err_pkt" or "err_line" is NULL
> > + */
> > +s32 hwd_viif_csi2rx_get_err_status(struct hwd_viif_res *res, u32
> *err_phy_fatal, u32 *err_pkt_fatal,
> > + u32 *err_frame_fatal, u32 *err_phy, u32
> *err_pkt, u32 *err_line)
> > +{
> > + if (!err_phy_fatal || !err_pkt_fatal || !err_frame_fatal || !err_phy
> || !err_pkt ||
> > + !err_line) {
> > + return -EINVAL;
> > + }
> > + *err_phy_fatal =
> readl(&res->csi2host_reg->CSI2RX_INT_ST_PHY_FATAL);
> > + *err_pkt_fatal =
> readl(&res->csi2host_reg->CSI2RX_INT_ST_PKT_FATAL);
> > + *err_frame_fatal =
> readl(&res->csi2host_reg->CSI2RX_INT_ST_FRAME_FATAL);
> > + *err_phy = readl(&res->csi2host_reg->CSI2RX_INT_ST_PHY);
> > + *err_pkt = readl(&res->csi2host_reg->CSI2RX_INT_ST_PKT);
> > + *err_line = readl(&res->csi2host_reg->CSI2RX_INT_ST_LINE);
> > +
> > + return 0;
> > +}
> > diff --git a/drivers/media/platform/visconti/hwd_viif_internal.h
> b/drivers/media/platform/visconti/hwd_viif_internal.h
> > new file mode 100644
> > index 00000000000..c954e804946
> > --- /dev/null
> > +++ b/drivers/media/platform/visconti/hwd_viif_internal.h
> > @@ -0,0 +1,340 @@
> > +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
> > +/* Toshiba Visconti Video Capture Support
> > + *
> > + * (C) Copyright 2022 TOSHIBA CORPORATION
> > + * (C) Copyright 2022 Toshiba Electronic Devices & Storage Corporation
> > + */
> > +
> > +#ifndef HWD_VIIF_INTERNAL_H
> > +#define HWD_VIIF_INTERNAL_H
> > +
> > +#include "hwd_viif_reg.h"
> > +
> > +#define HWD_VIIF_CSI2_MAX_VC (3U)
> > +#define HWD_VIIF_CSI2_MIN_DT (0x10U)
> > +#define HWD_VIIF_CSI2_MAX_DT (0x3fU)
> > +#define HWD_VIIF_CSI2_MAX_WORD_COUNT (16384U)
> > +#define HWD_VIIF_CSI2_MAX_PACKET_NUM (8192U)
> > +#define HWD_VIIF_DPHY_MIN_DATA_RATE (80U)
> > +#define HWD_VIIF_DPHY_MAX_DATA_RATE (1500U)
> > +#define HWD_VIIF_DPHY_CFG_CLK_25M (32U)
> > +#define HWD_VIIF_DPHY_TRANSFER_HS_TABLE_NUM (43U)
> > +
> > +/* maximum horizontal/vertical position/dimension of CROP with ISP */
> > +#define HWD_VIIF_CROP_MAX_X_ISP (8062U)
> > +#define HWD_VIIF_CROP_MAX_Y_ISP (3966U)
> > +#define HWD_VIIF_CROP_MAX_W_ISP (8190U)
> > +#define HWD_VIIF_CROP_MAX_H_ISP (4094U)
> > +
> > +/* maximum horizontal/vertical position/dimension of CROP without ISP */
> > +#define HWD_VIIF_CROP_MAX_X (1920U)
> > +#define HWD_VIIF_CROP_MAX_Y (1408U)
> > +#define HWD_VIIF_CROP_MIN_W (128U)
> > +#define HWD_VIIF_CROP_MAX_W (2048U)
> > +#define HWD_VIIF_CROP_MIN_H (128U)
> > +#define HWD_VIIF_CROP_MAX_H (1536U)
> > +
> > +/* pixel clock: [kHz] */
> > +#define HWD_VIIF_MIN_PIXEL_CLOCK (3375U)
> > +#define HWD_VIIF_MAX_PIXEL_CLOCK (600000U)
> > +
> > +/* picture size: [pixel], [ns] */
> > +#define HWD_VIIF_MIN_HTOTAL_PIXEL (143U)
> > +#define HWD_VIIF_MIN_HTOTAL_NSEC (239U)
> > +#define HWD_VIIF_MAX_HTOTAL_PIXEL (65535U)
> > +#define HWD_VIIF_MAX_HTOTAL_NSEC (109225U)
> > +
> > +/* horizontal back porch size: [system clock] */
> > +#define HWD_VIIF_HBP_SYSCLK (10U)
> > +
> > +/* active picture size: [pixel] */
> > +#define HWD_VIIF_MIN_HACTIVE_PIXEL_WO_L1ISP (128U)
> > +#define HWD_VIIF_MAX_HACTIVE_PIXEL_WO_L1ISP (4096U)
> > +#define HWD_VIIF_MIN_HACTIVE_PIXEL_W_L1ISP (640U)
> > +#define HWD_VIIF_MAX_HACTIVE_PIXEL_W_L1ISP (3840U)
> > +
> > +/* picture vertical size: [line], [packet] */
> > +#define HWD_VIIF_MIN_VTOTAL_LINE (144U)
> > +#define HWD_VIIF_MAX_VTOTAL_LINE (16383U)
> > +#define HWD_VIIF_MIN_VBP_LINE (5U)
> > +#define HWD_VIIF_MAX_VBP_LINE (4095U)
> > +#define HWD_VIIF_MIN_VBP_PACKET (5U)
> > +#define HWD_VIIF_MAX_VBP_PACKET (4095U)
> > +#define HWD_VIIF_MIN_VACTIVE_LINE_WO_L1ISP (128U)
> > +#define HWD_VIIF_MAX_VACTIVE_LINE_WO_L1ISP (2160U)
> > +#define HWD_VIIF_MIN_VACTIVE_LINE_W_L1ISP (480U)
> > +#define HWD_VIIF_MAX_VACTIVE_LINE_W_L1ISP (2160U)
> > +
> > +/* image source select */
> > +#define HWD_VIIF_INPUT_CSI2 (0U)
> > +
> > +#define HWD_VIIF_CSC_MAX_OFFSET (0x0001FFFFU)
> > +#define HWD_VIIF_CSC_MAX_COEF_VALUE (0x0000FFFFU)
> > +#define HWD_VIIF_CSC_MAX_COEF_NUM (9U)
> > +#define HWD_VIIF_GAMMA_MAX_VSPLIT (4094U)
> > +#define HWD_VIIF_MTB_CB_YG_COEF_OFFSET (16U)
> > +#define HWD_VIIF_MTB_CR_YG_COEF_OFFSET (0U)
> > +#define HWD_VIIF_MTB_CB_CB_COEF_OFFSET (16U)
> > +#define HWD_VIIF_MTB_CR_CB_COEF_OFFSET (0U)
> > +#define HWD_VIIF_MTB_CB_CR_COEF_OFFSET (16U)
> > +#define HWD_VIIF_MTB_CR_CR_COEF_OFFSET (0U)
> > +#define HWD_VIIF_MAX_PITCH_ISP (32704U)
> > +#define HWD_VIIF_MAX_PITCH (65536U)
> > +
> > +/* size of minimum/maximum input image */
> > +#define HWD_VIIF_MIN_INPUT_IMG_WIDTH (128U)
> > +#define HWD_VIIF_MAX_INPUT_IMG_WIDTH_ISP (4096U)
> > +#define HWD_VIIF_MAX_INPUT_IMG_WIDTH (2048U)
> > +#define HWD_VIIF_MIN_INPUT_IMG_HEIGHT (128U)
> > +#define HWD_VIIF_MAX_INPUT_IMG_HEIGHT_ISP (2160U)
> > +#define HWD_VIIF_MAX_INPUT_IMG_HEIGHT (1536U)
> > +#define HWD_VIIF_MAX_INPUT_LINE_SIZE (16384U)
> > +
> > +/* size of minimum/maximum output image */
> > +#define HWD_VIIF_MIN_OUTPUT_IMG_WIDTH (128U)
> > +#define HWD_VIIF_MAX_OUTPUT_IMG_WIDTH_ISP (5760U)
> > +#define HWD_VIIF_MAX_OUTPUT_IMG_WIDTH_SUB (4096U)
> > +
> > +#define HWD_VIIF_MIN_OUTPUT_IMG_HEIGHT (128U)
> > +#define HWD_VIIF_MAX_OUTPUT_IMG_HEIGHT_ISP (3240U)
> > +#define HWD_VIIF_MAX_OUTPUT_IMG_HEIGHT_SUB (2160U)
> > +
> > +#define HWD_VIIF_NO_EVENT (0x0U)
> > +
> > +/* System clock: [kHz] */
> > +#define HWD_VIIF_SYS_CLK (500000UL)
> > +
> > +/*
> > + * wait time for force abort to complete(max 1line time = 1228.8[us]
> > + * when width = 4096, RAW24, 80Mbps
> > + */
> > +#define HWD_VIIF_WAIT_ABORT_COMPLETE_TIME (1229U)
> > +
> > +/*
> > + * complete time of register buffer transfer.
> > + * actual time is about 30us in case of L1ISP
> > + */
> > +#define HWD_VIIF_WAIT_ISP_REGBF_TRNS_COMPLETE_TIME (39U)
> > +
> > +/* internal operation latencies: [system clock]*/
> > +#define HWD_VIIF_TABLE_LOAD_TIME (24000UL)
> > +#define HWD_VIIF_REGBUF_ACCESS_TIME (15360UL)
> > +
> > +/* offset of Vsync delay: [line] */
> > +#define HWD_VIIF_L1_DELAY_W_HDRC (31U)
> > +#define HWD_VIIF_L1_DELAY_WO_HDRC (11U)
> > +
> > +/* data width is 32bit */
> > +#define HWD_VIIF_VDM_CFG_PARAM (0x00000210U)
> > +
> > +/* vsync mode is pulse */
> > +#define HWD_VIIF_DPGM_VSYNC_PULSE (1U)
> > +
> > +/* Vlatch mask bit for L1ISP and L2ISP */
> > +#define HWD_VIIF_ISP_VLATCH_MASK (2U)
> > +
> > +/* Register buffer */
> > +#define HWD_VIIF_ISP_MAX_CONTEXT_NUM (4U)
> > +#define HWD_VIIF_ISP_REGBUF_MODE_BYPASS (0U)
> > +#define HWD_VIIF_ISP_REGBUF_MODE_BUFFER (1U)
> > +#define HWD_VIIF_ISP_REGBUF_READ (1U)
> > +
> > +/* constants for L1 ISP*/
> > +#define HWD_VIIF_L1_INPUT_MODE_NUM (5U)
> > +#define HWD_VIIF_L1_INPUT_DEPTH_MIN (8U)
> > +#define HWD_VIIF_L1_INPUT_DEPTH_MAX (24U)
> > +#define HWD_VIIF_L1_INPUT_DEPTH_SDR_MAX
> (12U)
> > +#define HWD_VIIF_L1_INPUT_DEPTH_PWL_MAX
> (14U)
> > +#define HWD_VIIF_L1_RAW_MODE_NUM (4U)
> > +#define HWD_VIIF_L1_INPUT_NUM_MIN (1U)
> > +#define HWD_VIIF_L1_INPUT_NUM_MAX (3U)
> > +#define HWD_VIIF_L1_AG_ID_NUM (4U)
> > +#define HWD_VIIF_L1_SENSITIVITY_IMAGE_NUM (3U)
> > +#define HWD_VIIF_L1_HDRE_MAX_KNEEPOINT_VAL (0x3fffU)
> > +#define HWD_VIIF_L1_HDRE_MAX_HDRE_SIG_VAL (0xffffffU)
> > +#define HWD_VIIF_L1_HDRE_MAX_OUT_PIXEL_RATIO
> (0x400000U)
> > +#define HWD_VIIF_L1_HDRE_MAX_OUT_PIXEL_VAL (0xffffffU)
> > +#define HWD_VIIF_L1_OBCC_MAX_AG_VAL (511U)
> > +#define HWD_VIIF_L1_IMG_EXTRACT_MAX_BLACK_LEVEL_VAL
> (0xffffffU)
> > +#define HWD_VIIF_L1_DPC_MAX_RATIO_LIMIT_VAL (1023U)
> > +#define HWD_VIIF_L1_DPC_MIN_LUMA_ADJ_VAL (1U)
> > +#define HWD_VIIF_L1_DPC_MAX_LUMA_ADJ_VAL (31U)
> > +#define HWD_VIIF_L1_VDM_ALIGN (0x8U) /*
> port interface width is 64bit */
> > +#define HWD_VIIF_L1_VDM_CFG_PARAM
> (0x00000310U) /* data width is 64bit */
> > +#define HWD_VIIF_L1_VDM_SRAM_BASE
> (0x00000600U)
> > +#define HWD_VIIF_L1_VDM_SRAM_SIZE
> (0x00000020U)
> > +#define HWD_VIIF_L1_VDM_DPC_TABLE_SIZE
> (0x2000U)
> > +#define HWD_VIIF_L1_VDM_LSC_TABLE_SIZE
> (0x600U)
> > +#define HWD_VIIF_L1_PWHB_MAX_OUT_PIXEL_VAL (4095U)
> > +#define HWD_VIIF_L1_PWHB_MAX_GAIN_VAL
> (0x80000U)
> > +#define HWD_VIIF_L1_RCNR_MAX_DARK_ADJUSTMENT_VAL
> (63U)
> > +#define HWD_VIIF_L1_RCNR_MAX_LUMA_LINKAGE_ADJUSTMENT_VAL
> (31U)
> > +#define HWD_VIIF_L1_RCNR_MAX_ADJUSTMENT_GAIN_VAL (3U)
> > +#define HWD_VIIF_L1_RCNR_MAX_ZERO_CLIP_VAL (256U)
> > +#define HWD_VIIF_L1_RCNR_MAX_BLEND_VAL
> (16U)
> > +#define HWD_VIIF_L1_RCNR_MAX_BLACK_LEVEL_VAL
> (64U)
> > +#define HWD_VIIF_L1_RCNR_MIN_0DIV_GUARD_VAL (4U)
> > +#define HWD_VIIF_L1_RCNR_MAX_0DIV_GUARD_VAL
> (16U)
> > +#define HWD_VIIF_L1_RCNR_MAX_CALC_MSF_NOISE_MULTI_VAL
> (32U)
> > +#define HWD_VIIF_L1_RCNR_MAX_GEN_LUMA_SIG_BLEND_VAL
> (2U)
> > +#define HWD_VIIF_L1_RCNR_MAX_UP_LIMIT_GRGB_SENS_RATIO
> (15U)
> > +#define HWD_VIIF_L1_HDRS_MIN_BLEND_RATIO (0x400U)
> > +#define HWD_VIIF_L1_HDRS_MAX_BLEND_RATIO
> (0x400000U)
> > +#define HWD_VIIF_L1_HDRS_MAX_DIGITAL_GAIN_VAL
> (0x400000U)
> > +#define HWD_VIIF_L1_HDRS_MAX_DST_MAX_VAL (0xffffffU)
> > +#define HWD_VIIF_L1_HDRS_MAX_BLEND_PIX_VAL (4095U)
> > +#define HWD_VIIF_L1_BLACK_LEVEL_MAX_VAL
> (0xffffffU)
> > +#define HWD_VIIF_L1_BLACK_LEVEL_MAX_GAIN_VAL
> (0x100000U)
> > +#define HWD_VIIF_L1_BLACK_LEVEL_MAX_DST_VAL
> (0xffffffU)
> > +#define HWD_VIIF_LSC_MIN_GAIN (-4096)
> > +#define HWD_VIIF_LSC_MAX_GAIN (4096)
> > +#define HWD_VIIF_LSC_GRID_MIN_COORDINATE (1U)
> > +#define HWD_VIIF_LSC_PWB_MAX_COEF_VAL
> (0x800U)
> > +#define HWD_VIIF_DAMP_MAX_LSBSEL (15U)
> > +#define HWD_VIIF_MAIN_PROCESS_MAX_OUT_PIXEL_VAL
> (0xffffffU)
> > +#define HWD_VIIF_AWB_MIN_GAIN (64U)
> > +#define HWD_VIIF_AWB_MAX_GAIN (1024U)
> > +#define HWD_VIIF_AWB_GATE_LOWER
> (-127)
> > +#define HWD_VIIF_AWB_GATE_UPPER
> (127)
> > +#define HWD_VIIF_AWB_UNSIGNED_GATE_UPPER (127U)
> > +#define HWD_VIIF_AWB_MAX_UV_CONVERGENCE_SPEED
> (15U)
> > +#define HWD_VIIF_AWB_MAX_UV_CONVERGENCE_LEVEL
> (31U)
> > +#define HWD_VIIF_AWB_INTEGRATION_STOP_TH (1023U)
> > +#define HWD_VIIF_L1_HDRC_MAX_THROUGH_SHIFT_VAL
> (8U)
> > +#define HWD_VIIF_L1_HDRC_MIN_INPUT_DATA_WIDTH
> (10U)
> > +#define HWD_VIIF_L1_HDRC_MAX_INPUT_DATA_WIDTH
> (24U)
> > +#define HWD_VIIF_L1_HDRC_MAX_PT_SLOPE
> (13U)
> > +#define HWD_VIIF_L1_HDRC_MAX_BLEND_RATIO (256U)
> > +#define HWD_VIIF_L1_HDRC_MAX_FLARE_VAL
> (0xffffffU)
> > +#define HWD_VIIF_L1_HDRC_MAX_BLEND_LUMA
> (16U)
> > +#define HWD_VIIF_L1_HDRC_MAX_LTM_TONE_BLEND_RATIO
> (0x400000U)
> > +#define HWD_VIIF_L1_HDRC_MAX_LTM_MAGNIFICATION
> (0x4000U)
> > +#define HWD_VIIF_L1_HDRC_RATIO_OFFSET
> (10U)
> > +#define HWD_VIIF_L1_GAMMA_MAX_VAL (8191U)
> > +#define HWD_VIIF_L1_SUPPRESSION_MAX_VAL
> (0x4000U)
> > +#define HWD_VIIF_L1_EDGE_SUPPRESSION_MAX_LIMIT
> (15U)
> > +#define HWD_VIIF_L1_COLOR_LEVEL_MAX_GAIN (0x1000U)
> > +#define HWD_VIIF_L1_AEXP_MAX_WEIGHT (3U)
> > +#define HWD_VIIF_L1_AEXP_MAX_BLOCK_TH
> (256U)
> > +#define HWD_VIIF_L1_AEXP_MAX_SATURATION_PIXEL_TH (0xffffffU)
> > +#define HWD_VIIF_L1_AEXP_MIN_BLOCK_WIDTH (64U)
> > +#define HWD_VIIF_L1_AEXP_MIN_BLOCK_HEIGHT (64U)
> > +#define HWD_VIIF_L1_HIST_COLOR_RGBY (2U)
> > +#define HWD_VIIF_L1_HIST_MAX_BLOCK_NUM
> (8U)
> > +#define HWD_VIIF_L1_HIST_MAX_STEP (15U)
> > +#define HWD_VIIF_L1_HIST_MAX_BIN_SHIFT
> (31U)
> > +#define HWD_VIIF_L1_HIST_MAX_COEF (65536U)
> > +#define HWD_VIIF_L1_HIST_MIN_ADD_B_COEF
> (-65536)
> > +#define HWD_VIIF_L1_HIST_MIN_ADD_A_COEF
> (-16777216)
> > +#define HWD_VIIF_L1_HIST_MAX_ADD_A_COEF
> (16777216)
> > +#define HWD_VIIF_L1_HIST_VDM_SIZE (4096U)
> > +#define HWD_VIIF_L1_HIST_VDM_SRAM_BASE
> (0x00000400U)
> > +#define HWD_VIIF_L1_HIST_VDM_SRAM_SIZE
> (0x00000040U)
> > +#define HWD_VIIF_L1_CRGBF_R_START_ADDR_LIMIT
> (0x0200U)
> > +#define HWD_VIIF_L1_CRGBF_R_END_ADDR_LIMIT (0x10BFU)
> > +#define HWD_VIIF_L1_COEF_MIN (256U)
> > +#define HWD_VIIF_L1_COEF_MAX (65024U)
> > +
> > +/* constants for L2 ISP */
> > +#define HWD_VIIF_L2_VDM_ALIGN (0x4U)
> > +#define HWD_VIIF_L2_VDM_GRID_SRAM_BASE
> (0x00000620U)
> > +#define HWD_VIIF_L2_VDM_GRID_SRAM_SIZE
> (0x00000020U)
> > +#define HWD_VIIF_L2_VDM_GAMMA_SRAM_BASE
> (0x00000640U)
> > +#define HWD_VIIF_L2_VDM_GAMMA_SRAM_SIZE
> (0x00000020U)
> > +#define HWD_VIIF_L2_VDM_GAMMA_TABLE_SIZE (0x00000200U)
> > +#define HWD_VIIF_L2_UNDIST_POLY_NUM (11U)
> > +#define HWD_VIIF_L2_UNDIST_MIN_SENSOR_CROP_OFS_H (-4296)
> > +#define HWD_VIIF_L2_UNDIST_MAX_SENSOR_CROP_OFS_H (4296)
> > +#define HWD_VIIF_L2_UNDIST_MIN_SENSOR_CROP_OFS_V (-2360)
> > +#define HWD_VIIF_L2_UNDIST_MAX_SENSOR_CROP_OFS_V (2360)
> > +#define HWD_VIIF_L2_UNDIST_MAX_NORM_SCALE (1677721U)
> > +#define HWD_VIIF_L2_UNDIST_MAX_VALID_R_NORM2
> (0x4000000U)
> > +#define HWD_VIIF_L2_UNDIST_MAX_ROI_WRITE_AREA_DELTA
> (0x800U)
> > +#define HWD_VIIF_L2_UNDIST_MIN_POLY_COEF (-2147352576)
> > +#define HWD_VIIF_L2_UNDIST_MAX_POLY_COEF (2147352576)
> > +#define HWD_VIIF_L2_UNDIST_MIN_GRID_NUM (16U)
> > +#define HWD_VIIF_L2_UNDIST_MAX_GRID_NUM (64U)
> > +#define HWD_VIIF_L2_UNDIST_MAX_GRID_TOTAL_NUM
> (2048U)
> > +#define HWD_VIIF_L2_UNDIST_MAX_GRID_PATCH_SIZE_INV
> (0x800000U)
> > +#define HWD_VIIF_L2_UNDIST_MIN_TABLE_SIZE (0x400U)
> > +#define HWD_VIIF_L2_UNDIST_MAX_TABLE_SIZE (0x2000U)
> > +#define HWD_VIIF_L2_ROI_MIN_NUM (1U)
> > +#define HWD_VIIF_L2_ROI_MAX_NUM (2U)
> > +#define HWD_VIIF_L2_ROI_MIN_SCALE (32768U)
> > +#define HWD_VIIF_L2_ROI_MAX_SCALE (131072U)
> > +#define HWD_VIIF_L2_ROI_MIN_SCALE_INV (32768U)
> > +#define HWD_VIIF_L2_ROI_MAX_SCALE_INV (131072U)
> > +#define HWD_VIIF_L2_ROI_MIN_CORRECTED_WO_SCALE_HSIZE (128U)
> > +#define HWD_VIIF_L2_ROI_MAX_CORRECTED_WO_SCALE_HSIZE
> (8190U)
> > +#define HWD_VIIF_L2_ROI_MIN_CORRECTED_WO_SCALE_VSIZE (128U)
> > +#define HWD_VIIF_L2_ROI_MAX_CORRECTED_WO_SCALE_VSIZE (4094U)
> > +#define HWD_VIIF_L2_ROI_MIN_CORRECTED_HSIZE (128U)
> > +#define HWD_VIIF_L2_ROI_MAX_CORRECTED_HSIZE (8190U)
> > +#define HWD_VIIF_L2_ROI_MIN_CORRECTED_VSIZE (128U)
> > +#define HWD_VIIF_L2_ROI_MAX_CORRECTED_VSIZE (4094U)
> > +#define HWD_VIIF_L2_CRGBF_R_START_ADDR_LIMIT
> (0x1CU)
> > +#define HWD_VIIF_L2_CRGBF_R_END_ADDR_LIMIT (0x1FU)
> > +#define HWD_VIIF_L2_ROI_NONE (3U)
> > +#define HWD_VIIF_MAX_POST_NUM (2U)
> > +#define HWD_VIIF_L2_INPUT_OTHER_CH (0x50U)
> > +
> > +/**
> > + * struct hwd_viif_l2_roi_path_info - L2ISP ROI path control information
> > + *
> > + * @roi_num: the number of ROIs which are used.
> > + * @post_enable_flag: flag to show which of POST is enabled.
> > + * @post_crop_x: CROP x of each L2ISP POST
> > + * @post_crop_y: CROP y of each L2ISP POST
> > + * @post_crop_w: CROP w of each L2ISP POST
> > + * @post_crop_h: CROP h of each L2ISP POST
> > + */
> > +struct hwd_viif_l2_roi_path_info {
> > + u32 roi_num;
> > + bool post_enable_flag[HWD_VIIF_MAX_POST_NUM];
> > + u32 post_crop_x[HWD_VIIF_MAX_POST_NUM];
> > + u32 post_crop_y[HWD_VIIF_MAX_POST_NUM];
> > + u32 post_crop_w[HWD_VIIF_MAX_POST_NUM];
> > + u32 post_crop_h[HWD_VIIF_MAX_POST_NUM];
> > +};
> > +
> > +/**
> > + * struct hwd_viif_res - driver internal resource structure
> > + *
> > + * @clock_id: clock ID of each unit
> > + * @csi2_clock_id: clock ID of CSI-2 RX
> > + * @csi2_reset_id: reset ID of CSI-2 RX
> > + * @pixel_clock: pixel clock
> > + * @htotal_size: horizontal total size
> > + * @dt_image_main_w_isp: Data type of image data for ISP path
> > + * @csi2host_reg: pointer to register access structure of CSI-2 RX host
> controller
> > + * @capture_reg: pointer to register access structure of capture unit
> > + * @l2_roi_path_info: ROI path information of L2ISP
> > + * @run_flag_main: run flag of MAIN unit(true: run, false: not run)
> > + */
> > +struct hwd_viif_res {
> > + //u32 clock_id;
> > + //u32 csi2_clock_id;
> > + //u32 csi2_reset_id;
>
> Please remove these if they're not needed.

I'll remove them.

> > + u32 pixel_clock;
> > + u32 htotal_size;
> > + u32 dt_image_main_w_isp;
> > + struct hwd_viif_csi2host_reg *csi2host_reg;
> > + struct hwd_viif_capture_reg *capture_reg;
> > + struct hwd_viif_l2_roi_path_info l2_roi_path_info;
> > + bool run_flag_main;
> > +};
> > +
> > +/**
> > + * struct hwd_viif_dphy_hs_info - dphy hs information
> > + *
> > + * @rate: Data rate [Mbps]
> > + * @hsfreqrange: IP operating frequency(hsfreqrange)
> > + * @osc_freq_target: DDL target oscillation frequency(osc_freq_target)
> > + */
> > +struct hwd_viif_dphy_hs_info {
> > + u32 rate;
> > + u32 hsfreqrange;
> > + u32 osc_freq_target;
> > +};
> > +
> > +#endif /* HWD_VIIF_INTERNAL_H */
> > diff --git a/drivers/media/platform/visconti/hwd_viif_reg.h
> b/drivers/media/platform/visconti/hwd_viif_reg.h
> > new file mode 100644
> > index 00000000000..b7f43c5fe95
> > --- /dev/null
> > +++ b/drivers/media/platform/visconti/hwd_viif_reg.h
> > @@ -0,0 +1,2802 @@
> > +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
> > +/* Toshiba Visconti Video Capture Support
> > + *
> > + * (C) Copyright 2022 TOSHIBA CORPORATION
> > + * (C) Copyright 2022 Toshiba Electronic Devices & Storage Corporation
> > + */
> > +
> > +#ifndef HWD_VIIF_REG_H
> > +#define HWD_VIIF_REG_H
> > +
> > +/**
> > + * struct hwd_viif_csi2host_reg - Registers for VIIF CSI2HOST control
> > + */
> > +struct hwd_viif_csi2host_reg {
> > + u32 RESERVED_A_1;
> > + u32 CSI2RX_NLANES;
> > + u32 CSI2RX_RESETN;
> > + u32 CSI2RX_INT_ST_MAIN;
> > + u32 CSI2RX_DATA_IDS_1;
> > + u32 CSI2RX_DATA_IDS_2;
> > + u32 RESERVED_B_1[10];
> > + u32 CSI2RX_PHY_SHUTDOWNZ;
> > + u32 CSI2RX_PHY_RSTZ;
> > + u32 CSI2RX_PHY_RX;
> > + u32 CSI2RX_PHY_STOPSTATE;
> > + u32 CSI2RX_PHY_TESTCTRL0;
> > + u32 CSI2RX_PHY_TESTCTRL1;
> > + u32 RESERVED_B_2[34];
> > + u32 CSI2RX_INT_ST_PHY_FATAL;
> > + u32 CSI2RX_INT_MSK_PHY_FATAL;
> > + u32 CSI2RX_INT_FORCE_PHY_FATAL;
> > + u32 RESERVED_B_3[1];
> > + u32 CSI2RX_INT_ST_PKT_FATAL;
> > + u32 CSI2RX_INT_MSK_PKT_FATAL;
> > + u32 CSI2RX_INT_FORCE_PKT_FATAL;
> > + u32 RESERVED_B_4[1];
> > + u32 CSI2RX_INT_ST_FRAME_FATAL;
> > + u32 CSI2RX_INT_MSK_FRAME_FATAL;
> > + u32 CSI2RX_INT_FORCE_FRAME_FATAL;
> > + u32 RESERVED_B_5[1];
> > + u32 CSI2RX_INT_ST_PHY;
> > + u32 CSI2RX_INT_MSK_PHY;
> > + u32 CSI2RX_INT_FORCE_PHY;
> > + u32 RESERVED_B_6[1];
> > + u32 CSI2RX_INT_ST_PKT;
> > + u32 CSI2RX_INT_MSK_PKT;
> > + u32 CSI2RX_INT_FORCE_PKT;
> > + u32 RESERVED_B_7[1];
> > + u32 CSI2RX_INT_ST_LINE;
> > + u32 CSI2RX_INT_MSK_LINE;
> > + u32 CSI2RX_INT_FORCE_LINE;
> > + u32 RESERVED_B_8[113];
> > + u32 RESERVED_A_2;
> > + u32 RESERVED_A_3;
> > + u32 RESERVED_A_4;
> > + u32 RESERVED_A_5;
> > + u32 RESERVED_A_6;
> > + u32 RESERVED_B_9[58];
> > + u32 RESERVED_A_7;
>
> These should be lower case, they're struct members.
>
> This way of defining a hardware register interface is highly
> unconventional. I'm not saying no to it, not now at least, but something
> should be done to make this more robust against accidental changes: adding
> a field in the middle changes the address of anything that comes after it,
> and it's really difficult to say from the code alone that the address of a
> given register is what it's intended to be. Maybe pahole would still help?
> But some documentation would be needed in that case.
>
> I wonder what others think.

I understand the risk.
I'll remove these struct-style definition and introduce macro style definition.
I've hesitated this migration simply because it seemed difficult to complete without any defects
especially on calculating the offset of each member.
I try find a series of operations that will complete the migration safely.

> > +};
> > +

snip

>
> --
> Kind regards,
>
> Sakari Ailus

Regards,

Yuji Ishikawa