linux/drivers/media/platform/qcom/camss/camss-csid-170.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * camss-csid-4-7.c
   4 *
   5 * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module
   6 *
   7 * Copyright (C) 2020 Linaro Ltd.
   8 */
   9#include <linux/completion.h>
  10#include <linux/interrupt.h>
  11#include <linux/io.h>
  12#include <linux/kernel.h>
  13#include <linux/of.h>
  14
  15#include "camss-csid.h"
  16#include "camss-csid-gen2.h"
  17#include "camss.h"
  18
  19/* The CSID 2 IP-block is different from the others,
  20 * and is of a bare-bones Lite version, with no PIX
  21 * interface support. As a result of that it has an
  22 * alternate register layout.
  23 */
  24#define IS_LITE         (csid->id == 2 ? 1 : 0)
  25
  26#define CSID_HW_VERSION         0x0
  27#define         HW_VERSION_STEPPING     0
  28#define         HW_VERSION_REVISION     16
  29#define         HW_VERSION_GENERATION   28
  30
  31#define CSID_RST_STROBES        0x10
  32#define         RST_STROBES     0
  33
  34#define CSID_CSI2_RX_IRQ_STATUS 0x20
  35#define CSID_CSI2_RX_IRQ_MASK   0x24
  36#define CSID_CSI2_RX_IRQ_CLEAR  0x28
  37
  38#define CSID_CSI2_RDIN_IRQ_STATUS(rdi)          ((IS_LITE ? 0x30 : 0x40) \
  39                                                 + 0x10 * (rdi))
  40#define CSID_CSI2_RDIN_IRQ_MASK(rdi)            ((IS_LITE ? 0x34 : 0x44) \
  41                                                 + 0x10 * (rdi))
  42#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi)           ((IS_LITE ? 0x38 : 0x48) \
  43                                                 + 0x10 * (rdi))
  44#define CSID_CSI2_RDIN_IRQ_SET(rdi)             ((IS_LITE ? 0x3C : 0x4C) \
  45                                                 + 0x10 * (rdi))
  46
  47#define CSID_TOP_IRQ_STATUS     0x70
  48#define         TOP_IRQ_STATUS_RESET_DONE 0
  49#define CSID_TOP_IRQ_MASK       0x74
  50#define CSID_TOP_IRQ_CLEAR      0x78
  51#define CSID_TOP_IRQ_SET        0x7C
  52#define CSID_IRQ_CMD            0x80
  53#define         IRQ_CMD_CLEAR   0
  54#define         IRQ_CMD_SET     4
  55
  56#define CSID_CSI2_RX_CFG0       0x100
  57#define         CSI2_RX_CFG0_NUM_ACTIVE_LANES   0
  58#define         CSI2_RX_CFG0_DL0_INPUT_SEL      4
  59#define         CSI2_RX_CFG0_DL1_INPUT_SEL      8
  60#define         CSI2_RX_CFG0_DL2_INPUT_SEL      12
  61#define         CSI2_RX_CFG0_DL3_INPUT_SEL      16
  62#define         CSI2_RX_CFG0_PHY_NUM_SEL        20
  63#define         CSI2_RX_CFG0_PHY_TYPE_SEL       24
  64
  65#define CSID_CSI2_RX_CFG1       0x104
  66#define         CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN           0
  67#define         CSI2_RX_CFG1_DE_SCRAMBLE_EN                     1
  68#define         CSI2_RX_CFG1_VC_MODE                            2
  69#define         CSI2_RX_CFG1_COMPLETE_STREAM_EN                 4
  70#define         CSI2_RX_CFG1_COMPLETE_STREAM_FRAME_TIMING       5
  71#define         CSI2_RX_CFG1_MISR_EN                            6
  72#define         CSI2_RX_CFG1_CGC_MODE                           7
  73#define                 CGC_MODE_DYNAMIC_GATING         0
  74#define                 CGC_MODE_ALWAYS_ON              1
  75
  76#define CSID_RDI_CFG0(rdi)                      ((IS_LITE ? 0x200 : 0x300) \
  77                                                 + 0x100 * (rdi))
  78#define         RDI_CFG0_BYTE_CNTR_EN           0
  79#define         RDI_CFG0_FORMAT_MEASURE_EN      1
  80#define         RDI_CFG0_TIMESTAMP_EN           2
  81#define         RDI_CFG0_DROP_H_EN              3
  82#define         RDI_CFG0_DROP_V_EN              4
  83#define         RDI_CFG0_CROP_H_EN              5
  84#define         RDI_CFG0_CROP_V_EN              6
  85#define         RDI_CFG0_MISR_EN                7
  86#define         RDI_CFG0_CGC_MODE               8
  87#define                 CGC_MODE_DYNAMIC        0
  88#define                 CGC_MODE_ALWAYS_ON      1
  89#define         RDI_CFG0_PLAIN_ALIGNMENT        9
  90#define                 PLAIN_ALIGNMENT_LSB     0
  91#define                 PLAIN_ALIGNMENT_MSB     1
  92#define         RDI_CFG0_PLAIN_FORMAT           10
  93#define         RDI_CFG0_DECODE_FORMAT          12
  94#define         RDI_CFG0_DATA_TYPE              16
  95#define         RDI_CFG0_VIRTUAL_CHANNEL        22
  96#define         RDI_CFG0_DT_ID                  27
  97#define         RDI_CFG0_EARLY_EOF_EN           29
  98#define         RDI_CFG0_PACKING_FORMAT         30
  99#define         RDI_CFG0_ENABLE                 31
 100
 101#define CSID_RDI_CFG1(rdi)                      ((IS_LITE ? 0x204 : 0x304)\
 102                                                + 0x100 * (rdi))
 103#define         RDI_CFG1_TIMESTAMP_STB_SEL      0
 104
 105#define CSID_RDI_CTRL(rdi)                      ((IS_LITE ? 0x208 : 0x308)\
 106                                                + 0x100 * (rdi))
 107#define         RDI_CTRL_HALT_CMD               0
 108#define                 ALT_CMD_RESUME_AT_FRAME_BOUNDARY        1
 109#define         RDI_CTRL_HALT_MODE              2
 110
 111#define CSID_RDI_FRM_DROP_PATTERN(rdi)                  ((IS_LITE ? 0x20C : 0x30C)\
 112                                                        + 0x100 * (rdi))
 113#define CSID_RDI_FRM_DROP_PERIOD(rdi)                   ((IS_LITE ? 0x210 : 0x310)\
 114                                                        + 0x100 * (rdi))
 115#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi)             ((IS_LITE ? 0x214 : 0x314)\
 116                                                        + 0x100 * (rdi))
 117#define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi)              ((IS_LITE ? 0x218 : 0x318)\
 118                                                        + 0x100 * (rdi))
 119#define CSID_RDI_RPP_PIX_DROP_PATTERN(rdi)              ((IS_LITE ? 0x224 : 0x324)\
 120                                                        + 0x100 * (rdi))
 121#define CSID_RDI_RPP_PIX_DROP_PERIOD(rdi)               ((IS_LITE ? 0x228 : 0x328)\
 122                                                        + 0x100 * (rdi))
 123#define CSID_RDI_RPP_LINE_DROP_PATTERN(rdi)             ((IS_LITE ? 0x22C : 0x32C)\
 124                                                        + 0x100 * (rdi))
 125#define CSID_RDI_RPP_LINE_DROP_PERIOD(rdi)              ((IS_LITE ? 0x230 : 0x330)\
 126                                                        + 0x100 * (rdi))
 127
 128#define CSID_TPG_CTRL           0x600
 129#define         TPG_CTRL_TEST_EN                0
 130#define         TPG_CTRL_FS_PKT_EN              1
 131#define         TPG_CTRL_FE_PKT_EN              2
 132#define         TPG_CTRL_NUM_ACTIVE_LANES       4
 133#define         TPG_CTRL_CYCLES_BETWEEN_PKTS    8
 134#define         TPG_CTRL_NUM_TRAIL_BYTES        20
 135
 136#define CSID_TPG_VC_CFG0        0x604
 137#define         TPG_VC_CFG0_VC_NUM                      0
 138#define         TPG_VC_CFG0_NUM_ACTIVE_SLOTS            8
 139#define                 NUM_ACTIVE_SLOTS_0_ENABLED      0
 140#define                 NUM_ACTIVE_SLOTS_0_1_ENABLED    1
 141#define                 NUM_ACTIVE_SLOTS_0_1_2_ENABLED  2
 142#define                 NUM_ACTIVE_SLOTS_0_1_3_ENABLED  3
 143#define         TPG_VC_CFG0_LINE_INTERLEAVING_MODE      10
 144#define                 INTELEAVING_MODE_INTERLEAVED    0
 145#define                 INTELEAVING_MODE_ONE_SHOT       1
 146#define         TPG_VC_CFG0_NUM_FRAMES                  16
 147
 148#define CSID_TPG_VC_CFG1        0x608
 149#define         TPG_VC_CFG1_H_BLANKING_COUNT            0
 150#define         TPG_VC_CFG1_V_BLANKING_COUNT            12
 151#define         TPG_VC_CFG1_V_BLANK_FRAME_WIDTH_SEL     24
 152
 153#define CSID_TPG_LFSR_SEED      0x60C
 154
 155#define CSID_TPG_DT_n_CFG_0(n)  (0x610 + (n) * 0xC)
 156#define         TPG_DT_n_CFG_0_FRAME_HEIGHT     0
 157#define         TPG_DT_n_CFG_0_FRAME_WIDTH      16
 158
 159#define CSID_TPG_DT_n_CFG_1(n)  (0x614 + (n) * 0xC)
 160#define         TPG_DT_n_CFG_1_DATA_TYPE        0
 161#define         TPG_DT_n_CFG_1_ECC_XOR_MASK     8
 162#define         TPG_DT_n_CFG_1_CRC_XOR_MASK     16
 163
 164#define CSID_TPG_DT_n_CFG_2(n)  (0x618 + (n) * 0xC)
 165#define         TPG_DT_n_CFG_2_PAYLOAD_MODE             0
 166#define         TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD   4
 167#define         TPG_DT_n_CFG_2_ENCODE_FORMAT            16
 168
 169#define CSID_TPG_COLOR_BARS_CFG 0x640
 170#define         TPG_COLOR_BARS_CFG_UNICOLOR_BAR_EN      0
 171#define         TPG_COLOR_BARS_CFG_UNICOLOR_BAR_SEL     4
 172#define         TPG_COLOR_BARS_CFG_SPLIT_EN             5
 173#define         TPG_COLOR_BARS_CFG_ROTATE_PERIOD        8
 174
 175#define CSID_TPG_COLOR_BOX_CFG  0x644
 176#define         TPG_COLOR_BOX_CFG_MODE          0
 177#define         TPG_COLOR_BOX_PATTERN_SEL       2
 178
 179static const struct csid_format csid_formats[] = {
 180        {
 181                MEDIA_BUS_FMT_UYVY8_2X8,
 182                DATA_TYPE_YUV422_8BIT,
 183                DECODE_FORMAT_UNCOMPRESSED_8_BIT,
 184                8,
 185                2,
 186        },
 187        {
 188                MEDIA_BUS_FMT_VYUY8_2X8,
 189                DATA_TYPE_YUV422_8BIT,
 190                DECODE_FORMAT_UNCOMPRESSED_8_BIT,
 191                8,
 192                2,
 193        },
 194        {
 195                MEDIA_BUS_FMT_YUYV8_2X8,
 196                DATA_TYPE_YUV422_8BIT,
 197                DECODE_FORMAT_UNCOMPRESSED_8_BIT,
 198                8,
 199                2,
 200        },
 201        {
 202                MEDIA_BUS_FMT_YVYU8_2X8,
 203                DATA_TYPE_YUV422_8BIT,
 204                DECODE_FORMAT_UNCOMPRESSED_8_BIT,
 205                8,
 206                2,
 207        },
 208        {
 209                MEDIA_BUS_FMT_SBGGR8_1X8,
 210                DATA_TYPE_RAW_8BIT,
 211                DECODE_FORMAT_UNCOMPRESSED_8_BIT,
 212                8,
 213                1,
 214        },
 215        {
 216                MEDIA_BUS_FMT_SGBRG8_1X8,
 217                DATA_TYPE_RAW_8BIT,
 218                DECODE_FORMAT_UNCOMPRESSED_8_BIT,
 219                8,
 220                1,
 221        },
 222        {
 223                MEDIA_BUS_FMT_SGRBG8_1X8,
 224                DATA_TYPE_RAW_8BIT,
 225                DECODE_FORMAT_UNCOMPRESSED_8_BIT,
 226                8,
 227                1,
 228        },
 229        {
 230                MEDIA_BUS_FMT_SRGGB8_1X8,
 231                DATA_TYPE_RAW_8BIT,
 232                DECODE_FORMAT_UNCOMPRESSED_8_BIT,
 233                8,
 234                1,
 235        },
 236        {
 237                MEDIA_BUS_FMT_SBGGR10_1X10,
 238                DATA_TYPE_RAW_10BIT,
 239                DECODE_FORMAT_UNCOMPRESSED_10_BIT,
 240                10,
 241                1,
 242        },
 243        {
 244                MEDIA_BUS_FMT_SGBRG10_1X10,
 245                DATA_TYPE_RAW_10BIT,
 246                DECODE_FORMAT_UNCOMPRESSED_10_BIT,
 247                10,
 248                1,
 249        },
 250        {
 251                MEDIA_BUS_FMT_SGRBG10_1X10,
 252                DATA_TYPE_RAW_10BIT,
 253                DECODE_FORMAT_UNCOMPRESSED_10_BIT,
 254                10,
 255                1,
 256        },
 257        {
 258                MEDIA_BUS_FMT_SRGGB10_1X10,
 259                DATA_TYPE_RAW_10BIT,
 260                DECODE_FORMAT_UNCOMPRESSED_10_BIT,
 261                10,
 262                1,
 263        },
 264        {
 265                MEDIA_BUS_FMT_Y10_1X10,
 266                DATA_TYPE_RAW_10BIT,
 267                DECODE_FORMAT_UNCOMPRESSED_10_BIT,
 268                10,
 269                1,
 270        },
 271        {
 272                MEDIA_BUS_FMT_SBGGR12_1X12,
 273                DATA_TYPE_RAW_12BIT,
 274                DECODE_FORMAT_UNCOMPRESSED_12_BIT,
 275                12,
 276                1,
 277        },
 278        {
 279                MEDIA_BUS_FMT_SGBRG12_1X12,
 280                DATA_TYPE_RAW_12BIT,
 281                DECODE_FORMAT_UNCOMPRESSED_12_BIT,
 282                12,
 283                1,
 284        },
 285        {
 286                MEDIA_BUS_FMT_SGRBG12_1X12,
 287                DATA_TYPE_RAW_12BIT,
 288                DECODE_FORMAT_UNCOMPRESSED_12_BIT,
 289                12,
 290                1,
 291        },
 292        {
 293                MEDIA_BUS_FMT_SRGGB12_1X12,
 294                DATA_TYPE_RAW_12BIT,
 295                DECODE_FORMAT_UNCOMPRESSED_12_BIT,
 296                12,
 297                1,
 298        },
 299        {
 300                MEDIA_BUS_FMT_SBGGR14_1X14,
 301                DATA_TYPE_RAW_14BIT,
 302                DECODE_FORMAT_UNCOMPRESSED_14_BIT,
 303                14,
 304                1,
 305        },
 306        {
 307                MEDIA_BUS_FMT_SGBRG14_1X14,
 308                DATA_TYPE_RAW_14BIT,
 309                DECODE_FORMAT_UNCOMPRESSED_14_BIT,
 310                14,
 311                1,
 312        },
 313        {
 314                MEDIA_BUS_FMT_SGRBG14_1X14,
 315                DATA_TYPE_RAW_14BIT,
 316                DECODE_FORMAT_UNCOMPRESSED_14_BIT,
 317                14,
 318                1,
 319        },
 320        {
 321                MEDIA_BUS_FMT_SRGGB14_1X14,
 322                DATA_TYPE_RAW_14BIT,
 323                DECODE_FORMAT_UNCOMPRESSED_14_BIT,
 324                14,
 325                1,
 326        },
 327};
 328
 329static void csid_configure_stream(struct csid_device *csid, u8 enable)
 330{
 331        struct csid_testgen_config *tg = &csid->testgen;
 332        u32 val;
 333        u32 phy_sel = 0;
 334        u8 lane_cnt = csid->phy.lane_cnt;
 335        struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_SRC];
 336        const struct csid_format *format = csid_get_fmt_entry(csid->formats, csid->nformats,
 337                                                              input_format->code);
 338
 339        if (!lane_cnt)
 340                lane_cnt = 4;
 341
 342        if (!tg->enabled)
 343                phy_sel = csid->phy.csiphy_id;
 344
 345        if (enable) {
 346                u8 vc = 0; /* Virtual Channel 0 */
 347                u8 dt_id = vc * 4;
 348
 349                if (tg->enabled) {
 350                        /* Config Test Generator */
 351                        vc = 0xa;
 352
 353                        /* configure one DT, infinite frames */
 354                        val = vc << TPG_VC_CFG0_VC_NUM;
 355                        val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE;
 356                        val |= 0 << TPG_VC_CFG0_NUM_FRAMES;
 357                        writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0);
 358
 359                        val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT;
 360                        val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT;
 361                        writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1);
 362
 363                        writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED);
 364
 365                        val = input_format->height & 0x1fff << TPG_DT_n_CFG_0_FRAME_HEIGHT;
 366                        val |= input_format->width & 0x1fff << TPG_DT_n_CFG_0_FRAME_WIDTH;
 367                        writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0));
 368
 369                        val = DATA_TYPE_RAW_10BIT << TPG_DT_n_CFG_1_DATA_TYPE;
 370                        writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
 371
 372                        val = tg->mode << TPG_DT_n_CFG_2_PAYLOAD_MODE;
 373                        val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD;
 374                        val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT;
 375                        writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0));
 376
 377                        writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG);
 378
 379                        writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG);
 380                }
 381
 382                val = 1 << RDI_CFG0_BYTE_CNTR_EN;
 383                val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;
 384                val |= 1 << RDI_CFG0_TIMESTAMP_EN;
 385                val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
 386                val |= DATA_TYPE_RAW_10BIT << RDI_CFG0_DATA_TYPE;
 387                val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
 388                val |= dt_id << RDI_CFG0_DT_ID;
 389                writel_relaxed(val, csid->base + CSID_RDI_CFG0(0));
 390
 391                /* CSID_TIMESTAMP_STB_POST_IRQ */
 392                val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;
 393                writel_relaxed(val, csid->base + CSID_RDI_CFG1(0));
 394
 395                val = 1;
 396                writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(0));
 397
 398                val = 0;
 399                writel_relaxed(0, csid->base + CSID_RDI_FRM_DROP_PATTERN(0));
 400
 401                val = 1;
 402                writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(0));
 403
 404                val = 0;
 405                writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(0));
 406
 407                val = 1;
 408                writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(0));
 409
 410                val = 0;
 411                writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(0));
 412
 413                val = 1;
 414                writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(0));
 415
 416                val = 0;
 417                writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(0));
 418
 419                val = 0;
 420                writel_relaxed(val, csid->base + CSID_RDI_CTRL(0));
 421
 422                val = readl_relaxed(csid->base + CSID_RDI_CFG0(0));
 423                val |=  1 << RDI_CFG0_ENABLE;
 424                writel_relaxed(val, csid->base + CSID_RDI_CFG0(0));
 425        }
 426
 427        if (tg->enabled) {
 428                val = enable << TPG_CTRL_TEST_EN;
 429                val |= 1 << TPG_CTRL_FS_PKT_EN;
 430                val |= 1 << TPG_CTRL_FE_PKT_EN;
 431                val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES;
 432                val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS;
 433                val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES;
 434                writel_relaxed(val, csid->base + CSID_TPG_CTRL);
 435        }
 436
 437        val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;
 438        val |= csid->phy.lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;
 439        val |= phy_sel << CSI2_RX_CFG0_PHY_NUM_SEL;
 440        writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0);
 441
 442        val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN;
 443        val |= 1 << CSI2_RX_CFG1_MISR_EN;
 444        writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1); // csi2_vc_mode_shift_val ?
 445
 446        /* error irqs start at BIT(11) */
 447        writel_relaxed(~0u, csid->base + CSID_CSI2_RX_IRQ_MASK);
 448
 449        /* RDI irq */
 450        writel_relaxed(~0u, csid->base + CSID_TOP_IRQ_MASK);
 451
 452        val = 1 << RDI_CTRL_HALT_CMD;
 453        writel_relaxed(val, csid->base + CSID_RDI_CTRL(0));
 454}
 455
 456static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
 457{
 458        if (val > 0 && val <= csid->testgen.nmodes)
 459                csid->testgen.mode = val;
 460
 461        return 0;
 462}
 463
 464/*
 465 * csid_hw_version - CSID hardware version query
 466 * @csid: CSID device
 467 *
 468 * Return HW version or error
 469 */
 470static u32 csid_hw_version(struct csid_device *csid)
 471{
 472        u32 hw_version;
 473        u32 hw_gen;
 474        u32 hw_rev;
 475        u32 hw_step;
 476
 477        hw_version = readl_relaxed(csid->base + CSID_HW_VERSION);
 478        hw_gen = (hw_version >> HW_VERSION_GENERATION) & 0xF;
 479        hw_rev = (hw_version >> HW_VERSION_REVISION) & 0xFFF;
 480        hw_step = (hw_version >> HW_VERSION_STEPPING) & 0xFFFF;
 481        dev_dbg(csid->camss->dev, "CSID HW Version = %u.%u.%u\n",
 482                hw_gen, hw_rev, hw_step);
 483
 484        return hw_version;
 485}
 486
 487/*
 488 * csid_isr - CSID module interrupt service routine
 489 * @irq: Interrupt line
 490 * @dev: CSID device
 491 *
 492 * Return IRQ_HANDLED on success
 493 */
 494static irqreturn_t csid_isr(int irq, void *dev)
 495{
 496        struct csid_device *csid = dev;
 497        u32 val;
 498        u8 reset_done;
 499
 500        val = readl_relaxed(csid->base + CSID_TOP_IRQ_STATUS);
 501        writel_relaxed(val, csid->base + CSID_TOP_IRQ_CLEAR);
 502        reset_done = val & BIT(TOP_IRQ_STATUS_RESET_DONE);
 503
 504        val = readl_relaxed(csid->base + CSID_CSI2_RX_IRQ_STATUS);
 505        writel_relaxed(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR);
 506
 507        val = readl_relaxed(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(0));
 508        writel_relaxed(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(0));
 509
 510        val = 1 << IRQ_CMD_CLEAR;
 511        writel_relaxed(val, csid->base + CSID_IRQ_CMD);
 512
 513        if (reset_done)
 514                complete(&csid->reset_complete);
 515
 516        return IRQ_HANDLED;
 517}
 518
 519/*
 520 * csid_reset - Trigger reset on CSID module and wait to complete
 521 * @csid: CSID device
 522 *
 523 * Return 0 on success or a negative error code otherwise
 524 */
 525static int csid_reset(struct csid_device *csid)
 526{
 527        unsigned long time;
 528        u32 val;
 529
 530        reinit_completion(&csid->reset_complete);
 531
 532        writel_relaxed(1, csid->base + CSID_TOP_IRQ_CLEAR);
 533        writel_relaxed(1, csid->base + CSID_IRQ_CMD);
 534        writel_relaxed(1, csid->base + CSID_TOP_IRQ_MASK);
 535        writel_relaxed(1, csid->base + CSID_IRQ_CMD);
 536
 537        /* preserve registers */
 538        val = 0x1e << RST_STROBES;
 539        writel_relaxed(val, csid->base + CSID_RST_STROBES);
 540
 541        time = wait_for_completion_timeout(&csid->reset_complete,
 542                                           msecs_to_jiffies(CSID_RESET_TIMEOUT_MS));
 543        if (!time) {
 544                dev_err(csid->camss->dev, "CSID reset timeout\n");
 545                return -EIO;
 546        }
 547
 548        return 0;
 549}
 550
 551static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code,
 552                             unsigned int match_format_idx, u32 match_code)
 553{
 554        switch (sink_code) {
 555        case MEDIA_BUS_FMT_SBGGR10_1X10:
 556        {
 557                u32 src_code[] = {
 558                        MEDIA_BUS_FMT_SBGGR10_1X10,
 559                        MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,
 560                };
 561
 562                return csid_find_code(src_code, ARRAY_SIZE(src_code),
 563                                      match_format_idx, match_code);
 564        }
 565        case MEDIA_BUS_FMT_Y10_1X10:
 566        {
 567                u32 src_code[] = {
 568                        MEDIA_BUS_FMT_Y10_1X10,
 569                        MEDIA_BUS_FMT_Y10_2X8_PADHI_LE,
 570                };
 571
 572                return csid_find_code(src_code, ARRAY_SIZE(src_code),
 573                                      match_format_idx, match_code);
 574        }
 575        default:
 576                if (match_format_idx > 0)
 577                        return 0;
 578
 579                return sink_code;
 580        }
 581}
 582
 583static void csid_subdev_init(struct csid_device *csid)
 584{
 585        csid->formats = csid_formats;
 586        csid->nformats = ARRAY_SIZE(csid_formats);
 587        csid->testgen.modes = csid_testgen_modes;
 588        csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2;
 589}
 590
 591const struct csid_hw_ops csid_ops_170 = {
 592        .configure_stream = csid_configure_stream,
 593        .configure_testgen_pattern = csid_configure_testgen_pattern,
 594        .hw_version = csid_hw_version,
 595        .isr = csid_isr,
 596        .reset = csid_reset,
 597        .src_pad_code = csid_src_pad_code,
 598        .subdev_init = csid_subdev_init,
 599};
 600