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 HALT_CMD_HALT_AT_FRAME_BOUNDARY 0 109 #define HALT_CMD_RESUME_AT_FRAME_BOUNDARY 1 110 #define RDI_CTRL_HALT_MODE 2 111 112 #define CSID_RDI_FRM_DROP_PATTERN(rdi) ((IS_LITE ? 0x20C : 0x30C)\ 113 + 0x100 * (rdi)) 114 #define CSID_RDI_FRM_DROP_PERIOD(rdi) ((IS_LITE ? 0x210 : 0x310)\ 115 + 0x100 * (rdi)) 116 #define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi) ((IS_LITE ? 0x214 : 0x314)\ 117 + 0x100 * (rdi)) 118 #define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) ((IS_LITE ? 0x218 : 0x318)\ 119 + 0x100 * (rdi)) 120 #define CSID_RDI_RPP_PIX_DROP_PATTERN(rdi) ((IS_LITE ? 0x224 : 0x324)\ 121 + 0x100 * (rdi)) 122 #define CSID_RDI_RPP_PIX_DROP_PERIOD(rdi) ((IS_LITE ? 0x228 : 0x328)\ 123 + 0x100 * (rdi)) 124 #define CSID_RDI_RPP_LINE_DROP_PATTERN(rdi) ((IS_LITE ? 0x22C : 0x32C)\ 125 + 0x100 * (rdi)) 126 #define CSID_RDI_RPP_LINE_DROP_PERIOD(rdi) ((IS_LITE ? 0x230 : 0x330)\ 127 + 0x100 * (rdi)) 128 129 #define CSID_TPG_CTRL 0x600 130 #define TPG_CTRL_TEST_EN 0 131 #define TPG_CTRL_FS_PKT_EN 1 132 #define TPG_CTRL_FE_PKT_EN 2 133 #define TPG_CTRL_NUM_ACTIVE_LANES 4 134 #define TPG_CTRL_CYCLES_BETWEEN_PKTS 8 135 #define TPG_CTRL_NUM_TRAIL_BYTES 20 136 137 #define CSID_TPG_VC_CFG0 0x604 138 #define TPG_VC_CFG0_VC_NUM 0 139 #define TPG_VC_CFG0_NUM_ACTIVE_SLOTS 8 140 #define NUM_ACTIVE_SLOTS_0_ENABLED 0 141 #define NUM_ACTIVE_SLOTS_0_1_ENABLED 1 142 #define NUM_ACTIVE_SLOTS_0_1_2_ENABLED 2 143 #define NUM_ACTIVE_SLOTS_0_1_3_ENABLED 3 144 #define TPG_VC_CFG0_LINE_INTERLEAVING_MODE 10 145 #define INTELEAVING_MODE_INTERLEAVED 0 146 #define INTELEAVING_MODE_ONE_SHOT 1 147 #define TPG_VC_CFG0_NUM_FRAMES 16 148 149 #define CSID_TPG_VC_CFG1 0x608 150 #define TPG_VC_CFG1_H_BLANKING_COUNT 0 151 #define TPG_VC_CFG1_V_BLANKING_COUNT 12 152 #define TPG_VC_CFG1_V_BLANK_FRAME_WIDTH_SEL 24 153 154 #define CSID_TPG_LFSR_SEED 0x60C 155 156 #define CSID_TPG_DT_n_CFG_0(n) (0x610 + (n) * 0xC) 157 #define TPG_DT_n_CFG_0_FRAME_HEIGHT 0 158 #define TPG_DT_n_CFG_0_FRAME_WIDTH 16 159 160 #define CSID_TPG_DT_n_CFG_1(n) (0x614 + (n) * 0xC) 161 #define TPG_DT_n_CFG_1_DATA_TYPE 0 162 #define TPG_DT_n_CFG_1_ECC_XOR_MASK 8 163 #define TPG_DT_n_CFG_1_CRC_XOR_MASK 16 164 165 #define CSID_TPG_DT_n_CFG_2(n) (0x618 + (n) * 0xC) 166 #define TPG_DT_n_CFG_2_PAYLOAD_MODE 0 167 #define TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD 4 168 #define TPG_DT_n_CFG_2_ENCODE_FORMAT 16 169 170 #define CSID_TPG_COLOR_BARS_CFG 0x640 171 #define TPG_COLOR_BARS_CFG_UNICOLOR_BAR_EN 0 172 #define TPG_COLOR_BARS_CFG_UNICOLOR_BAR_SEL 4 173 #define TPG_COLOR_BARS_CFG_SPLIT_EN 5 174 #define TPG_COLOR_BARS_CFG_ROTATE_PERIOD 8 175 176 #define CSID_TPG_COLOR_BOX_CFG 0x644 177 #define TPG_COLOR_BOX_CFG_MODE 0 178 #define TPG_COLOR_BOX_PATTERN_SEL 2 179 180 static const struct csid_format csid_formats[] = { 181 { 182 MEDIA_BUS_FMT_UYVY8_2X8, 183 DATA_TYPE_YUV422_8BIT, 184 DECODE_FORMAT_UNCOMPRESSED_8_BIT, 185 8, 186 2, 187 }, 188 { 189 MEDIA_BUS_FMT_VYUY8_2X8, 190 DATA_TYPE_YUV422_8BIT, 191 DECODE_FORMAT_UNCOMPRESSED_8_BIT, 192 8, 193 2, 194 }, 195 { 196 MEDIA_BUS_FMT_YUYV8_2X8, 197 DATA_TYPE_YUV422_8BIT, 198 DECODE_FORMAT_UNCOMPRESSED_8_BIT, 199 8, 200 2, 201 }, 202 { 203 MEDIA_BUS_FMT_YVYU8_2X8, 204 DATA_TYPE_YUV422_8BIT, 205 DECODE_FORMAT_UNCOMPRESSED_8_BIT, 206 8, 207 2, 208 }, 209 { 210 MEDIA_BUS_FMT_SBGGR8_1X8, 211 DATA_TYPE_RAW_8BIT, 212 DECODE_FORMAT_UNCOMPRESSED_8_BIT, 213 8, 214 1, 215 }, 216 { 217 MEDIA_BUS_FMT_SGBRG8_1X8, 218 DATA_TYPE_RAW_8BIT, 219 DECODE_FORMAT_UNCOMPRESSED_8_BIT, 220 8, 221 1, 222 }, 223 { 224 MEDIA_BUS_FMT_SGRBG8_1X8, 225 DATA_TYPE_RAW_8BIT, 226 DECODE_FORMAT_UNCOMPRESSED_8_BIT, 227 8, 228 1, 229 }, 230 { 231 MEDIA_BUS_FMT_SRGGB8_1X8, 232 DATA_TYPE_RAW_8BIT, 233 DECODE_FORMAT_UNCOMPRESSED_8_BIT, 234 8, 235 1, 236 }, 237 { 238 MEDIA_BUS_FMT_SBGGR10_1X10, 239 DATA_TYPE_RAW_10BIT, 240 DECODE_FORMAT_UNCOMPRESSED_10_BIT, 241 10, 242 1, 243 }, 244 { 245 MEDIA_BUS_FMT_SGBRG10_1X10, 246 DATA_TYPE_RAW_10BIT, 247 DECODE_FORMAT_UNCOMPRESSED_10_BIT, 248 10, 249 1, 250 }, 251 { 252 MEDIA_BUS_FMT_SGRBG10_1X10, 253 DATA_TYPE_RAW_10BIT, 254 DECODE_FORMAT_UNCOMPRESSED_10_BIT, 255 10, 256 1, 257 }, 258 { 259 MEDIA_BUS_FMT_SRGGB10_1X10, 260 DATA_TYPE_RAW_10BIT, 261 DECODE_FORMAT_UNCOMPRESSED_10_BIT, 262 10, 263 1, 264 }, 265 { 266 MEDIA_BUS_FMT_Y8_1X8, 267 DATA_TYPE_RAW_8BIT, 268 DECODE_FORMAT_UNCOMPRESSED_8_BIT, 269 8, 270 1, 271 }, 272 { 273 MEDIA_BUS_FMT_Y10_1X10, 274 DATA_TYPE_RAW_10BIT, 275 DECODE_FORMAT_UNCOMPRESSED_10_BIT, 276 10, 277 1, 278 }, 279 { 280 MEDIA_BUS_FMT_SBGGR12_1X12, 281 DATA_TYPE_RAW_12BIT, 282 DECODE_FORMAT_UNCOMPRESSED_12_BIT, 283 12, 284 1, 285 }, 286 { 287 MEDIA_BUS_FMT_SGBRG12_1X12, 288 DATA_TYPE_RAW_12BIT, 289 DECODE_FORMAT_UNCOMPRESSED_12_BIT, 290 12, 291 1, 292 }, 293 { 294 MEDIA_BUS_FMT_SGRBG12_1X12, 295 DATA_TYPE_RAW_12BIT, 296 DECODE_FORMAT_UNCOMPRESSED_12_BIT, 297 12, 298 1, 299 }, 300 { 301 MEDIA_BUS_FMT_SRGGB12_1X12, 302 DATA_TYPE_RAW_12BIT, 303 DECODE_FORMAT_UNCOMPRESSED_12_BIT, 304 12, 305 1, 306 }, 307 { 308 MEDIA_BUS_FMT_SBGGR14_1X14, 309 DATA_TYPE_RAW_14BIT, 310 DECODE_FORMAT_UNCOMPRESSED_14_BIT, 311 14, 312 1, 313 }, 314 { 315 MEDIA_BUS_FMT_SGBRG14_1X14, 316 DATA_TYPE_RAW_14BIT, 317 DECODE_FORMAT_UNCOMPRESSED_14_BIT, 318 14, 319 1, 320 }, 321 { 322 MEDIA_BUS_FMT_SGRBG14_1X14, 323 DATA_TYPE_RAW_14BIT, 324 DECODE_FORMAT_UNCOMPRESSED_14_BIT, 325 14, 326 1, 327 }, 328 { 329 MEDIA_BUS_FMT_SRGGB14_1X14, 330 DATA_TYPE_RAW_14BIT, 331 DECODE_FORMAT_UNCOMPRESSED_14_BIT, 332 14, 333 1, 334 }, 335 }; 336 337 static void __csid_configure_stream(struct csid_device *csid, u8 enable, u8 vc) 338 { 339 struct csid_testgen_config *tg = &csid->testgen; 340 u32 val; 341 u32 phy_sel = 0; 342 u8 lane_cnt = csid->phy.lane_cnt; 343 /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */ 344 struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc]; 345 const struct csid_format *format = csid_get_fmt_entry(csid->formats, csid->nformats, 346 input_format->code); 347 348 if (!lane_cnt) 349 lane_cnt = 4; 350 351 if (!tg->enabled) 352 phy_sel = csid->phy.csiphy_id; 353 354 if (enable) { 355 /* 356 * DT_ID is a two bit bitfield that is concatenated with 357 * the four least significant bits of the five bit VC 358 * bitfield to generate an internal CID value. 359 * 360 * CSID_RDI_CFG0(vc) 361 * DT_ID : 28:27 362 * VC : 26:22 363 * DT : 21:16 364 * 365 * CID : VC 3:0 << 2 | DT_ID 1:0 366 */ 367 u8 dt_id = vc & 0x03; 368 369 if (tg->enabled) { 370 /* configure one DT, infinite frames */ 371 val = vc << TPG_VC_CFG0_VC_NUM; 372 val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE; 373 val |= 0 << TPG_VC_CFG0_NUM_FRAMES; 374 writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0); 375 376 val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT; 377 val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT; 378 writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1); 379 380 writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED); 381 382 val = (input_format->height & 0x1fff) << TPG_DT_n_CFG_0_FRAME_HEIGHT; 383 val |= (input_format->width & 0x1fff) << TPG_DT_n_CFG_0_FRAME_WIDTH; 384 writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0)); 385 386 val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE; 387 writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0)); 388 389 val = (tg->mode - 1) << TPG_DT_n_CFG_2_PAYLOAD_MODE; 390 val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD; 391 val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT; 392 writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0)); 393 394 writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG); 395 396 writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG); 397 } 398 399 val = 1 << RDI_CFG0_BYTE_CNTR_EN; 400 val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN; 401 val |= 1 << RDI_CFG0_TIMESTAMP_EN; 402 /* note: for non-RDI path, this should be format->decode_format */ 403 val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; 404 val |= format->data_type << RDI_CFG0_DATA_TYPE; 405 val |= vc << RDI_CFG0_VIRTUAL_CHANNEL; 406 val |= dt_id << RDI_CFG0_DT_ID; 407 writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); 408 409 /* CSID_TIMESTAMP_STB_POST_IRQ */ 410 val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL; 411 writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc)); 412 413 val = 1; 414 writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc)); 415 416 val = 0; 417 writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc)); 418 419 val = 1; 420 writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc)); 421 422 val = 0; 423 writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc)); 424 425 val = 1; 426 writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc)); 427 428 val = 0; 429 writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc)); 430 431 val = 1; 432 writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc)); 433 434 val = 0; 435 writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc)); 436 437 val = 0; 438 writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc)); 439 440 val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc)); 441 val |= 1 << RDI_CFG0_ENABLE; 442 writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); 443 } 444 445 if (tg->enabled) { 446 val = enable << TPG_CTRL_TEST_EN; 447 val |= 1 << TPG_CTRL_FS_PKT_EN; 448 val |= 1 << TPG_CTRL_FE_PKT_EN; 449 val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES; 450 val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS; 451 val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES; 452 writel_relaxed(val, csid->base + CSID_TPG_CTRL); 453 } 454 455 val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; 456 val |= csid->phy.lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; 457 val |= phy_sel << CSI2_RX_CFG0_PHY_NUM_SEL; 458 writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0); 459 460 val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN; 461 if (vc > 3) 462 val |= 1 << CSI2_RX_CFG1_VC_MODE; 463 val |= 1 << CSI2_RX_CFG1_MISR_EN; 464 writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1); 465 466 if (enable) 467 val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD; 468 else 469 val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD; 470 writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc)); 471 } 472 473 static void csid_configure_stream(struct csid_device *csid, u8 enable) 474 { 475 u8 i; 476 /* Loop through all enabled VCs and configure stream for each */ 477 for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) 478 if (csid->phy.en_vc & BIT(i)) 479 __csid_configure_stream(csid, enable, i); 480 } 481 482 static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) 483 { 484 if (val > 0 && val <= csid->testgen.nmodes) 485 csid->testgen.mode = val; 486 487 return 0; 488 } 489 490 /* 491 * csid_hw_version - CSID hardware version query 492 * @csid: CSID device 493 * 494 * Return HW version or error 495 */ 496 static u32 csid_hw_version(struct csid_device *csid) 497 { 498 u32 hw_version; 499 u32 hw_gen; 500 u32 hw_rev; 501 u32 hw_step; 502 503 hw_version = readl_relaxed(csid->base + CSID_HW_VERSION); 504 hw_gen = (hw_version >> HW_VERSION_GENERATION) & 0xF; 505 hw_rev = (hw_version >> HW_VERSION_REVISION) & 0xFFF; 506 hw_step = (hw_version >> HW_VERSION_STEPPING) & 0xFFFF; 507 dev_dbg(csid->camss->dev, "CSID HW Version = %u.%u.%u\n", 508 hw_gen, hw_rev, hw_step); 509 510 return hw_version; 511 } 512 513 /* 514 * csid_isr - CSID module interrupt service routine 515 * @irq: Interrupt line 516 * @dev: CSID device 517 * 518 * Return IRQ_HANDLED on success 519 */ 520 static irqreturn_t csid_isr(int irq, void *dev) 521 { 522 struct csid_device *csid = dev; 523 u32 val; 524 u8 reset_done; 525 int i; 526 527 val = readl_relaxed(csid->base + CSID_TOP_IRQ_STATUS); 528 writel_relaxed(val, csid->base + CSID_TOP_IRQ_CLEAR); 529 reset_done = val & BIT(TOP_IRQ_STATUS_RESET_DONE); 530 531 val = readl_relaxed(csid->base + CSID_CSI2_RX_IRQ_STATUS); 532 writel_relaxed(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR); 533 534 /* Read and clear IRQ status for each enabled RDI channel */ 535 for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) 536 if (csid->phy.en_vc & BIT(i)) { 537 val = readl_relaxed(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); 538 writel_relaxed(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); 539 } 540 541 val = 1 << IRQ_CMD_CLEAR; 542 writel_relaxed(val, csid->base + CSID_IRQ_CMD); 543 544 if (reset_done) 545 complete(&csid->reset_complete); 546 547 return IRQ_HANDLED; 548 } 549 550 /* 551 * csid_reset - Trigger reset on CSID module and wait to complete 552 * @csid: CSID device 553 * 554 * Return 0 on success or a negative error code otherwise 555 */ 556 static int csid_reset(struct csid_device *csid) 557 { 558 unsigned long time; 559 u32 val; 560 561 reinit_completion(&csid->reset_complete); 562 563 writel_relaxed(1, csid->base + CSID_TOP_IRQ_CLEAR); 564 writel_relaxed(1, csid->base + CSID_IRQ_CMD); 565 writel_relaxed(1, csid->base + CSID_TOP_IRQ_MASK); 566 writel_relaxed(1, csid->base + CSID_IRQ_CMD); 567 568 /* preserve registers */ 569 val = 0x1e << RST_STROBES; 570 writel_relaxed(val, csid->base + CSID_RST_STROBES); 571 572 time = wait_for_completion_timeout(&csid->reset_complete, 573 msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); 574 if (!time) { 575 dev_err(csid->camss->dev, "CSID reset timeout\n"); 576 return -EIO; 577 } 578 579 return 0; 580 } 581 582 static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code, 583 unsigned int match_format_idx, u32 match_code) 584 { 585 switch (sink_code) { 586 case MEDIA_BUS_FMT_SBGGR10_1X10: 587 { 588 u32 src_code[] = { 589 MEDIA_BUS_FMT_SBGGR10_1X10, 590 MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 591 }; 592 593 return csid_find_code(src_code, ARRAY_SIZE(src_code), 594 match_format_idx, match_code); 595 } 596 case MEDIA_BUS_FMT_Y10_1X10: 597 { 598 u32 src_code[] = { 599 MEDIA_BUS_FMT_Y10_1X10, 600 MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 601 }; 602 603 return csid_find_code(src_code, ARRAY_SIZE(src_code), 604 match_format_idx, match_code); 605 } 606 default: 607 if (match_format_idx > 0) 608 return 0; 609 610 return sink_code; 611 } 612 } 613 614 static void csid_subdev_init(struct csid_device *csid) 615 { 616 csid->formats = csid_formats; 617 csid->nformats = ARRAY_SIZE(csid_formats); 618 csid->testgen.modes = csid_testgen_modes; 619 csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2; 620 } 621 622 const struct csid_hw_ops csid_ops_gen2 = { 623 .configure_stream = csid_configure_stream, 624 .configure_testgen_pattern = csid_configure_testgen_pattern, 625 .hw_version = csid_hw_version, 626 .isr = csid_isr, 627 .reset = csid_reset, 628 .src_pad_code = csid_src_pad_code, 629 .subdev_init = csid_subdev_init, 630 }; 631