linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Robert Foss <robert.foss@linaro.org>
To: Andrey Konovalov <andrey.konovalov@linaro.org>
Cc: Andy Gross <agross@kernel.org>,
	Bjorn Andersson <bjorn.andersson@linaro.org>,
	Todor Tomov <todor.too@gmail.com>,
	Mauro Carvalho Chehab <mchehab@kernel.org>,
	Rob Herring <robh+dt@kernel.org>,
	angelogioacchino.delregno@somainline.org,
	MSM <linux-arm-msm@vger.kernel.org>,
	linux-media <linux-media@vger.kernel.org>,
	"open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" 
	<devicetree@vger.kernel.org>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	AngeloGioacchino Del Regno <kholk11@gmail.com>,
	Tomasz Figa <tfiga@chromium.org>,
	Azam Sadiq Pasha Kapatrala Syed <akapatra@quicinc.com>,
	Sarvesh Sridutt <Sarvesh.Sridutt@smartwirelesscompute.com>,
	Jonathan Marek <jonathan@marek.ca>,
	Sakari Ailus <sakari.ailus@iki.fi>
Subject: Re: [PATCH v5 09/22] media: camss: Refactor CSID HW version support
Date: Mon, 22 Feb 2021 19:13:52 +0100	[thread overview]
Message-ID: <CAG3jFyvZKTcFWBaRT9j36mEMHqKSW9Q5Opn51vpZ_Ve1ndt24A@mail.gmail.com> (raw)
In-Reply-To: <9b425e95-cbf2-1fd7-50b3-c1278b003522@linaro.org>

On Sun, 21 Feb 2021 at 18:50, Andrey Konovalov
<andrey.konovalov@linaro.org> wrote:
>
> Hi Robert,
>
> After reviewing the [PATCH v5 10/22], I noticed that this patch also
> has a problematic test_pattern control implementation.
>
> See below.
>
> On 21.02.2021 18:15, Andrey Konovalov wrote:
> > Hi Robert,
> >
> > Thank you for your patch!
> >
> > Reviewed-by: Andrey Konovalov <andrey.konovalov@linaro.org>
> >
> > Thanks,
> > Andrey
> >
> > On 17.02.2021 14:21, Robert Foss wrote:
> >> In order to support Qualcomm ISP hardware architectures that diverge
> >> from older architectures, the CSID subdevice drivers needs to be refactored
> >> to better abstract the different ISP hardware architectures.
> >>
> >> Signed-off-by: Robert Foss <robert.foss@linaro.org>
> >> ---
> >>
> >> Changes since v1
> >>   - kernel test robot: Add missing include, interrupt.h
> >>
> >> Changes since v4
> >>   - Andrey: Removed whitespace from some includes
> >>   - Andrey: Removed unused enum
> >>
> >>
> >>   drivers/media/platform/qcom/camss/Makefile    |   2 +
> >>   .../platform/qcom/camss/camss-csid-4-1.c      | 330 ++++++++++
> >>   .../platform/qcom/camss/camss-csid-4-7.c      | 406 ++++++++++++
> >>   .../media/platform/qcom/camss/camss-csid.c    | 616 +-----------------
> >>   .../media/platform/qcom/camss/camss-csid.h    | 126 +++-
> >>   5 files changed, 890 insertions(+), 590 deletions(-)
> >>   create mode 100644 drivers/media/platform/qcom/camss/camss-csid-4-1.c
> >>   create mode 100644 drivers/media/platform/qcom/camss/camss-csid-4-7.c
> >>
> >> diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile
> >> index 052c4f405fa3..cff388b653ba 100644
> >> --- a/drivers/media/platform/qcom/camss/Makefile
> >> +++ b/drivers/media/platform/qcom/camss/Makefile
> >> @@ -4,6 +4,8 @@
> >>   qcom-camss-objs += \
> >>           camss.o \
> >>           camss-csid.o \
> >> +        camss-csid-4-1.o \
> >> +        camss-csid-4-7.o \
> >>           camss-csiphy-2ph-1-0.o \
> >>           camss-csiphy-3ph-1-0.o \
> >>           camss-csiphy.o \
> >> diff --git a/drivers/media/platform/qcom/camss/camss-csid-4-1.c b/drivers/media/platform/qcom/camss/camss-csid-4-1.c
> >> new file mode 100644
> >> index 000000000000..c92077a7f758
> >> --- /dev/null
> >> +++ b/drivers/media/platform/qcom/camss/camss-csid-4-1.c
> >> @@ -0,0 +1,330 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * camss-csid-4-1.c
> >> + *
> >> + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module
> >> + *
> >> + * Copyright (C) 2020 Linaro Ltd.
> >> + */
> >> +
> >> +#include <linux/completion.h>
> >> +#include <linux/interrupt.h>
> >> +#include <linux/io.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/of.h>
> >> +
> >> +#include "camss-csid.h"
> >> +#include "camss.h"
> >> +
> >> +#define CAMSS_CSID_HW_VERSION        0x0
> >> +#define CAMSS_CSID_CORE_CTRL_0        0x004
> >> +#define CAMSS_CSID_CORE_CTRL_1        0x008
> >> +#define CAMSS_CSID_RST_CMD        0x00c
> >> +#define CAMSS_CSID_CID_LUT_VC_n(n)    (0x010 + 0x4 * (n))
> >> +#define CAMSS_CSID_CID_n_CFG(n)        (0x020 + 0x4 * (n))
> >> +#define CAMSS_CSID_CID_n_CFG_ISPIF_EN    BIT(0)
> >> +#define CAMSS_CSID_CID_n_CFG_RDI_EN    BIT(1)
> >> +#define CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT    4
> >> +#define CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_8        (0 << 8)
> >> +#define CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_16        (1 << 8)
> >> +#define CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_LSB    (0 << 9)
> >> +#define CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_MSB    (1 << 9)
> >> +#define CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP        (0 << 10)
> >> +#define CAMSS_CSID_CID_n_CFG_RDI_MODE_PLAIN_PACKING    (1 << 10)
> >> +#define CAMSS_CSID_IRQ_CLEAR_CMD    0x060
> >> +#define CAMSS_CSID_IRQ_MASK        0x064
> >> +#define CAMSS_CSID_IRQ_STATUS        0x068
> >> +#define CAMSS_CSID_TG_CTRL        0x0a0
> >> +#define CAMSS_CSID_TG_CTRL_DISABLE    0xa06436
> >> +#define CAMSS_CSID_TG_CTRL_ENABLE    0xa06437
> >> +#define CAMSS_CSID_TG_VC_CFG        0x0a4
> >> +#define CAMSS_CSID_TG_VC_CFG_H_BLANKING        0x3ff
> >> +#define CAMSS_CSID_TG_VC_CFG_V_BLANKING        0x7f
> >> +#define CAMSS_CSID_TG_DT_n_CGG_0(n)    (0x0ac + 0xc * (n))
> >> +#define CAMSS_CSID_TG_DT_n_CGG_1(n)    (0x0b0 + 0xc * (n))
> >> +#define CAMSS_CSID_TG_DT_n_CGG_2(n)    (0x0b4 + 0xc * (n))
> >> +
> >> +
> >> +static const struct csid_format csid_formats[] = {
> >> +    {
> >> +        MEDIA_BUS_FMT_UYVY8_2X8,
> >> +        DATA_TYPE_YUV422_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        2,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_VYUY8_2X8,
> >> +        DATA_TYPE_YUV422_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        2,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_YUYV8_2X8,
> >> +        DATA_TYPE_YUV422_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        2,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_YVYU8_2X8,
> >> +        DATA_TYPE_YUV422_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        2,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SBGGR8_1X8,
> >> +        DATA_TYPE_RAW_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGBRG8_1X8,
> >> +        DATA_TYPE_RAW_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGRBG8_1X8,
> >> +        DATA_TYPE_RAW_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SRGGB8_1X8,
> >> +        DATA_TYPE_RAW_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SBGGR10_1X10,
> >> +        DATA_TYPE_RAW_10BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> +        10,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGBRG10_1X10,
> >> +        DATA_TYPE_RAW_10BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> +        10,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGRBG10_1X10,
> >> +        DATA_TYPE_RAW_10BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> +        10,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SRGGB10_1X10,
> >> +        DATA_TYPE_RAW_10BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> +        10,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SBGGR12_1X12,
> >> +        DATA_TYPE_RAW_12BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> +        12,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGBRG12_1X12,
> >> +        DATA_TYPE_RAW_12BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> +        12,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGRBG12_1X12,
> >> +        DATA_TYPE_RAW_12BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> +        12,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SRGGB12_1X12,
> >> +        DATA_TYPE_RAW_12BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> +        12,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_Y10_1X10,
> >> +        DATA_TYPE_RAW_10BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> +        10,
> >> +        1,
> >> +    },
> >> +};
> >> +
> >> +static void csid_configure_stream(struct csid_device *csid, u8 enable)
> >> +{
> >> +    struct csid_testgen_config *tg = &csid->testgen;
> >> +    u32 val;
> >> +
> >> +    if (enable) {
> >> +        struct v4l2_mbus_framefmt *input_format;
> >> +        const struct csid_format *format;
> >> +        u8 vc = 0; /* Virtual Channel 0 */
> >> +        u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */
> >> +        u8 dt_shift;
> >> +
> >> +        if (tg->enabled) {
> >> +            /* Config Test Generator */
> >> +            u32 num_lines, num_bytes_per_line;
> >> +
> >> +            input_format = &csid->fmt[MSM_CSID_PAD_SRC];
> >> +            format = csid_get_fmt_entry(csid->formats, csid->nformats,
> >> +                            input_format->code);
> >> +            num_bytes_per_line = input_format->width * format->bpp * format->spp / 8;
> >> +            num_lines = input_format->height;
> >> +
> >> +            /* 31:24 V blank, 23:13 H blank, 3:2 num of active DT */
> >> +            /* 1:0 VC */
> >> +            val = ((CAMSS_CSID_TG_VC_CFG_V_BLANKING & 0xff) << 24) |
> >> +                  ((CAMSS_CSID_TG_VC_CFG_H_BLANKING & 0x7ff) << 13);
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_VC_CFG);
> >> +
> >> +            /* 28:16 bytes per lines, 12:0 num of lines */
> >> +            val = ((num_bytes_per_line & 0x1fff) << 16) |
> >> +                  (num_lines & 0x1fff);
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_0(0));
> >> +
> >> +            /* 5:0 data type */
> >> +            val = format->data_type;
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_1(0));
> >> +
> >> +            /* 2:0 output test pattern */
> >> +            val = tg->mode;
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_2(0));
> >> +        } else {
> >> +            struct csid_phy_config *phy = &csid->phy;
> >> +
> >> +            input_format = &csid->fmt[MSM_CSID_PAD_SINK];
> >> +            format = csid_get_fmt_entry(csid->formats, csid->nformats,
> >> +                            input_format->code);
> >> +
> >> +            val = phy->lane_cnt - 1;
> >> +            val |= phy->lane_assign << 4;
> >> +
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_CORE_CTRL_0);
> >> +
> >> +            val = phy->csiphy_id << 17;
> >> +            val |= 0x9;
> >> +
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_CORE_CTRL_1);
> >> +        }
> >> +
> >> +        /* Config LUT */
> >> +
> >> +        dt_shift = (cid % 4) * 8;
> >> +        val = readl_relaxed(csid->base + CAMSS_CSID_CID_LUT_VC_n(vc));
> >> +        val &= ~(0xff << dt_shift);
> >> +        val |= format->data_type << dt_shift;
> >> +        writel_relaxed(val, csid->base + CAMSS_CSID_CID_LUT_VC_n(vc));
> >> +
> >> +        val = CAMSS_CSID_CID_n_CFG_ISPIF_EN;
> >> +        val |= CAMSS_CSID_CID_n_CFG_RDI_EN;
> >> +        val |= format->decode_format << CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT;
> >> +        val |= CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP;
> >> +        writel_relaxed(val, csid->base + CAMSS_CSID_CID_n_CFG(cid));
> >> +
> >> +        if (tg->enabled) {
> >> +            val = CAMSS_CSID_TG_CTRL_ENABLE;
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_CTRL);
> >> +        }
> >> +    } else {
> >> +        if (tg->enabled) {
> >> +            val = CAMSS_CSID_TG_CTRL_DISABLE;
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_CTRL);
> >> +        }
> >> +    }
> >> +}
> >> +
> >> +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
> >> +{
> >> +    s32 regval = val - 1;
> >> +
> >> +    if (regval > 0 || regval <= CSID_PAYLOAD_MODE_MAX_SUPPORTED_4_1)
> >> +        csid->testgen.mode = regval;
>
> regval of 0 is the valid "Incrementing" test pattern. The condition above
> should be "regval >= 0", not "regval > 0".

Ack

>
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static u32 csid_hw_version(struct csid_device *csid)
> >> +{
> >> +    u32 hw_version = readl_relaxed(csid->base + CAMSS_CSID_HW_VERSION);
> >> +
> >> +    dev_dbg(csid->camss->dev, "CSID HW Version = 0x%08x\n", hw_version);
> >> +
> >> +    return hw_version;
> >> +}
> >> +
> >> +static irqreturn_t csid_isr(int irq, void *dev)
> >> +{
> >> +    struct csid_device *csid = dev;
> >> +    u32 value;
> >> +
> >> +    value = readl_relaxed(csid->base + CAMSS_CSID_IRQ_STATUS);
> >> +    writel_relaxed(value, csid->base + CAMSS_CSID_IRQ_CLEAR_CMD);
> >> +
> >> +    if ((value >> 11) & 0x1)
> >> +        complete(&csid->reset_complete);
> >> +
> >> +    return IRQ_HANDLED;
> >> +}
> >> +
> >> +static int csid_reset(struct csid_device *csid)
> >> +{
> >> +    unsigned long time;
> >> +
> >> +    reinit_completion(&csid->reset_complete);
> >> +
> >> +    writel_relaxed(0x7fff, csid->base + CAMSS_CSID_RST_CMD);
> >> +
> >> +    time = wait_for_completion_timeout(&csid->reset_complete,
> >> +        msecs_to_jiffies(CSID_RESET_TIMEOUT_MS));
> >> +    if (!time) {
> >> +        dev_err(csid->camss->dev, "CSID reset timeout\n");
> >> +        return -EIO;
> >> +    }
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code,
> >> +                 unsigned int match_format_idx, u32 match_code)
> >> +{
> >> +    if (match_format_idx > 0)
> >> +        return 0;
> >> +
> >> +    return sink_code;
> >> +}
> >> +
> >> +static void csid_subdev_init(struct csid_device *csid)
> >> +{
> >> +    csid->formats = csid_formats;
> >> +    csid->nformats = ARRAY_SIZE(csid_formats);
> >> +    csid->testgen.modes = csid_testgen_modes;
> >> +    csid->testgen.nmodes = CSID_PAYLOAD_MODE_MAX_SUPPORTED_4_1;
> >> +}
> >> +
> >> +const struct csid_hw_ops csid_ops_4_1 = {
> >> +    .configure_stream = csid_configure_stream,
> >> +    .configure_testgen_pattern = csid_configure_testgen_pattern,
> >> +    .hw_version = csid_hw_version,
> >> +    .isr = csid_isr,
> >> +    .reset = csid_reset,
> >> +    .src_pad_code = csid_src_pad_code,
> >> +    .subdev_init = csid_subdev_init,
> >> +};
> >> diff --git a/drivers/media/platform/qcom/camss/camss-csid-4-7.c b/drivers/media/platform/qcom/camss/camss-csid-4-7.c
> >> new file mode 100644
> >> index 000000000000..16a69b140f4e
> >> --- /dev/null
> >> +++ b/drivers/media/platform/qcom/camss/camss-csid-4-7.c
> >> @@ -0,0 +1,406 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * camss-csid-4-7.c
> >> + *
> >> + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module
> >> + *
> >> + * Copyright (C) 2020 Linaro Ltd.
> >> + */
> >> +#include <linux/completion.h>
> >> +#include <linux/interrupt.h>
> >> +#include <linux/io.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/of.h>
> >> +
> >> +#include "camss-csid.h"
> >> +#include "camss.h"
> >> +
> >> +#define CAMSS_CSID_HW_VERSION        0x0
> >> +#define CAMSS_CSID_CORE_CTRL_0        0x004
> >> +#define CAMSS_CSID_CORE_CTRL_1        0x008
> >> +#define CAMSS_CSID_RST_CMD        0x010
> >> +#define CAMSS_CSID_CID_LUT_VC_n(n)    (0x014 + 0x4 * (n))
> >> +#define CAMSS_CSID_CID_n_CFG(n)        (0x024 + 0x4 * (n))
> >> +#define CAMSS_CSID_CID_n_CFG_ISPIF_EN    BIT(0)
> >> +#define CAMSS_CSID_CID_n_CFG_RDI_EN    BIT(1)
> >> +#define CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT    4
> >> +#define CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_8        (0 << 8)
> >> +#define CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_16        (1 << 8)
> >> +#define CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_LSB    (0 << 9)
> >> +#define CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_MSB    (1 << 9)
> >> +#define CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP        (0 << 10)
> >> +#define CAMSS_CSID_CID_n_CFG_RDI_MODE_PLAIN_PACKING    (1 << 10)
> >> +#define CAMSS_CSID_IRQ_CLEAR_CMD    0x064
> >> +#define CAMSS_CSID_IRQ_MASK        0x068
> >> +#define CAMSS_CSID_IRQ_STATUS        0x06c
> >> +#define CAMSS_CSID_TG_CTRL        0x0a8
> >> +#define CAMSS_CSID_TG_CTRL_DISABLE    0xa06436
> >> +#define CAMSS_CSID_TG_CTRL_ENABLE    0xa06437
> >> +#define CAMSS_CSID_TG_VC_CFG        0x0ac
> >> +#define CAMSS_CSID_TG_VC_CFG_H_BLANKING        0x3ff
> >> +#define CAMSS_CSID_TG_VC_CFG_V_BLANKING        0x7f
> >> +#define CAMSS_CSID_TG_DT_n_CGG_0(n)    (0x0b4 + 0xc * (n))
> >> +#define CAMSS_CSID_TG_DT_n_CGG_1(n)    (0x0b8 + 0xc * (n))
> >> +#define CAMSS_CSID_TG_DT_n_CGG_2(n)    (0x0bc + 0xc * (n))
> >> +
> >> +
> >> +static const struct csid_format csid_formats[] = {
> >> +    {
> >> +        MEDIA_BUS_FMT_UYVY8_2X8,
> >> +        DATA_TYPE_YUV422_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        2,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_VYUY8_2X8,
> >> +        DATA_TYPE_YUV422_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        2,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_YUYV8_2X8,
> >> +        DATA_TYPE_YUV422_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        2,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_YVYU8_2X8,
> >> +        DATA_TYPE_YUV422_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        2,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SBGGR8_1X8,
> >> +        DATA_TYPE_RAW_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGBRG8_1X8,
> >> +        DATA_TYPE_RAW_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGRBG8_1X8,
> >> +        DATA_TYPE_RAW_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SRGGB8_1X8,
> >> +        DATA_TYPE_RAW_8BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> +        8,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SBGGR10_1X10,
> >> +        DATA_TYPE_RAW_10BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> +        10,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGBRG10_1X10,
> >> +        DATA_TYPE_RAW_10BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> +        10,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGRBG10_1X10,
> >> +        DATA_TYPE_RAW_10BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> +        10,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SRGGB10_1X10,
> >> +        DATA_TYPE_RAW_10BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> +        10,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SBGGR12_1X12,
> >> +        DATA_TYPE_RAW_12BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> +        12,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGBRG12_1X12,
> >> +        DATA_TYPE_RAW_12BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> +        12,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGRBG12_1X12,
> >> +        DATA_TYPE_RAW_12BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> +        12,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SRGGB12_1X12,
> >> +        DATA_TYPE_RAW_12BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> +        12,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SBGGR14_1X14,
> >> +        DATA_TYPE_RAW_14BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_14_BIT,
> >> +        14,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGBRG14_1X14,
> >> +        DATA_TYPE_RAW_14BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_14_BIT,
> >> +        14,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SGRBG14_1X14,
> >> +        DATA_TYPE_RAW_14BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_14_BIT,
> >> +        14,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_SRGGB14_1X14,
> >> +        DATA_TYPE_RAW_14BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_14_BIT,
> >> +        14,
> >> +        1,
> >> +    },
> >> +    {
> >> +        MEDIA_BUS_FMT_Y10_1X10,
> >> +        DATA_TYPE_RAW_10BIT,
> >> +        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> +        10,
> >> +        1,
> >> +    },
> >> +};
> >> +
> >> +static void csid_configure_stream(struct csid_device *csid, u8 enable)
> >> +{
> >> +    struct csid_testgen_config *tg = &csid->testgen;
> >> +    u32 sink_code = csid->fmt[MSM_CSID_PAD_SINK].code;
> >> +    u32 src_code = csid->fmt[MSM_CSID_PAD_SRC].code;
> >> +    u32 val;
> >> +
> >> +    if (enable) {
> >> +        struct v4l2_mbus_framefmt *input_format;
> >> +        const struct csid_format *format;
> >> +        u8 vc = 0; /* Virtual Channel 0 */
> >> +        u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */
> >> +        u8 dt_shift;
> >> +
> >> +        if (tg->enabled) {
> >> +            /* Config Test Generator */
> >> +            u32 num_bytes_per_line, num_lines;
> >> +
> >> +            input_format = &csid->fmt[MSM_CSID_PAD_SRC];
> >> +            format = csid_get_fmt_entry(csid->formats, csid->nformats,
> >> +                            input_format->code);
> >> +            num_bytes_per_line = input_format->width * format->bpp * format->spp / 8;
> >> +            num_lines = input_format->height;
> >> +
> >> +            /* 31:24 V blank, 23:13 H blank, 3:2 num of active DT */
> >> +            /* 1:0 VC */
> >> +            val = ((CAMSS_CSID_TG_VC_CFG_V_BLANKING & 0xff) << 24) |
> >> +                  ((CAMSS_CSID_TG_VC_CFG_H_BLANKING & 0x7ff) << 13);
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_VC_CFG);
> >> +
> >> +            /* 28:16 bytes per lines, 12:0 num of lines */
> >> +            val = ((num_bytes_per_line & 0x1fff) << 16) |
> >> +                  (num_lines & 0x1fff);
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_0(0));
> >> +
> >> +            /* 5:0 data type */
> >> +            val = format->data_type;
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_1(0));
> >> +
> >> +            /* 2:0 output test pattern */
> >> +            val = tg->mode;
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_2(0));
> >> +        } else {
> >> +            struct csid_phy_config *phy = &csid->phy;
> >> +
> >> +            input_format = &csid->fmt[MSM_CSID_PAD_SINK];
> >> +            format = csid_get_fmt_entry(csid->formats, csid->nformats,
> >> +                            input_format->code);
> >> +
> >> +            val = phy->lane_cnt - 1;
> >> +            val |= phy->lane_assign << 4;
> >> +
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_CORE_CTRL_0);
> >> +
> >> +            val = phy->csiphy_id << 17;
> >> +            val |= 0x9;
> >> +
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_CORE_CTRL_1);
> >> +        }
> >> +
> >> +        /* Config LUT */
> >> +
> >> +        dt_shift = (cid % 4) * 8;
> >> +
> >> +        val = readl_relaxed(csid->base + CAMSS_CSID_CID_LUT_VC_n(vc));
> >> +        val &= ~(0xff << dt_shift);
> >> +        val |= format->data_type << dt_shift;
> >> +        writel_relaxed(val, csid->base + CAMSS_CSID_CID_LUT_VC_n(vc));
> >> +
> >> +        val = CAMSS_CSID_CID_n_CFG_ISPIF_EN;
> >> +        val |= CAMSS_CSID_CID_n_CFG_RDI_EN;
> >> +        val |= format->decode_format << CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT;
> >> +        val |= CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP;
> >> +
> >> +        if ((sink_code == MEDIA_BUS_FMT_SBGGR10_1X10 &&
> >> +             src_code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) ||
> >> +            (sink_code == MEDIA_BUS_FMT_Y10_1X10 &&
> >> +             src_code == MEDIA_BUS_FMT_Y10_2X8_PADHI_LE)) {
> >> +            val |= CAMSS_CSID_CID_n_CFG_RDI_MODE_PLAIN_PACKING;
> >> +            val |= CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_16;
> >> +            val |= CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_LSB;
> >> +        }
> >> +
> >> +        writel_relaxed(val, csid->base + CAMSS_CSID_CID_n_CFG(cid));
> >> +
> >> +        if (tg->enabled) {
> >> +            val = CAMSS_CSID_TG_CTRL_ENABLE;
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_CTRL);
> >> +        }
> >> +    } else {
> >> +        if (tg->enabled) {
> >> +            val = CAMSS_CSID_TG_CTRL_DISABLE;
> >> +            writel_relaxed(val, csid->base + CAMSS_CSID_TG_CTRL);
> >> +        }
> >> +    }
> >> +}
> >> +
> >> +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
> >> +{
> >> +    s32 regval = val - 1;
> >> +
> >> +    if (regval > 0 || regval <= CSID_PAYLOAD_MODE_MAX_SUPPORTED_4_7)
> >> +        csid->testgen.mode = regval;
>
> regval of 0 is the valid "Incrementing" test pattern. The condition above
> should be "regval >= 0", not "regval > 0".

Ack

>
> >> +    return 0;
> >> +}
> >> +
> >> +static u32 csid_hw_version(struct csid_device *csid)
> >> +{
> >> +    u32 hw_version = readl_relaxed(csid->base + CAMSS_CSID_HW_VERSION);
> >> +
> >> +    dev_dbg(csid->camss->dev, "CSID HW Version = 0x%08x\n", hw_version);
> >> +
> >> +    return hw_version;
> >> +}
> >> +
> >> +/*
> >> + * isr - CSID module interrupt service routine
> >> + * @irq: Interrupt line
> >> + * @dev: CSID device
> >> + *
> >> + * Return IRQ_HANDLED on success
> >> + */
> >> +static irqreturn_t csid_isr(int irq, void *dev)
> >> +{
> >> +    struct csid_device *csid = dev;
> >> +    u32 value;
> >> +
> >> +    value = readl_relaxed(csid->base + CAMSS_CSID_IRQ_STATUS);
> >> +    writel_relaxed(value, csid->base + CAMSS_CSID_IRQ_CLEAR_CMD);
> >> +
> >> +    if ((value >> 11) & 0x1)
> >> +        complete(&csid->reset_complete);
> >> +
> >> +    return IRQ_HANDLED;
> >> +}
> >> +
> >> +/*
> >> + * csid_reset - Trigger reset on CSID module and wait to complete
> >> + * @csid: CSID device
> >> + *
> >> + * Return 0 on success or a negative error code otherwise
> >> + */
> >> +static int csid_reset(struct csid_device *csid)
> >> +{
> >> +    unsigned long time;
> >> +
> >> +    reinit_completion(&csid->reset_complete);
> >> +
> >> +    writel_relaxed(0x7fff, csid->base + CAMSS_CSID_RST_CMD);
> >> +
> >> +    time = wait_for_completion_timeout(&csid->reset_complete,
> >> +        msecs_to_jiffies(CSID_RESET_TIMEOUT_MS));
> >> +    if (!time) {
> >> +        dev_err(csid->camss->dev, "CSID reset timeout\n");
> >> +        return -EIO;
> >> +    }
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code,
> >> +                 unsigned int match_format_idx, u32 match_code)
> >> +{
> >> +    switch (sink_code) {
> >> +    case MEDIA_BUS_FMT_SBGGR10_1X10:
> >> +    {
> >> +        u32 src_code[] = {
> >> +            MEDIA_BUS_FMT_SBGGR10_1X10,
> >> +            MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,
> >> +        };
> >> +
> >> +        return csid_find_code(src_code, ARRAY_SIZE(src_code),
> >> +                      match_format_idx, match_code);
> >> +    }
> >> +    case MEDIA_BUS_FMT_Y10_1X10:
> >> +    {
> >> +        u32 src_code[] = {
> >> +            MEDIA_BUS_FMT_Y10_1X10,
> >> +            MEDIA_BUS_FMT_Y10_2X8_PADHI_LE,
> >> +        };
> >> +
> >> +        return csid_find_code(src_code, ARRAY_SIZE(src_code),
> >> +                      match_format_idx, match_code);
> >> +    }
> >> +    default:
> >> +        if (match_format_idx > 0)
> >> +            return 0;
> >> +
> >> +        return sink_code;
> >> +    }
> >> +}
> >> +
> >> +static void csid_subdev_init(struct csid_device *csid)
> >> +{
> >> +    csid->formats = csid_formats;
> >> +    csid->nformats = ARRAY_SIZE(csid_formats);
> >> +    csid->testgen.modes = csid_testgen_modes;
> >> +    csid->testgen.nmodes = CSID_PAYLOAD_MODE_MAX_SUPPORTED_4_7;
> >> +}
> >> +
> >> +const struct csid_hw_ops csid_ops_4_7 = {
> >> +    .configure_stream = csid_configure_stream,
> >> +    .configure_testgen_pattern = csid_configure_testgen_pattern,
> >> +    .hw_version = csid_hw_version,
> >> +    .isr = csid_isr,
> >> +    .reset = csid_reset,
> >> +    .src_pad_code = csid_src_pad_code,
> >> +    .subdev_init = csid_subdev_init,
> >> +};
> >> diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c
> >> index be3fe76f3dc3..601bd810f2b0 100644
> >> --- a/drivers/media/platform/qcom/camss/camss-csid.c
> >> +++ b/drivers/media/platform/qcom/camss/camss-csid.c
> >> @@ -26,405 +26,35 @@
> >>   #define MSM_CSID_NAME "msm_csid"
> >> -#define CAMSS_CSID_HW_VERSION        0x0
> >> -#define CAMSS_CSID_CORE_CTRL_0        0x004
> >> -#define CAMSS_CSID_CORE_CTRL_1        0x008
> >> -#define CAMSS_CSID_RST_CMD(v)        ((v) == CAMSS_8x16 ? 0x00c : 0x010)
> >> -#define CAMSS_CSID_CID_LUT_VC_n(v, n)    \
> >> -            (((v) == CAMSS_8x16 ? 0x010 : 0x014) + 0x4 * (n))
> >> -#define CAMSS_CSID_CID_n_CFG(v, n)    \
> >> -            (((v) == CAMSS_8x16 ? 0x020 : 0x024) + 0x4 * (n))
> >> -#define CAMSS_CSID_CID_n_CFG_ISPIF_EN    BIT(0)
> >> -#define CAMSS_CSID_CID_n_CFG_RDI_EN    BIT(1)
> >> -#define CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT    4
> >> -#define CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_8        (0 << 8)
> >> -#define CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_16        (1 << 8)
> >> -#define CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_LSB    (0 << 9)
> >> -#define CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_MSB    (1 << 9)
> >> -#define CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP        (0 << 10)
> >> -#define CAMSS_CSID_CID_n_CFG_RDI_MODE_PLAIN_PACKING    (1 << 10)
> >> -#define CAMSS_CSID_IRQ_CLEAR_CMD(v)    ((v) == CAMSS_8x16 ? 0x060 : 0x064)
> >> -#define CAMSS_CSID_IRQ_MASK(v)        ((v) == CAMSS_8x16 ? 0x064 : 0x068)
> >> -#define CAMSS_CSID_IRQ_STATUS(v)    ((v) == CAMSS_8x16 ? 0x068 : 0x06c)
> >> -#define CAMSS_CSID_TG_CTRL(v)        ((v) == CAMSS_8x16 ? 0x0a0 : 0x0a8)
> >> -#define CAMSS_CSID_TG_CTRL_DISABLE    0xa06436
> >> -#define CAMSS_CSID_TG_CTRL_ENABLE    0xa06437
> >> -#define CAMSS_CSID_TG_VC_CFG(v)        ((v) == CAMSS_8x16 ? 0x0a4 : 0x0ac)
> >> -#define CAMSS_CSID_TG_VC_CFG_H_BLANKING        0x3ff
> >> -#define CAMSS_CSID_TG_VC_CFG_V_BLANKING        0x7f
> >> -#define CAMSS_CSID_TG_DT_n_CGG_0(v, n)    \
> >> -            (((v) == CAMSS_8x16 ? 0x0ac : 0x0b4) + 0xc * (n))
> >> -#define CAMSS_CSID_TG_DT_n_CGG_1(v, n)    \
> >> -            (((v) == CAMSS_8x16 ? 0x0b0 : 0x0b8) + 0xc * (n))
> >> -#define CAMSS_CSID_TG_DT_n_CGG_2(v, n)    \
> >> -            (((v) == CAMSS_8x16 ? 0x0b4 : 0x0bc) + 0xc * (n))
> >> -
> >> -#define DATA_TYPE_EMBEDDED_DATA_8BIT    0x12
> >> -#define DATA_TYPE_YUV422_8BIT        0x1e
> >> -#define DATA_TYPE_RAW_6BIT        0x28
> >> -#define DATA_TYPE_RAW_8BIT        0x2a
> >> -#define DATA_TYPE_RAW_10BIT        0x2b
> >> -#define DATA_TYPE_RAW_12BIT        0x2c
> >> -#define DATA_TYPE_RAW_14BIT        0x2d
> >> -
> >> -#define DECODE_FORMAT_UNCOMPRESSED_6_BIT    0x0
> >> -#define DECODE_FORMAT_UNCOMPRESSED_8_BIT    0x1
> >> -#define DECODE_FORMAT_UNCOMPRESSED_10_BIT    0x2
> >> -#define DECODE_FORMAT_UNCOMPRESSED_12_BIT    0x3
> >> -#define DECODE_FORMAT_UNCOMPRESSED_14_BIT    0x8
> >> -
> >> -#define CSID_RESET_TIMEOUT_MS 500
> >> -
> >> -struct csid_format {
> >> -    u32 code;
> >> -    u8 data_type;
> >> -    u8 decode_format;
> >> -    u8 bpp;
> >> -    u8 spp; /* bus samples per pixel */
> >> -};
> >> -
> >> -static const struct csid_format csid_formats_8x16[] = {
> >> -    {
> >> -        MEDIA_BUS_FMT_UYVY8_2X8,
> >> -        DATA_TYPE_YUV422_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        2,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_VYUY8_2X8,
> >> -        DATA_TYPE_YUV422_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        2,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_YUYV8_2X8,
> >> -        DATA_TYPE_YUV422_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        2,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_YVYU8_2X8,
> >> -        DATA_TYPE_YUV422_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        2,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SBGGR8_1X8,
> >> -        DATA_TYPE_RAW_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGBRG8_1X8,
> >> -        DATA_TYPE_RAW_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGRBG8_1X8,
> >> -        DATA_TYPE_RAW_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SRGGB8_1X8,
> >> -        DATA_TYPE_RAW_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SBGGR10_1X10,
> >> -        DATA_TYPE_RAW_10BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> -        10,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGBRG10_1X10,
> >> -        DATA_TYPE_RAW_10BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> -        10,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGRBG10_1X10,
> >> -        DATA_TYPE_RAW_10BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> -        10,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SRGGB10_1X10,
> >> -        DATA_TYPE_RAW_10BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> -        10,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SBGGR12_1X12,
> >> -        DATA_TYPE_RAW_12BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> -        12,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGBRG12_1X12,
> >> -        DATA_TYPE_RAW_12BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> -        12,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGRBG12_1X12,
> >> -        DATA_TYPE_RAW_12BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> -        12,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SRGGB12_1X12,
> >> -        DATA_TYPE_RAW_12BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> -        12,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_Y10_1X10,
> >> -        DATA_TYPE_RAW_10BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> -        10,
> >> -        1,
> >> -    },
> >> -};
> >> -
> >> -static const struct csid_format csid_formats_8x96[] = {
> >> -    {
> >> -        MEDIA_BUS_FMT_UYVY8_2X8,
> >> -        DATA_TYPE_YUV422_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        2,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_VYUY8_2X8,
> >> -        DATA_TYPE_YUV422_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        2,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_YUYV8_2X8,
> >> -        DATA_TYPE_YUV422_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        2,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_YVYU8_2X8,
> >> -        DATA_TYPE_YUV422_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        2,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SBGGR8_1X8,
> >> -        DATA_TYPE_RAW_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGBRG8_1X8,
> >> -        DATA_TYPE_RAW_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGRBG8_1X8,
> >> -        DATA_TYPE_RAW_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SRGGB8_1X8,
> >> -        DATA_TYPE_RAW_8BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_8_BIT,
> >> -        8,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SBGGR10_1X10,
> >> -        DATA_TYPE_RAW_10BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> -        10,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGBRG10_1X10,
> >> -        DATA_TYPE_RAW_10BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> -        10,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGRBG10_1X10,
> >> -        DATA_TYPE_RAW_10BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> -        10,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SRGGB10_1X10,
> >> -        DATA_TYPE_RAW_10BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> -        10,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SBGGR12_1X12,
> >> -        DATA_TYPE_RAW_12BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> -        12,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGBRG12_1X12,
> >> -        DATA_TYPE_RAW_12BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> -        12,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGRBG12_1X12,
> >> -        DATA_TYPE_RAW_12BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> -        12,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SRGGB12_1X12,
> >> -        DATA_TYPE_RAW_12BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_12_BIT,
> >> -        12,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SBGGR14_1X14,
> >> -        DATA_TYPE_RAW_14BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_14_BIT,
> >> -        14,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGBRG14_1X14,
> >> -        DATA_TYPE_RAW_14BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_14_BIT,
> >> -        14,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SGRBG14_1X14,
> >> -        DATA_TYPE_RAW_14BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_14_BIT,
> >> -        14,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_SRGGB14_1X14,
> >> -        DATA_TYPE_RAW_14BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_14_BIT,
> >> -        14,
> >> -        1,
> >> -    },
> >> -    {
> >> -        MEDIA_BUS_FMT_Y10_1X10,
> >> -        DATA_TYPE_RAW_10BIT,
> >> -        DECODE_FORMAT_UNCOMPRESSED_10_BIT,
> >> -        10,
> >> -        1,
> >> -    },
> >> -};
> >> -static u32 csid_find_code(u32 *code, unsigned int n_code,
> >> -              unsigned int index, u32 req_code)
> >> +u32 csid_find_code(u32 *codes, unsigned int ncodes,
> >> +           unsigned int match_format_idx, u32 match_code)
> >>   {
> >>       int i;
> >> -    if (!req_code && (index >= n_code))
> >> +    if (!match_code && (match_format_idx >= ncodes))
> >>           return 0;
> >> -    for (i = 0; i < n_code; i++)
> >> -        if (req_code) {
> >> -            if (req_code == code[i])
> >> -                return req_code;
> >> +    for (i = 0; i < ncodes; i++)
> >> +        if (match_code) {
> >> +            if (codes[i] == match_code)
> >> +                return match_code;
> >>           } else {
> >> -            if (i == index)
> >> -                return code[i];
> >> -        }
> >> -
> >> -    return code[0];
> >> -}
> >> -
> >> -static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code,
> >> -                 unsigned int index, u32 src_req_code)
> >> -{
> >> -    if (csid->camss->version == CAMSS_8x16) {
> >> -        if (index > 0)
> >> -            return 0;
> >> -
> >> -        return sink_code;
> >> -    } else if (csid->camss->version == CAMSS_8x96 ||
> >> -           csid->camss->version == CAMSS_660) {
> >> -        switch (sink_code) {
> >> -        case MEDIA_BUS_FMT_SBGGR10_1X10:
> >> -        {
> >> -            u32 src_code[] = {
> >> -                MEDIA_BUS_FMT_SBGGR10_1X10,
> >> -                MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,
> >> -            };
> >> -
> >> -            return csid_find_code(src_code, ARRAY_SIZE(src_code),
> >> -                          index, src_req_code);
> >> -        }
> >> -        case MEDIA_BUS_FMT_Y10_1X10:
> >> -        {
> >> -            u32 src_code[] = {
> >> -                MEDIA_BUS_FMT_Y10_1X10,
> >> -                MEDIA_BUS_FMT_Y10_2X8_PADHI_LE,
> >> -            };
> >> -
> >> -            return csid_find_code(src_code, ARRAY_SIZE(src_code),
> >> -                          index, src_req_code);
> >> +            if (i == match_format_idx)
> >> +                return codes[i];
> >>           }
> >> -        default:
> >> -            if (index > 0)
> >> -                return 0;
> >> -            return sink_code;
> >> -        }
> >> -    } else {
> >> -        return 0;
> >> -    }
> >> +    return codes[0];
> >>   }
> >> -static const struct csid_format *csid_get_fmt_entry(
> >> +const struct csid_format *csid_get_fmt_entry(
> >>                       const struct csid_format *formats,
> >> -                    unsigned int nformat,
> >> +                    unsigned int nformats,
> >>                       u32 code)
> >>   {
> >>       unsigned int i;
> >> -    for (i = 0; i < nformat; i++)
> >> +    for (i = 0; i < nformats; i++)
> >>           if (code == formats[i].code)
> >>               return &formats[i];
> >> @@ -433,28 +63,6 @@ static const struct csid_format *csid_get_fmt_entry(
> >>       return &formats[0];
> >>   }
> >> -/*
> >> - * csid_isr - CSID module interrupt handler
> >> - * @irq: Interrupt line
> >> - * @dev: CSID device
> >> - *
> >> - * Return IRQ_HANDLED on success
> >> - */
> >> -static irqreturn_t csid_isr(int irq, void *dev)
> >> -{
> >> -    struct csid_device *csid = dev;
> >> -    enum camss_version ver = csid->camss->version;
> >> -    u32 value;
> >> -
> >> -    value = readl_relaxed(csid->base + CAMSS_CSID_IRQ_STATUS(ver));
> >> -    writel_relaxed(value, csid->base + CAMSS_CSID_IRQ_CLEAR_CMD(ver));
> >> -
> >> -    if ((value >> 11) & 0x1)
> >> -        complete(&csid->reset_complete);
> >> -
> >> -    return IRQ_HANDLED;
> >> -}
> >> -
> >>   /*
> >>    * csid_set_clock_rates - Calculate and set clock rates on CSID module
> >>    * @csiphy: CSID device
> >> @@ -521,31 +129,6 @@ static int csid_set_clock_rates(struct csid_device *csid)
> >>       return 0;
> >>   }
> >> -/*
> >> - * csid_reset - Trigger reset on CSID module and wait to complete
> >> - * @csid: CSID device
> >> - *
> >> - * Return 0 on success or a negative error code otherwise
> >> - */
> >> -static int csid_reset(struct csid_device *csid)
> >> -{
> >> -    unsigned long time;
> >> -
> >> -    reinit_completion(&csid->reset_complete);
> >> -
> >> -    writel_relaxed(0x7fff, csid->base +
> >> -               CAMSS_CSID_RST_CMD(csid->camss->version));
> >> -
> >> -    time = wait_for_completion_timeout(&csid->reset_complete,
> >> -        msecs_to_jiffies(CSID_RESET_TIMEOUT_MS));
> >> -    if (!time) {
> >> -        dev_err(csid->camss->dev, "CSID reset timeout\n");
> >> -        return -EIO;
> >> -    }
> >> -
> >> -    return 0;
> >> -}
> >> -
> >>   /*
> >>    * csid_set_power - Power on/off CSID module
> >>    * @sd: CSID V4L2 subdevice
> >> @@ -560,8 +143,6 @@ static int csid_set_power(struct v4l2_subdev *sd, int on)
> >>       int ret;
> >>       if (on) {
> >> -        u32 hw_version;
> >> -
> >>           ret = pm_runtime_get_sync(dev);
> >>           if (ret < 0) {
> >>               pm_runtime_put_sync(dev);
> >> @@ -590,7 +171,7 @@ static int csid_set_power(struct v4l2_subdev *sd, int on)
> >>           enable_irq(csid->irq);
> >> -        ret = csid_reset(csid);
> >> +        ret = csid->ops->reset(csid);
> >>           if (ret < 0) {
> >>               disable_irq(csid->irq);
> >>               camss_disable_clocks(csid->nclocks, csid->clock);
> >> @@ -599,8 +180,7 @@ static int csid_set_power(struct v4l2_subdev *sd, int on)
> >>               return ret;
> >>           }
> >> -        hw_version = readl_relaxed(csid->base + CAMSS_CSID_HW_VERSION);
> >> -        dev_dbg(dev, "CSID HW Version = 0x%08x\n", hw_version);
> >> +        csid->ops->hw_version(csid);
> >>       } else {
> >>           disable_irq(csid->irq);
> >>           camss_disable_clocks(csid->nclocks, csid->clock);
> >> @@ -623,16 +203,9 @@ static int csid_set_power(struct v4l2_subdev *sd, int on)
> >>   static int csid_set_stream(struct v4l2_subdev *sd, int enable)
> >>   {
> >>       struct csid_device *csid = v4l2_get_subdevdata(sd);
> >> -    struct csid_testgen_config *tg = &csid->testgen;
> >> -    enum camss_version ver = csid->camss->version;
> >> -    u32 val;
> >> +    int ret;
> >>       if (enable) {
> >> -        u8 vc = 0; /* Virtual Channel 0 */
> >> -        u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */
> >> -        u8 dt, dt_shift, df;
> >> -        int ret;
> >> -
> >>           ret = v4l2_ctrl_handler_setup(&csid->ctrls);
> >>           if (ret < 0) {
> >>               dev_err(csid->camss->dev,
> >> @@ -640,116 +213,13 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable)
> >>               return ret;
> >>           }
> >> -        if (!tg->enabled &&
> >> +        if (!csid->testgen.enabled &&
> >>               !media_entity_remote_pad(&csid->pads[MSM_CSID_PAD_SINK]))
> >>               return -ENOLINK;
> >> -
> >> -        if (tg->enabled) {
> >> -            /* Config Test Generator */
> >> -            struct v4l2_mbus_framefmt *f =
> >> -                    &csid->fmt[MSM_CSID_PAD_SRC];
> >> -            const struct csid_format *format = csid_get_fmt_entry(
> >> -                    csid->formats, csid->nformats, f->code);
> >> -            u32 num_bytes_per_line =
> >> -                f->width * format->bpp * format->spp / 8;
> >> -            u32 num_lines = f->height;
> >> -
> >> -            /* 31:24 V blank, 23:13 H blank, 3:2 num of active DT */
> >> -            /* 1:0 VC */
> >> -            val = ((CAMSS_CSID_TG_VC_CFG_V_BLANKING & 0xff) << 24) |
> >> -                  ((CAMSS_CSID_TG_VC_CFG_H_BLANKING & 0x7ff) << 13);
> >> -            writel_relaxed(val, csid->base +
> >> -                       CAMSS_CSID_TG_VC_CFG(ver));
> >> -
> >> -            /* 28:16 bytes per lines, 12:0 num of lines */
> >> -            val = ((num_bytes_per_line & 0x1fff) << 16) |
> >> -                  (num_lines & 0x1fff);
> >> -            writel_relaxed(val, csid->base +
> >> -                       CAMSS_CSID_TG_DT_n_CGG_0(ver, 0));
> >> -
> >> -            dt = format->data_type;
> >> -
> >> -            /* 5:0 data type */
> >> -            val = dt;
> >> -            writel_relaxed(val, csid->base +
> >> -                       CAMSS_CSID_TG_DT_n_CGG_1(ver, 0));
> >> -
> >> -            /* 2:0 output test pattern */
> >> -            val = tg->payload_mode;
> >> -            writel_relaxed(val, csid->base +
> >> -                       CAMSS_CSID_TG_DT_n_CGG_2(ver, 0));
> >> -
> >> -            df = format->decode_format;
> >> -        } else {
> >> -            struct v4l2_mbus_framefmt *f =
> >> -                    &csid->fmt[MSM_CSID_PAD_SINK];
> >> -            const struct csid_format *format = csid_get_fmt_entry(
> >> -                    csid->formats, csid->nformats, f->code);
> >> -            struct csid_phy_config *phy = &csid->phy;
> >> -
> >> -            val = phy->lane_cnt - 1;
> >> -            val |= phy->lane_assign << 4;
> >> -
> >> -            writel_relaxed(val,
> >> -                       csid->base + CAMSS_CSID_CORE_CTRL_0);
> >> -
> >> -            val = phy->csiphy_id << 17;
> >> -            val |= 0x9;
> >> -
> >> -            writel_relaxed(val,
> >> -                       csid->base + CAMSS_CSID_CORE_CTRL_1);
> >> -
> >> -            dt = format->data_type;
> >> -            df = format->decode_format;
> >> -        }
> >> -
> >> -        /* Config LUT */
> >> -
> >> -        dt_shift = (cid % 4) * 8;
> >> -
> >> -        val = readl_relaxed(csid->base +
> >> -                    CAMSS_CSID_CID_LUT_VC_n(ver, vc));
> >> -        val &= ~(0xff << dt_shift);
> >> -        val |= dt << dt_shift;
> >> -        writel_relaxed(val, csid->base +
> >> -                   CAMSS_CSID_CID_LUT_VC_n(ver, vc));
> >> -
> >> -        val = CAMSS_CSID_CID_n_CFG_ISPIF_EN;
> >> -        val |= CAMSS_CSID_CID_n_CFG_RDI_EN;
> >> -        val |= df << CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT;
> >> -        val |= CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP;
> >> -
> >> -        if (csid->camss->version == CAMSS_8x96 ||
> >> -            csid->camss->version == CAMSS_660) {
> >> -            u32 sink_code = csid->fmt[MSM_CSID_PAD_SINK].code;
> >> -            u32 src_code = csid->fmt[MSM_CSID_PAD_SRC].code;
> >> -
> >> -            if ((sink_code == MEDIA_BUS_FMT_SBGGR10_1X10 &&
> >> -                 src_code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) ||
> >> -                (sink_code == MEDIA_BUS_FMT_Y10_1X10 &&
> >> -                 src_code == MEDIA_BUS_FMT_Y10_2X8_PADHI_LE)) {
> >> -                val |= CAMSS_CSID_CID_n_CFG_RDI_MODE_PLAIN_PACKING;
> >> -                val |= CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_16;
> >> -                val |= CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_LSB;
> >> -            }
> >> -        }
> >> -
> >> -        writel_relaxed(val, csid->base +
> >> -                   CAMSS_CSID_CID_n_CFG(ver, cid));
> >> -
> >> -        if (tg->enabled) {
> >> -            val = CAMSS_CSID_TG_CTRL_ENABLE;
> >> -            writel_relaxed(val, csid->base +
> >> -                       CAMSS_CSID_TG_CTRL(ver));
> >> -        }
> >> -    } else {
> >> -        if (tg->enabled) {
> >> -            val = CAMSS_CSID_TG_CTRL_DISABLE;
> >> -            writel_relaxed(val, csid->base +
> >> -                       CAMSS_CSID_TG_CTRL(ver));
> >> -        }
> >>       }
> >> +    csid->ops->configure_stream(csid, enable);
> >> +
> >>       return 0;
> >>   }
> >> @@ -818,7 +288,7 @@ static void csid_try_format(struct csid_device *csid,
> >>               *fmt = *__csid_get_format(csid, cfg,
> >>                                 MSM_CSID_PAD_SINK, which);
> >> -            fmt->code = csid_src_pad_code(csid, fmt->code, 0, code);
> >> +            fmt->code = csid->ops->src_pad_code(csid, fmt->code, 0, code);
> >>           } else {
> >>               /* Test generator is enabled, set format on source */
> >>               /* pad to allow test generator usage */
> >> @@ -868,7 +338,7 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd,
> >>                                MSM_CSID_PAD_SINK,
> >>                                code->which);
> >> -            code->code = csid_src_pad_code(csid, sink_fmt->code,
> >> +            code->code = csid->ops->src_pad_code(csid, sink_fmt->code,
> >>                                  code->index, 0);
> >>               if (!code->code)
> >>                   return -EINVAL;
> >> @@ -1004,15 +474,6 @@ static int csid_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> >>       return csid_set_format(sd, fh ? fh->pad : NULL, &format);
> >>   }
> >> -static const char * const csid_test_pattern_menu[] = {
> >> -    "Disabled",
> >> -    "Incrementing",
> >> -    "Alternating 0x55/0xAA",
> >> -    "All Zeros 0x00",
> >> -    "All Ones 0xFF",
> >> -    "Pseudo-random Data",
> >> -};
> >> -
> >>   /*
> >>    * csid_set_test_pattern - Set test generator's pattern mode
> >>    * @csid: CSID device
> >> @@ -1030,25 +491,7 @@ static int csid_set_test_pattern(struct csid_device *csid, s32 value)
> >>       tg->enabled = !!value;
> >> -    switch (value) {
> >> -    case 1:
> >> -        tg->payload_mode = CSID_PAYLOAD_MODE_INCREMENTING;
> >> -        break;
> >> -    case 2:
> >> -        tg->payload_mode = CSID_PAYLOAD_MODE_ALTERNATING_55_AA;
> >> -        break;
> >> -    case 3:
> >> -        tg->payload_mode = CSID_PAYLOAD_MODE_ALL_ZEROES;
> >> -        break;
> >> -    case 4:
> >> -        tg->payload_mode = CSID_PAYLOAD_MODE_ALL_ONES;
> >> -        break;
> >> -    case 5:
> >> -        tg->payload_mode = CSID_PAYLOAD_MODE_RANDOM;
> >> -        break;
> >> -    }
> >> -
> >> -    return 0;
> >> +    return csid->ops->configure_testgen_pattern(csid, value);
> >>   }
> >>   /*
> >> @@ -1097,17 +540,14 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid,
> >>       csid->id = id;
> >>       if (camss->version == CAMSS_8x16) {
> >> -        csid->formats = csid_formats_8x16;
> >> -        csid->nformats =
> >> -                ARRAY_SIZE(csid_formats_8x16);
> >> +        csid->ops = &csid_ops_4_1;
> >>       } else if (camss->version == CAMSS_8x96 ||
> >>              camss->version == CAMSS_660) {
> >> -        csid->formats = csid_formats_8x96;
> >> -        csid->nformats =
> >> -                ARRAY_SIZE(csid_formats_8x96);
> >> +        csid->ops = &csid_ops_4_7;
> >>       } else {
> >>           return -EINVAL;
> >>       }
> >> +    csid->ops->subdev_init(csid);
> >>       /* Memory */
> >> @@ -1130,7 +570,7 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid,
> >>       csid->irq = r->start;
> >>       snprintf(csid->irq_name, sizeof(csid->irq_name), "%s_%s%d",
> >>            dev_name(dev), MSM_CSID_NAME, csid->id);
> >> -    ret = devm_request_irq(dev, csid->irq, csid_isr,
> >> +    ret = devm_request_irq(dev, csid->irq, csid->ops->isr,
> >>           IRQF_TRIGGER_RISING, csid->irq_name, csid);
> >>       if (ret < 0) {
> >>           dev_err(dev, "request_irq failed: %d\n", ret);
> >> @@ -1341,8 +781,8 @@ int msm_csid_register_entity(struct csid_device *csid,
> >>       csid->testgen_mode = v4l2_ctrl_new_std_menu_items(&csid->ctrls,
> >>                   &csid_ctrl_ops, V4L2_CID_TEST_PATTERN,
> >> -                ARRAY_SIZE(csid_test_pattern_menu) - 1, 0, 0,
> >> -                csid_test_pattern_menu);
> >> +                csid->testgen.nmodes, 0, 0,
>
> enum csid_testgen_mode has the test patterns id's numbered from 0 to MAX_SUPPORTED.
> So the MAX_SUPPORTED is the number of test patterns *minus one*.
> csid->testgen.nmodes points to the csid_testgen_modes[] array which contains the
> test patterns name *plus* "Disabled" as the first element.
> Thus the old (ARRAY_SIZE(csid_test_pattern_menu) - 1) is greater by one than
> csid->testgen.nmodes.
> By passing csid->testgen.nmodes as the max value to v4l2_ctrl_new_std_menu_items()
> you exclude the last test pattern from the menu - you can check the output of
> "v4l2-ctl -L -d <csid subdevice>".
> IMHO the logic would be simpler, if the test patterns were numbered starting from 1, not 0,
> leaving the value of 0 to "TG disabled".

Ack. I agree. The reason for the current enum numbering is because it
aligns with register values. But adding a '-1' to the register write
is cleaner than having this pile of exceptions throughout the code.

I think I'll rework enum, the related code chunks, and switch out the
MAX_SUPPORTED value for NUM_SUPPORTED == MAX_SUPPORTED + 1, to get rid
of offsets everywhere.

>
>
> Thanks,
> Andrey
>
> >> +                csid->testgen.modes);
> >>       if (csid->ctrls.error) {
> >>           dev_err(dev, "Failed to init ctrl: %d\n", csid->ctrls.error);
> >> diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h
> >> index 02fc34ee8a41..d40194e2bed3 100644
> >> --- a/drivers/media/platform/qcom/camss/camss-csid.h
> >> +++ b/drivers/media/platform/qcom/camss/camss-csid.h
> >> @@ -11,6 +11,7 @@
> >>   #define QC_MSM_CAMSS_CSID_H
> >>   #include <linux/clk.h>
> >> +#include <linux/interrupt.h>
> >>   #include <media/media-entity.h>
> >>   #include <media/v4l2-ctrls.h>
> >>   #include <media/v4l2-device.h>
> >> @@ -70,19 +71,50 @@
> >>   #define PLAIN_FORMAT_PLAIN16    0x1 /* supports DPCM, UNCOMPRESSED_10/16_BIT */
> >>   #define PLAIN_FORMAT_PLAIN32    0x2 /* supports UNCOMPRESSED_20_BIT */
> >> +#define CSID_RESET_TIMEOUT_MS 500
> >> -enum csid_payload_mode {
> >> +
> >> +enum csid_testgen_mode {
> >>       CSID_PAYLOAD_MODE_INCREMENTING = 0,
> >>       CSID_PAYLOAD_MODE_ALTERNATING_55_AA = 1,
> >>       CSID_PAYLOAD_MODE_ALL_ZEROES = 2,
> >>       CSID_PAYLOAD_MODE_ALL_ONES = 3,
> >>       CSID_PAYLOAD_MODE_RANDOM = 4,
> >>       CSID_PAYLOAD_MODE_USER_SPECIFIED = 5,
> >> +    CSID_PAYLOAD_MODE_MAX_SUPPORTED_4_1 = 5,
> >> +    CSID_PAYLOAD_MODE_MAX_SUPPORTED_4_7 = 5,
> >> +    CSID_PAYLOAD_MODE_COMPLEX_PATTERN = 6,
> >> +    CSID_PAYLOAD_MODE_COLOR_BOX = 7,
> >> +    CSID_PAYLOAD_MODE_COLOR_BARS = 8,
> >> +    CSID_PAYLOAD_MODE_MAX_SUPPORTED_170 = 8,
> >> +};
> >> +
> >> +static const char * const csid_testgen_modes[] = {
> >> +    "Disabled",
> >> +    "Incrementing",
> >> +    "Alternating 0x55/0xAA",
> >> +    "All Zeros 0x00",
> >> +    "All Ones 0xFF",
> >> +    "Pseudo-random Data",
> >> +    "User Specified",
> >> +    "Complex pattern",
> >> +    "Color box",
> >> +    "Color bars",
> >> +};
> >> +
> >> +struct csid_format {
> >> +    u32 code;
> >> +    u8 data_type;
> >> +    u8 decode_format;
> >> +    u8 bpp;
> >> +    u8 spp; /* bus samples per pixel */
> >>   };
> >>   struct csid_testgen_config {
> >> +    enum csid_testgen_mode mode;
> >> +    const char * const*modes;
> >> +    u8 nmodes;
> >>       u8 enabled;
> >> -    enum csid_payload_mode payload_mode;
> >>   };
> >>   struct csid_phy_config {
> >> @@ -91,6 +123,65 @@ struct csid_phy_config {
> >>       u32 lane_assign;
> >>   };
> >> +struct csid_device;
> >> +
> >> +struct csid_hw_ops {
> >> +    /*
> >> +     * configure_stream - Configures and starts CSID input stream
> >> +     * @csid: CSID device
> >> +     */
> >> +    void (*configure_stream)(struct csid_device *csid, u8 enable);
> >> +
> >> +    /*
> >> +     * configure_testgen_pattern - Validates and configures output pattern mode
> >> +     * of test pattern generator
> >> +     * @csid: CSID device
> >> +     */
> >> +    int (*configure_testgen_pattern)(struct csid_device *csid, s32 val);
> >> +
> >> +    /*
> >> +     * hw_version - Read hardware version register from hardware
> >> +     * @csid: CSID device
> >> +     */
> >> +    u32 (*hw_version)(struct csid_device *csid);
> >> +
> >> +    /*
> >> +     * isr - CSID module interrupt service routine
> >> +     * @irq: Interrupt line
> >> +     * @dev: CSID device
> >> +     *
> >> +     * Return IRQ_HANDLED on success
> >> +     */
> >> +    irqreturn_t (*isr)(int irq, void *dev);
> >> +
> >> +    /*
> >> +     * reset - Trigger reset on CSID module and wait to complete
> >> +     * @csid: CSID device
> >> +     *
> >> +     * Return 0 on success or a negative error code otherwise
> >> +     */
> >> +    int (*reset)(struct csid_device *csid);
> >> +
> >> +    /*
> >> +     * src_pad_code - Pick an output/src format based on the input/sink format
> >> +     * @csid: CSID device
> >> +     * @sink_code: The sink format of the input
> >> +     * @match_format_idx: Request preferred index, as defined by subdevice csid_format.
> >> +     *    Set @match_code to 0 if used.
> >> +     * @match_code: Request preferred code, set @match_format_idx to 0 if used
> >> +     *
> >> +     * Return 0 on failure or src format code otherwise
> >> +     */
> >> +    u32 (*src_pad_code)(struct csid_device *csid, u32 sink_code,
> >> +                unsigned int match_format_idx, u32 match_code);
> >> +
> >> +    /*
> >> +     * subdev_init - Initialize CSID device according for hardware revision
> >> +     * @csid: CSID device
> >> +     */
> >> +    void (*subdev_init)(struct csid_device *csid);
> >> +};
> >> +
> >>   struct csid_device {
> >>       struct camss *camss;
> >>       u8 id;
> >> @@ -110,10 +201,37 @@ struct csid_device {
> >>       struct v4l2_ctrl *testgen_mode;
> >>       const struct csid_format *formats;
> >>       unsigned int nformats;
> >> +    const struct csid_hw_ops *ops;
> >>   };
> >>   struct resources;
> >> +
> >> +/*
> >> + * csid_find_code - Find a format code in an array using array index or format code
> >> + * @codes: Array of format codes
> >> + * @ncodes: Length of @code array
> >> + * @req_format_idx: Request preferred index, as defined by subdevice csid_format.
> >> + *    Set @match_code to 0 if used.
> >> + * @match_code: Request preferred code, set @req_format_idx to 0 if used
> >> + *
> >> + * Return 0 on failure or format code otherwise
> >> + */
> >> +u32 csid_find_code(u32 *codes, unsigned int ncode,
> >> +           unsigned int match_format_idx, u32 match_code);
> >> +
> >> +/*
> >> + * csid_get_fmt_entry - Find csid_format entry with matching format code
> >> + * @formats: Array of format csid_format entries
> >> + * @nformats: Length of @nformats array
> >> + * @code: Desired format code
> >> + *
> >> + * Return formats[0] on failure to find code
> >> + */
> >> +const struct csid_format *csid_get_fmt_entry(const struct csid_format *formats,
> >> +                         unsigned int nformats,
> >> +                         u32 code);
> >> +
> >>   int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid,
> >>                const struct resources *res, u8 id);
> >> @@ -124,4 +242,8 @@ void msm_csid_unregister_entity(struct csid_device *csid);
> >>   void msm_csid_get_csid_id(struct media_entity *entity, u8 *id);
> >> +
> >> +extern const struct csid_hw_ops csid_ops_4_1;
> >> +extern const struct csid_hw_ops csid_ops_4_7;
> >> +
> >>   #endif /* QC_MSM_CAMSS_CSID_H */
> >>

  reply	other threads:[~2021-02-22 18:20 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-17 11:21 [PATCH v5 00/22] Add support for the SDM845 Camera Subsystem Robert Foss
2021-02-17 11:21 ` [PATCH v5 01/22] media: camss: Fix vfe_isr_comp_done() documentation Robert Foss
2021-02-19 21:05   ` Nicolas Dufresne
2021-02-22 10:51     ` Robert Foss
2021-02-20 18:44   ` Andrey Konovalov
2021-02-17 11:21 ` [PATCH v5 02/22] media: camss: Fix vfe_isr comment typo Robert Foss
2021-02-17 11:21 ` [PATCH v5 03/22] media: camss: Replace trace_printk() with dev_dbg() Robert Foss
2021-02-17 11:21 ` [PATCH v5 04/22] media: camss: Add CAMSS_845 camss version Robert Foss
2021-02-20 18:42   ` Andrey Konovalov
2021-02-17 11:21 ` [PATCH v5 05/22] media: camss: Make ISPIF subdevice optional Robert Foss
2021-02-18 19:49   ` Andrey Konovalov
2021-02-17 11:21 ` [PATCH v5 06/22] media: camss: Refactor VFE HW version support Robert Foss
2021-02-20 18:35   ` Andrey Konovalov
2021-02-22 10:46     ` Robert Foss
2021-02-17 11:21 ` [PATCH v5 07/22] media: camss: Add support for VFE hardware version Titan 170 Robert Foss
2021-02-20 21:40   ` Andrey Konovalov
2021-02-22 16:37     ` Robert Foss
2021-02-22 17:06       ` Andrey Konovalov
2021-02-22 17:21         ` Robert Foss
2021-02-22 17:24           ` Andrey Konovalov
2021-02-20 21:40   ` Andrey Konovalov
2021-02-17 11:21 ` [PATCH v5 08/22] media: camss: Add missing format identifiers Robert Foss
2021-02-22 16:26   ` Andrey Konovalov
2021-02-23 17:25     ` Robert Foss
2021-02-17 11:21 ` [PATCH v5 09/22] media: camss: Refactor CSID HW version support Robert Foss
2021-02-21 15:15   ` Andrey Konovalov
2021-02-21 17:50     ` Andrey Konovalov
2021-02-22 18:13       ` Robert Foss [this message]
2021-02-17 11:21 ` [PATCH v5 10/22] media: camss: Add support for CSID hardware version Titan 170 Robert Foss
2021-02-21 17:14   ` Andrey Konovalov
2021-02-22 17:06     ` Robert Foss
2021-02-17 11:21 ` [PATCH v5 11/22] media: camss: Add support for CSIPHY " Robert Foss
2021-02-21 18:17   ` Andrey Konovalov
2021-02-23  9:36     ` Robert Foss
2021-02-17 11:21 ` [PATCH v5 12/22] media: camss: Remove per VFE power domain toggling Robert Foss
2021-02-22 11:44   ` Andrey Konovalov
2021-02-24 14:53     ` Robert Foss
2021-02-17 11:21 ` [PATCH v5 13/22] media: camss: Enable SDM845 Robert Foss
2021-02-21 18:32   ` Andrey Konovalov
2021-02-17 11:21 ` [PATCH v5 14/22] dt-bindings: media: camss: Add qcom,msm8916-camss binding Robert Foss
2021-02-17 11:21 ` [PATCH v5 15/22] dt-bindings: media: camss: Add qcom,msm8996-camss binding Robert Foss
2021-02-17 11:21 ` [PATCH v5 16/22] dt-bindings: media: camss: Add qcom,sdm660-camss binding Robert Foss
2021-02-17 11:21 ` [PATCH v5 17/22] dt-bindings: media: camss: Add qcom,sdm845-camss binding Robert Foss
2021-02-17 11:21 ` [PATCH v5 18/22] MAINTAINERS: Change CAMSS documentation to use dtschema bindings Robert Foss
2021-02-17 11:21 ` [PATCH v5 19/22] media: dt-bindings: media: Remove qcom,camss documentation Robert Foss
2021-02-17 11:21 ` [PATCH v5 20/22] arm64: dts: sdm845: Add CAMSS ISP node Robert Foss
2021-02-21 18:39   ` Andrey Konovalov
2021-02-17 11:21 ` [PATCH v5 21/22] arm64: dts: sdm845-db845c: Configure regulators for camss node Robert Foss
2021-02-21 18:39   ` Andrey Konovalov
2021-02-17 11:21 ` [PATCH v5 22/22] arm64: dts: sdm845-db845c: Enable ov8856 sensor and connect to ISP Robert Foss
2021-02-21 18:39   ` Andrey Konovalov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAG3jFyvZKTcFWBaRT9j36mEMHqKSW9Q5Opn51vpZ_Ve1ndt24A@mail.gmail.com \
    --to=robert.foss@linaro.org \
    --cc=Sarvesh.Sridutt@smartwirelesscompute.com \
    --cc=agross@kernel.org \
    --cc=akapatra@quicinc.com \
    --cc=andrey.konovalov@linaro.org \
    --cc=angelogioacchino.delregno@somainline.org \
    --cc=bjorn.andersson@linaro.org \
    --cc=devicetree@vger.kernel.org \
    --cc=jonathan@marek.ca \
    --cc=kholk11@gmail.com \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=mchehab@kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=sakari.ailus@iki.fi \
    --cc=tfiga@chromium.org \
    --cc=todor.too@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).