From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9CAB1C433E9 for ; Mon, 22 Feb 2021 18:20:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 397CC64E09 for ; Mon, 22 Feb 2021 18:20:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232197AbhBVSUF (ORCPT ); Mon, 22 Feb 2021 13:20:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51202 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232143AbhBVSOr (ORCPT ); Mon, 22 Feb 2021 13:14:47 -0500 Received: from mail-pg1-x533.google.com (mail-pg1-x533.google.com [IPv6:2607:f8b0:4864:20::533]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4B67BC06178A for ; Mon, 22 Feb 2021 10:14:07 -0800 (PST) Received: by mail-pg1-x533.google.com with SMTP id o38so10710467pgm.9 for ; Mon, 22 Feb 2021 10:14:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=Fl+iRwWeoAl1lv3KDRJ+bCCJsuYkxLGuwLOOewljG0Q=; b=b5BhqIn32x+kIGRmzi9uRM7XssxfXgi5XW366RZcJHfpHuWuHutfnUUGAa8M1YxVgN 76OwlxEzw4wywQkj2oQq3NJTkCmiFtGVAmkkPbTVU4wis65a3YPTOLq3mMN7NCV78mZX mF4h0ODOikUFJYxqyVmwtMqCEAF4/6GUFO2BzTRkP1wJUe4M0lLscNjnmAq9jCyKHzRD G6AVF9cc3HVk5RfytAyYUtM1VU79LPfO/ZcW0/fJJAKiSiEqWxji5aZQZ9wHPskL/y+1 k9Oy0fAdGiVPu4nGwSMhqymxVrP7aDVzBiwQqzco8Dv3dyfEy7EBIG+rO7PY3DxiI+jg n+fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=Fl+iRwWeoAl1lv3KDRJ+bCCJsuYkxLGuwLOOewljG0Q=; b=rAa1AZFJzUIsHm8a61wWo9DWww4C47vuojONFu/vGEByixW7M0s9uEgRdqbhErkuuB uo1er+19EA42JiPx/GI7jjiYWfcukoKP8TNbH2RpNUs3DUVtMD5aKh9WFaMOEoo6pd0x srb4GLCxVjWblOlXi/U5zMSq4mTlwkurTRB+0t9Mpi6V18NcgUJsmZ4G9LVfIzBuFMwW tJiNhxaFGViF19FBghuG92+c7xyBf7oXaTJTAPx4ebgsVpObE0NpJtHg+nBKzeLfuiqW TqnTe3lq8nPD3/hEd+ZTAwXNeUXwzlcLEIDoGTa+1PnEBM+VuAfRIdjQvBvLt6131eos o8+g== X-Gm-Message-State: AOAM530xWidVZyNCXdC1EDoo0w9jk/HeW1BMkMC8DYKO6ANxnP+/ZlBS MH3Yks+n9NhgUrKcgp1INeIFL/NNuZ9L0Vu8HUJwjA== X-Google-Smtp-Source: ABdhPJwPTFRZmDj5o0ugutMTIJYHbOGfCV9u80SXKHPGdtEekkWrrFfTbefoyfhIAraextvkWehwQFfLZcJiSyDhLBU= X-Received: by 2002:a63:6547:: with SMTP id z68mr17764415pgb.120.1614017643682; Mon, 22 Feb 2021 10:14:03 -0800 (PST) MIME-Version: 1.0 References: <20210217112122.424236-1-robert.foss@linaro.org> <20210217112122.424236-10-robert.foss@linaro.org> <9209a588-b859-1da7-fd4f-2ab317b5c517@linaro.org> <9b425e95-cbf2-1fd7-50b3-c1278b003522@linaro.org> In-Reply-To: <9b425e95-cbf2-1fd7-50b3-c1278b003522@linaro.org> From: Robert Foss Date: Mon, 22 Feb 2021 19:13:52 +0100 Message-ID: Subject: Re: [PATCH v5 09/22] media: camss: Refactor CSID HW version support To: Andrey Konovalov Cc: Andy Gross , Bjorn Andersson , Todor Tomov , Mauro Carvalho Chehab , Rob Herring , angelogioacchino.delregno@somainline.org, MSM , linux-media , "open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" , linux-kernel , AngeloGioacchino Del Regno , Tomasz Figa , Azam Sadiq Pasha Kapatrala Syed , Sarvesh Sridutt , Jonathan Marek , Sakari Ailus Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sun, 21 Feb 2021 at 18:50, Andrey Konovalov 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 > > > > 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 > >> --- > >> > >> 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 > >> +#include > >> +#include > >> +#include > >> +#include > >> + > >> +#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 > >> +#include > >> +#include > >> +#include > >> +#include > >> + > >> +#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 ". > 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 > >> +#include > >> #include > >> #include > >> #include > >> @@ -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 */ > >>