Thread (31 messages) flat view 31 messages, 2 authors, 2021-03-11

Re: [PATCH v6 10/22] media: camss: Add support for CSID hardware version Titan 170

From: Robert Foss <hidden>
Date: 2021-03-10 10:13:25
Also in: linux-arm-msm, linux-media, lkml

Hey Andrey,

On Tue, 9 Mar 2021 at 14:54, Andrey Konovalov
[off-list ref] wrote:
Hi Robert,

The testgen_pattern in this version are in the right direction, but
the test patterns aren't working properly in v6:

On db410c:
==========
-----8<-----
$ v4l2-ctl -L -d /dev/v4l-subdev2

Image Processing Controls

                    test_pattern 0x009f0903 (menu)   : min=0 max=7 default=0 value=1
                 0: Disabled
                 1: Incrementing
                 2: Alternating 0x55/0xAA
                 3: All Zeros 0x00
                 4: All Ones 0xFF
                 5: Pseudo-random Data
                 6: User Specified
                 7: Complex pattern
$
-----8<-----
- "max=7" is not right; it should be "max=6", and "7: Complex pattern" should not
   be listed for this SOC.

On db845c:
==========
-----8<-----
$ v4l2-ctl -L -d /dev/v4l-subdev4

Image Processing Controls

                    test_pattern 0x009f0903 (menu)   : min=0 max=10 default=0 value=0
                 0: Disabled
                 1: Incrementing
                 2: Alternating 0x55/0xAA
                 3: All Zeros 0x00
                 4: All Ones 0xFF
                 5: Pseudo-random Data
                 6: User Specified
                 7: Complex pattern
                 8: Color box
                 9: Color bars

Message from syslogd@linaro-gnome at Mar  8 21:09:26 ...
  kernel:[ 3936.604286] Internal error: Oops: 96000004 [#1] PREEMPT SMP

Message from syslogd@linaro-gnome at Mar  8 21:09:26 ...
  kernel:[ 3936.858085] Code: a8c27bfd d50323bf d65f03c0 b4ffff61 (39400020)
Segmentation fault
$
-----8<-----
- "max=10" is too much; it goes beyond the array of test pattern names and segfaults.
Thanks for finding this, and sending the logs!

I'll fix this in v7.
The rest looks good for me.


Thanks,
Andrey

On 04.03.2021 15:03, Robert Foss wrote:
quoted
Add register definitions for version 170 of the Titan architecture
and implement support for the CSID subdevice.

Signed-off-by: Robert Foss <redacted>
Reviewed-by: Andrey Konovalov <redacted>
---

Changes since v5:
  - Andrey: Fix test pattern selection logic
  - Andrey: Add r-b
  - Move Titan 170 specific test modes to this commit


  drivers/media/platform/qcom/camss/Makefile    |   1 +
  .../platform/qcom/camss/camss-csid-170.c      | 601 ++++++++++++++++++
  .../media/platform/qcom/camss/camss-csid.c    |   4 +
  .../media/platform/qcom/camss/camss-csid.h    |   9 +
  .../media/platform/qcom/camss/camss-vfe-170.c |   1 -
  drivers/media/platform/qcom/camss/camss.c     |  62 ++
  6 files changed, 677 insertions(+), 1 deletion(-)
  create mode 100644 drivers/media/platform/qcom/camss/camss-csid-170.c
diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile
index cff388b653ba..0752c46ea37b 100644
--- a/drivers/media/platform/qcom/camss/Makefile
+++ b/drivers/media/platform/qcom/camss/Makefile
@@ -6,6 +6,7 @@ qcom-camss-objs += \
              camss-csid.o \
              camss-csid-4-1.o \
              camss-csid-4-7.o \
+             camss-csid-170.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-170.c b/drivers/media/platform/qcom/camss/camss-csid-170.c
new file mode 100644
index 000000000000..ee16efecd466
--- /dev/null
+++ b/drivers/media/platform/qcom/camss/camss-csid-170.c
@@ -0,0 +1,601 @@
+// 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-csid-gen2.h"
+#include "camss.h"
+
+/* The CSID 2 IP-block is different from the others,
+ * and is of a bare-bones Lite version, with no PIX
+ * interface support. As a result of that it has an
+ * alternate register layout.
+ */
+#define IS_LITE              (csid->id == 2 ? 1 : 0)
+
+#define CSID_HW_VERSION              0x0
+#define              HW_VERSION_STEPPING     0
+#define              HW_VERSION_REVISION     16
+#define              HW_VERSION_GENERATION   28
+
+#define CSID_RST_STROBES     0x10
+#define              RST_STROBES     0
+
+#define CSID_CSI2_RX_IRQ_STATUS      0x20
+#define      CSID_CSI2_RX_IRQ_MASK   0x24
+#define CSID_CSI2_RX_IRQ_CLEAR       0x28
+
+#define CSID_CSI2_RDIN_IRQ_STATUS(rdi)               ((IS_LITE ? 0x30 : 0x40) \
+                                              + 0x10 * (rdi))
+#define CSID_CSI2_RDIN_IRQ_MASK(rdi)         ((IS_LITE ? 0x34 : 0x44) \
+                                              + 0x10 * (rdi))
+#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi)                ((IS_LITE ? 0x38 : 0x48) \
+                                              + 0x10 * (rdi))
+#define CSID_CSI2_RDIN_IRQ_SET(rdi)          ((IS_LITE ? 0x3C : 0x4C) \
+                                              + 0x10 * (rdi))
+
+#define CSID_TOP_IRQ_STATUS  0x70
+#define              TOP_IRQ_STATUS_RESET_DONE 0
+#define CSID_TOP_IRQ_MASK    0x74
+#define CSID_TOP_IRQ_CLEAR   0x78
+#define CSID_TOP_IRQ_SET     0x7C
+#define CSID_IRQ_CMD         0x80
+#define              IRQ_CMD_CLEAR   0
+#define              IRQ_CMD_SET     4
+
+#define CSID_CSI2_RX_CFG0    0x100
+#define              CSI2_RX_CFG0_NUM_ACTIVE_LANES   0
+#define              CSI2_RX_CFG0_DL0_INPUT_SEL      4
+#define              CSI2_RX_CFG0_DL1_INPUT_SEL      8
+#define              CSI2_RX_CFG0_DL2_INPUT_SEL      12
+#define              CSI2_RX_CFG0_DL3_INPUT_SEL      16
+#define              CSI2_RX_CFG0_PHY_NUM_SEL        20
+#define              CSI2_RX_CFG0_PHY_TYPE_SEL       24
+
+#define CSID_CSI2_RX_CFG1    0x104
+#define              CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN           0
+#define              CSI2_RX_CFG1_DE_SCRAMBLE_EN                     1
+#define              CSI2_RX_CFG1_VC_MODE                            2
+#define              CSI2_RX_CFG1_COMPLETE_STREAM_EN                 4
+#define              CSI2_RX_CFG1_COMPLETE_STREAM_FRAME_TIMING       5
+#define              CSI2_RX_CFG1_MISR_EN                            6
+#define              CSI2_RX_CFG1_CGC_MODE                           7
+#define                      CGC_MODE_DYNAMIC_GATING         0
+#define                      CGC_MODE_ALWAYS_ON              1
+
+#define CSID_RDI_CFG0(rdi)                   ((IS_LITE ? 0x200 : 0x300) \
+                                              + 0x100 * (rdi))
+#define              RDI_CFG0_BYTE_CNTR_EN           0
+#define              RDI_CFG0_FORMAT_MEASURE_EN      1
+#define              RDI_CFG0_TIMESTAMP_EN           2
+#define              RDI_CFG0_DROP_H_EN              3
+#define              RDI_CFG0_DROP_V_EN              4
+#define              RDI_CFG0_CROP_H_EN              5
+#define              RDI_CFG0_CROP_V_EN              6
+#define              RDI_CFG0_MISR_EN                7
+#define              RDI_CFG0_CGC_MODE               8
+#define                      CGC_MODE_DYNAMIC        0
+#define                      CGC_MODE_ALWAYS_ON      1
+#define              RDI_CFG0_PLAIN_ALIGNMENT        9
+#define                      PLAIN_ALIGNMENT_LSB     0
+#define                      PLAIN_ALIGNMENT_MSB     1
+#define              RDI_CFG0_PLAIN_FORMAT           10
+#define              RDI_CFG0_DECODE_FORMAT          12
+#define              RDI_CFG0_DATA_TYPE              16
+#define              RDI_CFG0_VIRTUAL_CHANNEL        22
+#define              RDI_CFG0_DT_ID                  27
+#define              RDI_CFG0_EARLY_EOF_EN           29
+#define              RDI_CFG0_PACKING_FORMAT         30
+#define              RDI_CFG0_ENABLE                 31
+
+#define CSID_RDI_CFG1(rdi)                   ((IS_LITE ? 0x204 : 0x304)\
+                                             + 0x100 * (rdi))
+#define              RDI_CFG1_TIMESTAMP_STB_SEL      0
+
+#define CSID_RDI_CTRL(rdi)                   ((IS_LITE ? 0x208 : 0x308)\
+                                             + 0x100 * (rdi))
+#define              RDI_CTRL_HALT_CMD               0
+#define                      ALT_CMD_RESUME_AT_FRAME_BOUNDARY        1
+#define              RDI_CTRL_HALT_MODE              2
+
+#define CSID_RDI_FRM_DROP_PATTERN(rdi)                       ((IS_LITE ? 0x20C : 0x30C)\
+                                                     + 0x100 * (rdi))
+#define CSID_RDI_FRM_DROP_PERIOD(rdi)                        ((IS_LITE ? 0x210 : 0x310)\
+                                                     + 0x100 * (rdi))
+#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi)          ((IS_LITE ? 0x214 : 0x314)\
+                                                     + 0x100 * (rdi))
+#define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi)           ((IS_LITE ? 0x218 : 0x318)\
+                                                     + 0x100 * (rdi))
+#define CSID_RDI_RPP_PIX_DROP_PATTERN(rdi)           ((IS_LITE ? 0x224 : 0x324)\
+                                                     + 0x100 * (rdi))
+#define CSID_RDI_RPP_PIX_DROP_PERIOD(rdi)            ((IS_LITE ? 0x228 : 0x328)\
+                                                     + 0x100 * (rdi))
+#define CSID_RDI_RPP_LINE_DROP_PATTERN(rdi)          ((IS_LITE ? 0x22C : 0x32C)\
+                                                     + 0x100 * (rdi))
+#define CSID_RDI_RPP_LINE_DROP_PERIOD(rdi)           ((IS_LITE ? 0x230 : 0x330)\
+                                                     + 0x100 * (rdi))
+
+#define CSID_TPG_CTRL                0x600
+#define              TPG_CTRL_TEST_EN                0
+#define              TPG_CTRL_FS_PKT_EN              1
+#define              TPG_CTRL_FE_PKT_EN              2
+#define              TPG_CTRL_NUM_ACTIVE_LANES       4
+#define              TPG_CTRL_CYCLES_BETWEEN_PKTS    8
+#define              TPG_CTRL_NUM_TRAIL_BYTES        20
+
+#define CSID_TPG_VC_CFG0     0x604
+#define              TPG_VC_CFG0_VC_NUM                      0
+#define              TPG_VC_CFG0_NUM_ACTIVE_SLOTS            8
+#define                      NUM_ACTIVE_SLOTS_0_ENABLED      0
+#define                      NUM_ACTIVE_SLOTS_0_1_ENABLED    1
+#define                      NUM_ACTIVE_SLOTS_0_1_2_ENABLED  2
+#define                      NUM_ACTIVE_SLOTS_0_1_3_ENABLED  3
+#define              TPG_VC_CFG0_LINE_INTERLEAVING_MODE      10
+#define                      INTELEAVING_MODE_INTERLEAVED    0
+#define                      INTELEAVING_MODE_ONE_SHOT       1
+#define              TPG_VC_CFG0_NUM_FRAMES                  16
+
+#define CSID_TPG_VC_CFG1     0x608
+#define              TPG_VC_CFG1_H_BLANKING_COUNT            0
+#define              TPG_VC_CFG1_V_BLANKING_COUNT            12
+#define              TPG_VC_CFG1_V_BLANK_FRAME_WIDTH_SEL     24
+
+#define CSID_TPG_LFSR_SEED   0x60C
+
+#define CSID_TPG_DT_n_CFG_0(n)       (0x610 + (n) * 0xC)
+#define              TPG_DT_n_CFG_0_FRAME_HEIGHT     0
+#define              TPG_DT_n_CFG_0_FRAME_WIDTH      16
+
+#define CSID_TPG_DT_n_CFG_1(n)       (0x614 + (n) * 0xC)
+#define              TPG_DT_n_CFG_1_DATA_TYPE        0
+#define              TPG_DT_n_CFG_1_ECC_XOR_MASK     8
+#define              TPG_DT_n_CFG_1_CRC_XOR_MASK     16
+
+#define CSID_TPG_DT_n_CFG_2(n)       (0x618 + (n) * 0xC)
+#define              TPG_DT_n_CFG_2_PAYLOAD_MODE             0
+#define              TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD   4
+#define              TPG_DT_n_CFG_2_ENCODE_FORMAT            16
+
+#define CSID_TPG_COLOR_BARS_CFG      0x640
+#define              TPG_COLOR_BARS_CFG_UNICOLOR_BAR_EN      0
+#define              TPG_COLOR_BARS_CFG_UNICOLOR_BAR_SEL     4
+#define              TPG_COLOR_BARS_CFG_SPLIT_EN             5
+#define              TPG_COLOR_BARS_CFG_ROTATE_PERIOD        8
+
+#define CSID_TPG_COLOR_BOX_CFG       0x644
+#define              TPG_COLOR_BOX_CFG_MODE          0
+#define              TPG_COLOR_BOX_PATTERN_SEL       2
+
+
+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_Y10_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,
+     },
+};
+
+static void csid_configure_stream(struct csid_device *csid, u8 enable)
+{
+     struct csid_testgen_config *tg = &csid->testgen;
+     u32 val;
+     u32 phy_sel = 0;
+     u8 lane_cnt = csid->phy.lane_cnt;
+     struct v4l2_mbus_framefmt *input_format =
+                     &csid->fmt[MSM_CSID_PAD_SRC];
+     const struct csid_format *format = csid_get_fmt_entry(
+                     csid->formats, csid->nformats, input_format->code);
+     if (!lane_cnt)
+             lane_cnt = 4;
+
+     if (!tg->enabled)
+             phy_sel = csid->phy.csiphy_id;
+
+     if (enable) {
+             u8 vc = 0; /* Virtual Channel 0 */
+             u8 dt_id = vc * 4;
+
+             if (tg->enabled) {
+                     /* Config Test Generator */
+                     vc = 0xa;
+
+                     /* configure one DT, infinite frames */
+                     val = vc << TPG_VC_CFG0_VC_NUM;
+                     val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE;
+                     val |= 0 << TPG_VC_CFG0_NUM_FRAMES;
+                     writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0);
+
+                     val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT;
+                     val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT;
+                     writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1);
+
+                     writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED);
+
+                     val = input_format->height & 0x1fff << TPG_DT_n_CFG_0_FRAME_HEIGHT;
+                     val |= input_format->width & 0x1fff << TPG_DT_n_CFG_0_FRAME_WIDTH;
+                     writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0));
+
+                     val = DATA_TYPE_RAW_10BIT << TPG_DT_n_CFG_1_DATA_TYPE;
+                     writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
+
+                     val = tg->mode << TPG_DT_n_CFG_2_PAYLOAD_MODE;
+                     val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD;
+                     val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT;
+                     writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0));
+
+                     writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG);
+
+                     writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG);
+             }
+
+             val = 1 << RDI_CFG0_BYTE_CNTR_EN;
+             val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;
+             val |= 1 << RDI_CFG0_TIMESTAMP_EN;
+             val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
+             val |= DATA_TYPE_RAW_10BIT << RDI_CFG0_DATA_TYPE;
+             val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
+             val |= dt_id << RDI_CFG0_DT_ID;
+             writel_relaxed(val, csid->base + CSID_RDI_CFG0(0));
+
+             /* CSID_TIMESTAMP_STB_POST_IRQ */
+             val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;
+             writel_relaxed(val, csid->base + CSID_RDI_CFG1(0));
+
+             val = 1;
+             writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(0));
+
+             val = 0;
+             writel_relaxed(0, csid->base + CSID_RDI_FRM_DROP_PATTERN(0));
+
+             val = 1;
+             writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(0));
+
+             val = 0;
+             writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(0));
+
+             val = 1;
+             writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(0));
+
+             val = 0;
+             writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(0));
+
+             val = 1;
+             writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(0));
+
+             val = 0;
+             writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(0));
+
+             val = 0;
+             writel_relaxed(val, csid->base + CSID_RDI_CTRL(0));
+
+             val = readl_relaxed(csid->base + CSID_RDI_CFG0(0));
+             val |=  1 << RDI_CFG0_ENABLE;
+             writel_relaxed(val, csid->base + CSID_RDI_CFG0(0));
+     }
+
+     if (tg->enabled) {
+             val = enable << TPG_CTRL_TEST_EN;
+             val |= 1 << TPG_CTRL_FS_PKT_EN;
+             val |= 1 << TPG_CTRL_FE_PKT_EN;
+             val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES;
+             val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS;
+             val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES;
+             writel_relaxed(val, csid->base + CSID_TPG_CTRL);
+     }
+
+     val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;
+     val |= csid->phy.lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;
+     val |= phy_sel << CSI2_RX_CFG0_PHY_NUM_SEL;
+     writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0);
+
+
+     val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN;
+     val |= 1 << CSI2_RX_CFG1_MISR_EN;
+     writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1); // csi2_vc_mode_shift_val ?
+
+     /* error irqs start at BIT(11) */
+     writel_relaxed(~0u, csid->base + CSID_CSI2_RX_IRQ_MASK);
+
+     /* RDI irq */
+     writel_relaxed(~0u, csid->base + CSID_TOP_IRQ_MASK);
+
+     val = 1 << RDI_CTRL_HALT_CMD;
+     writel_relaxed(val, csid->base + CSID_RDI_CTRL(0));
+}
+
+static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
+{
+     if (val > 0 && val < csid->testgen.nmodes)
+             csid->testgen.mode = val;
+
+     return 0;
+}
+
+/*
+ * csid_hw_version - CSID hardware version query
+ * @csid: CSID device
+ *
+ * Return HW version or error
+ */
+static u32 csid_hw_version(struct csid_device *csid)
+{
+     u32 hw_version;
+     u32 hw_gen;
+     u32 hw_rev;
+     u32 hw_step;
+
+     hw_version = readl_relaxed(csid->base + CSID_HW_VERSION);
+     hw_gen = (hw_version >> HW_VERSION_GENERATION) & 0xF;
+     hw_rev = (hw_version >> HW_VERSION_REVISION) & 0xFFF;
+     hw_step = (hw_version >> HW_VERSION_STEPPING) & 0xFFFF;
+     dev_dbg(csid->camss->dev, "CSID HW Version = %u.%u.%u\n",
+             hw_gen, hw_rev, hw_step);
+
+     return hw_version;
+}
+
+/*
+ * csid_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 val;
+     u8 reset_done;
+
+     val = readl_relaxed(csid->base + CSID_TOP_IRQ_STATUS);
+     writel_relaxed(val, csid->base + CSID_TOP_IRQ_CLEAR);
+     reset_done = val & BIT(TOP_IRQ_STATUS_RESET_DONE);
+
+     val = readl_relaxed(csid->base + CSID_CSI2_RX_IRQ_STATUS);
+     writel_relaxed(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR);
+
+     val = readl_relaxed(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(0));
+     writel_relaxed(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(0));
+
+     val = 1 << IRQ_CMD_CLEAR;
+     writel_relaxed(val, csid->base + CSID_IRQ_CMD);
+
+     if (reset_done)
+             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;
+     u32 val;
+
+     reinit_completion(&csid->reset_complete);
+
+     writel_relaxed(1, csid->base + CSID_TOP_IRQ_CLEAR);
+     writel_relaxed(1, csid->base + CSID_IRQ_CMD);
+     writel_relaxed(1, csid->base + CSID_TOP_IRQ_MASK);
+     writel_relaxed(1, csid->base + CSID_IRQ_CMD);
+
+     /* preserve registers */
+     val = 0x1e << RST_STROBES;
+     writel_relaxed(val, csid->base + CSID_RST_STROBES);
+
+     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_NUM_SUPPORTED_170;
+}
+
+const struct csid_hw_ops csid_ops_170 = {
+     .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 a76ad213604e..a5a94425923a 100644
--- a/drivers/media/platform/qcom/camss/camss-csid.c
+++ b/drivers/media/platform/qcom/camss/camss-csid.c
@@ -124,6 +124,8 @@ static int csid_set_clock_rates(struct csid_device *csid)
                              dev_err(dev, "clk set rate failed: %d\n", ret);
                              return ret;
                      }
+             } else if (clock->nfreqs) {
+                     clk_set_rate(clock->clk, clock->freq[0]);
              }
      }
@@ -545,6 +547,8 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid,
      } else if (camss->version == CAMSS_8x96 ||
                 camss->version == CAMSS_660) {
              csid->ops = &csid_ops_4_7;
+     } else if (camss->version == CAMSS_845) {
+             csid->ops = &csid_ops_170;
      } else {
              return -EINVAL;
      }
diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h
index 60933f436daa..892150e1f7a0 100644
--- a/drivers/media/platform/qcom/camss/camss-csid.h
+++ b/drivers/media/platform/qcom/camss/camss-csid.h
@@ -58,6 +58,10 @@ enum csid_testgen_mode {
      CSID_PAYLOAD_MODE_USER_SPECIFIED = 6,
      CSID_PAYLOAD_MODE_NUM_SUPPORTED_4_1 = 7,
      CSID_PAYLOAD_MODE_NUM_SUPPORTED_4_7 = 7,
+     CSID_PAYLOAD_MODE_COMPLEX_PATTERN = 7,
+     CSID_PAYLOAD_MODE_COLOR_BOX = 8,
+     CSID_PAYLOAD_MODE_COLOR_BARS = 9,
+     CSID_PAYLOAD_MODE_NUM_SUPPORTED_170 = 10,
  };

  static const char * const csid_testgen_modes[] = {
@@ -68,6 +72,9 @@ static const char * const csid_testgen_modes[] = {
      "All Ones 0xFF",
      "Pseudo-random Data",
      "User Specified",
+     "Complex pattern",
+     "Color box",
+     "Color bars",
  };

  struct csid_format {
@@ -213,5 +220,7 @@ 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;
+extern const struct csid_hw_ops csid_ops_170;
+

  #endif /* QC_MSM_CAMSS_CSID_H */
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-170.c b/drivers/media/platform/qcom/camss/camss-vfe-170.c
index 9ab5964b1e99..ce1130108e01 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-170.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-170.c
@@ -274,7 +274,6 @@ static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line)
      writel_relaxed(val, vfe->base + VFE_BUS_WM_PACKER_CFG(wm)); // XXX 1 for PLAIN8?

      /* Configure stride for RDIs */
-     //val = pix->plane_fmt[0].bytesperline;
      val = WM_STRIDE_DEFAULT_STRIDE;
      writel_relaxed(val, vfe->base + VFE_BUS_WM_STRIDE(wm));
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 0e006def1996..0b1693c34fbc 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -465,6 +465,68 @@ static const struct resources vfe_res_660[] = {
      }
  };

+static const struct resources csid_res_845[] = {
+     /* CSID0 */
+     {
+             .regulator = { "vdda-csi0" },
+             .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src",
+                             "soc_ahb", "vfe0", "vfe0_src",
+                             "vfe0_cphy_rx", "csi0",
+                             "csi0_src" },
+             .clock_rate = { { 0 },
+                             { 384000000 },
+                             { 80000000 },
+                             { 0 },
+                             { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 },
+                             { 320000000 },
+                             { 0 },
+                             { 19200000, 75000000, 384000000, 538666667 },
+                             { 384000000 } },
+             .reg = { "csid0" },
+             .interrupt = { "csid0" }
+     },
+
+     /* CSID1 */
+     {
+             .regulator = { "vdda-csi1" },
+             .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src",
+                             "soc_ahb", "vfe1", "vfe1_src",
+                             "vfe1_cphy_rx", "csi1",
+                             "csi1_src" },
+             .clock_rate = { { 0 },
+                             { 384000000 },
+                             { 80000000 },
+                             { 0 },
+                             { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 },
+                             { 320000000 },
+                             { 0 },
+                             { 19200000, 75000000, 384000000, 538666667 },
+                             { 384000000 } },
+             .reg = { "csid1" },
+             .interrupt = { "csid1" }
+     },
+
+     /* CSID2 */
+     {
+             .regulator = { "vdda-csi2" },
+             .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src",
+                             "soc_ahb", "vfe_lite", "vfe_lite_src",
+                             "vfe_lite_cphy_rx", "csi2",
+                             "csi2_src" },
+             .clock_rate = { { 0 },
+                             { 384000000 },
+                             { 80000000 },
+                             { 0 },
+                             { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 },
+                             { 320000000 },
+                             { 0 },
+                             { 19200000, 75000000, 384000000, 538666667 },
+                             { 384000000 } },
+             .reg = { "csid2" },
+             .interrupt = { "csid2" }
+     }
+};
+
  static const struct resources vfe_res_845[] = {
      /* VFE0 */
      {
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help