media: qcom: camss: Split testgen, RDI and RX for CSID 170
authorMilen Mitkov <quic_mmitkov@quicinc.com>
Wed, 22 May 2024 15:46:57 +0000 (18:46 +0300)
committerHans Verkuil <hverkuil-cisco@xs4all.nl>
Sat, 29 Jun 2024 10:20:04 +0000 (12:20 +0200)
Split the RAW interface (RDI), the CSID receiver (RX)
and test pattern generator (testgen), configurations
for CSID on Titan 170

Signed-off-by: Milen Mitkov <quic_mmitkov@quicinc.com>
Signed-off-by: Gjorgji Rosikopulos <quic_grosikop@quicinc.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp/sm8250/sdm845/apq8016
Acked-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
[hverkuil: folded https://lore.kernel.org/linux-media/20240626074730.85-1-quic_grosikop@quicinc.com/ into this patch]

drivers/media/platform/qcom/camss/camss-csid-gen2.c

index eb5dabe2639ae1ead9710a46c40909dff8d7d56d..e1c757933e2733a0ec8d6bd068ec295925fd9e21 100644 (file)
 #define                TPG_COLOR_BOX_CFG_MODE          0
 #define                TPG_COLOR_BOX_PATTERN_SEL       2
 
-static void __csid_configure_stream(struct csid_device *csid, u8 enable, u8 vc)
+static void __csid_configure_rx(struct csid_device *csid,
+                               struct csid_phy_config *phy, int vc)
 {
-       struct csid_testgen_config *tg = &csid->testgen;
-       u32 val;
-       u32 phy_sel = 0;
        u8 lane_cnt = csid->phy.lane_cnt;
-       /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
-       struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
-       const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats,
-                                                                  csid->res->formats->nformats,
-                                                                  input_format->code);
+       int val;
 
        if (!lane_cnt)
                lane_cnt = 4;
 
-       if (!tg->enabled)
-               phy_sel = csid->phy.csiphy_id;
-
-       if (enable) {
-               /*
-                * DT_ID is a two bit bitfield that is concatenated with
-                * the four least significant bits of the five bit VC
-                * bitfield to generate an internal CID value.
-                *
-                * CSID_RDI_CFG0(vc)
-                * DT_ID : 28:27
-                * VC    : 26:22
-                * DT    : 21:16
-                *
-                * CID   : VC 3:0 << 2 | DT_ID 1:0
-                */
-               u8 dt_id = vc & 0x03;
-
-               if (tg->enabled) {
-                       /* 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 = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE;
-                       writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
-
-                       val = (tg->mode - 1) << 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 = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;
+       val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;
+       val |= phy->csiphy_id << CSI2_RX_CFG0_PHY_NUM_SEL;
+       writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0);
 
-               val = 1 << RDI_CFG0_BYTE_CNTR_EN;
-               val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;
-               val |= 1 << RDI_CFG0_TIMESTAMP_EN;
-               /* note: for non-RDI path, this should be format->decode_format */
-               val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
-               val |= format->data_type << 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(vc));
+       val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN;
+       if (vc > 3)
+               val |= 1 << CSI2_RX_CFG1_VC_MODE;
+       val |= 1 << CSI2_RX_CFG1_MISR_EN;
+       writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1);
+}
 
-               /* CSID_TIMESTAMP_STB_POST_IRQ */
-               val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;
-               writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc));
+static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi)
+{
+       int val;
 
-               val = 1;
-               writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc));
+       if (enable)
+               val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
+       else
+               val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
+       writel_relaxed(val, csid->base + CSID_RDI_CTRL(rdi));
+}
 
-               val = 0;
-               writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc));
+static void __csid_configure_testgen(struct csid_device *csid, u8 enable, u8 vc)
+{
+       struct csid_testgen_config *tg = &csid->testgen;
+       struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
+       const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats,
+                                                                  csid->res->formats->nformats,
+                                                                  input_format->code);
+       u8 lane_cnt = csid->phy.lane_cnt;
+       u32 val;
 
-               val = 1;
-               writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));
+       if (!lane_cnt)
+               lane_cnt = 4;
 
-               val = 0;
-               writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));
+       /* 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 = 1;
-               writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc));
+       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);
 
-               val = 0;
-               writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc));
+       writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED);
 
-               val = 1;
-               writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc));
+       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 = 0;
-               writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc));
+       val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE;
+       writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
 
-               val = 0;
-               writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));
+       val = (tg->mode - 1) << 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));
 
-               val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc));
-               val |=  1 << RDI_CFG0_ENABLE;
-               writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
-       }
+       writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG);
 
-       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);
-       }
+       writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG);
 
-       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 = 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 = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN;
-       if (vc > 3)
-               val |= 1 << CSI2_RX_CFG1_VC_MODE;
-       val |= 1 << CSI2_RX_CFG1_MISR_EN;
-       writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1);
+static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc)
+{
+       /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
+       struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
+       const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats,
+                                                                  csid->res->formats->nformats,
+                                                                  input_format->code);
+       u32 val;
 
-       if (enable)
-               val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
-       else
-               val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
+       /*
+        * DT_ID is a two bit bitfield that is concatenated with
+        * the four least significant bits of the five bit VC
+        * bitfield to generate an internal CID value.
+        *
+        * CSID_RDI_CFG0(vc)
+        * DT_ID : 28:27
+        * VC    : 26:22
+        * DT    : 21:16
+        *
+        * CID   : VC 3:0 << 2 | DT_ID 1:0
+        */
+       u8 dt_id = vc & 0x03;
+
+       val = 1 << RDI_CFG0_BYTE_CNTR_EN;
+       val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;
+       val |= 1 << RDI_CFG0_TIMESTAMP_EN;
+       /* note: for non-RDI path, this should be format->decode_format */
+       val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
+       val |= format->data_type << 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(vc));
+
+       /* CSID_TIMESTAMP_STB_POST_IRQ */
+       val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;
+       writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc));
+
+       val = 1;
+       writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc));
+
+       val = 0;
+       writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc));
+
+       val = 1;
+       writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));
+
+       val = 0;
+       writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));
+
+       val = 1;
+       writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc));
+
+       val = 0;
+       writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc));
+
+       val = 1;
+       writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc));
+
+       val = 0;
+       writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc));
+
+       val = 0;
        writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));
+
+       val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc));
+       val |=  enable << RDI_CFG0_ENABLE;
+       writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
 }
 
 static void csid_configure_stream(struct csid_device *csid, u8 enable)
 {
+       struct csid_testgen_config *tg = &csid->testgen;
        u8 i;
        /* Loop through all enabled VCs and configure stream for each */
        for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
-               if (csid->phy.en_vc & BIT(i))
-                       __csid_configure_stream(csid, enable, i);
+               if (csid->phy.en_vc & BIT(i)) {
+                       if (tg->enabled)
+                               __csid_configure_testgen(csid, enable, i);
+
+                       __csid_configure_rdi_stream(csid, enable, i);
+                       __csid_configure_rx(csid, &csid->phy, i);
+                       __csid_ctrl_rdi(csid, enable, i);
+               }
 }
 
 static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)