1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Rockchip Camera Interface (CIF) Driver 4 * 5 * Copyright (C) 2018 Rockchip Electronics Co., Ltd. 6 * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net> 7 * Copyright (C) 2025 Collabora, Ltd. 8 */ 9 10 #include <linux/interrupt.h> 11 12 #include <media/mipi-csi2.h> 13 #include <media/v4l2-common.h> 14 #include <media/v4l2-event.h> 15 #include <media/v4l2-fh.h> 16 #include <media/v4l2-fwnode.h> 17 #include <media/v4l2-ioctl.h> 18 #include <media/v4l2-mc.h> 19 #include <media/v4l2-subdev.h> 20 21 #include "rkcif-capture-mipi.h" 22 #include "rkcif-common.h" 23 #include "rkcif-interface.h" 24 #include "rkcif-regs.h" 25 #include "rkcif-stream.h" 26 27 #define RK3568_MIPI_CTRL0_HIGH_ALIGN BIT(31) 28 #define RK3568_MIPI_CTRL0_UV_SWAP_EN BIT(7) 29 #define RK3568_MIPI_CTRL0_COMPACT_EN BIT(6) 30 #define RK3568_MIPI_CTRL0_CROP_EN BIT(5) 31 #define RK3568_MIPI_CTRL0_WRDDR(type) ((type) << 1) 32 33 #define RKCIF_MIPI_CTRL0_DT_ID(id) ((id) << 10) 34 #define RKCIF_MIPI_CTRL0_VC_ID(id) ((id) << 8) 35 #define RKCIF_MIPI_CTRL0_CAP_EN BIT(0) 36 37 #define RKCIF_MIPI_INT_FRAME0_END(id) BIT(8 + (id) * 2 + 0) 38 #define RKCIF_MIPI_INT_FRAME1_END(id) BIT(8 + (id) * 2 + 1) 39 40 static const struct rkcif_output_fmt mipi_out_fmts[] = { 41 /* YUV formats */ 42 { 43 .fourcc = V4L2_PIX_FMT_YUYV, 44 .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16, 45 .depth = 16, 46 .cplanes = 1, 47 .mipi = { 48 .dt = MIPI_CSI2_DT_YUV422_8B, 49 .type = RKCIF_MIPI_TYPE_RAW8, 50 }, 51 }, 52 { 53 .fourcc = V4L2_PIX_FMT_UYVY, 54 .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, 55 .depth = 16, 56 .cplanes = 1, 57 .mipi = { 58 .dt = MIPI_CSI2_DT_YUV422_8B, 59 .type = RKCIF_MIPI_TYPE_RAW8, 60 }, 61 }, 62 { 63 .fourcc = V4L2_PIX_FMT_YVYU, 64 .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16, 65 .depth = 16, 66 .cplanes = 1, 67 .mipi = { 68 .dt = MIPI_CSI2_DT_YUV422_8B, 69 .type = RKCIF_MIPI_TYPE_RAW8, 70 }, 71 }, 72 { 73 .fourcc = V4L2_PIX_FMT_VYUY, 74 .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16, 75 .depth = 16, 76 .cplanes = 1, 77 .mipi = { 78 .dt = MIPI_CSI2_DT_YUV422_8B, 79 .type = RKCIF_MIPI_TYPE_RAW8, 80 }, 81 }, 82 /* RGB formats */ 83 { 84 .fourcc = V4L2_PIX_FMT_RGB24, 85 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, 86 .depth = 24, 87 .cplanes = 1, 88 .mipi = { 89 .dt = MIPI_CSI2_DT_RGB888, 90 .type = RKCIF_MIPI_TYPE_RGB888, 91 }, 92 }, 93 { 94 .fourcc = V4L2_PIX_FMT_BGR24, 95 .mbus_code = MEDIA_BUS_FMT_BGR888_1X24, 96 .depth = 24, 97 .cplanes = 1, 98 .mipi = { 99 .dt = MIPI_CSI2_DT_RGB888, 100 .type = RKCIF_MIPI_TYPE_RGB888, 101 }, 102 }, 103 /* Bayer formats */ 104 { 105 .fourcc = V4L2_PIX_FMT_SBGGR8, 106 .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, 107 .depth = 8, 108 .cplanes = 1, 109 .mipi = { 110 .dt = MIPI_CSI2_DT_RAW8, 111 .type = RKCIF_MIPI_TYPE_RAW8, 112 }, 113 }, 114 { 115 .fourcc = V4L2_PIX_FMT_SGBRG8, 116 .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, 117 .depth = 8, 118 .cplanes = 1, 119 .mipi = { 120 .dt = MIPI_CSI2_DT_RAW8, 121 .type = RKCIF_MIPI_TYPE_RAW8, 122 }, 123 }, 124 { 125 .fourcc = V4L2_PIX_FMT_SGRBG8, 126 .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, 127 .depth = 8, 128 .cplanes = 1, 129 .mipi = { 130 .dt = MIPI_CSI2_DT_RAW8, 131 .type = RKCIF_MIPI_TYPE_RAW8, 132 }, 133 }, 134 { 135 .fourcc = V4L2_PIX_FMT_SRGGB8, 136 .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, 137 .depth = 8, 138 .cplanes = 1, 139 .mipi = { 140 .dt = MIPI_CSI2_DT_RAW8, 141 .type = RKCIF_MIPI_TYPE_RAW8, 142 }, 143 }, 144 { 145 .fourcc = V4L2_PIX_FMT_SBGGR10, 146 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, 147 .depth = 10, 148 .cplanes = 1, 149 .mipi = { 150 .dt = MIPI_CSI2_DT_RAW10, 151 .type = RKCIF_MIPI_TYPE_RAW10, 152 }, 153 }, 154 { 155 .fourcc = V4L2_PIX_FMT_SBGGR10P, 156 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, 157 .depth = 10, 158 .cplanes = 1, 159 .mipi = { 160 .dt = MIPI_CSI2_DT_RAW10, 161 .compact = true, 162 .type = RKCIF_MIPI_TYPE_RAW10, 163 }, 164 }, 165 { 166 .fourcc = V4L2_PIX_FMT_SGBRG10, 167 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, 168 .depth = 10, 169 .cplanes = 1, 170 .mipi = { 171 .dt = MIPI_CSI2_DT_RAW10, 172 .type = RKCIF_MIPI_TYPE_RAW10, 173 }, 174 }, 175 { 176 .fourcc = V4L2_PIX_FMT_SGBRG10P, 177 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, 178 .depth = 10, 179 .cplanes = 1, 180 .mipi = { 181 .dt = MIPI_CSI2_DT_RAW10, 182 .compact = true, 183 .type = RKCIF_MIPI_TYPE_RAW10, 184 }, 185 }, 186 { 187 .fourcc = V4L2_PIX_FMT_SGRBG10, 188 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, 189 .depth = 10, 190 .cplanes = 1, 191 .mipi = { 192 .dt = MIPI_CSI2_DT_RAW10, 193 .type = RKCIF_MIPI_TYPE_RAW10, 194 }, 195 }, 196 { 197 .fourcc = V4L2_PIX_FMT_SGRBG10P, 198 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, 199 .depth = 10, 200 .cplanes = 1, 201 .mipi = { 202 .dt = MIPI_CSI2_DT_RAW10, 203 .compact = true, 204 .type = RKCIF_MIPI_TYPE_RAW10, 205 }, 206 }, 207 { 208 .fourcc = V4L2_PIX_FMT_SRGGB10, 209 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, 210 .depth = 10, 211 .cplanes = 1, 212 .mipi = { 213 .dt = MIPI_CSI2_DT_RAW10, 214 .type = RKCIF_MIPI_TYPE_RAW10, 215 }, 216 }, 217 { 218 .fourcc = V4L2_PIX_FMT_SRGGB10P, 219 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, 220 .depth = 10, 221 .cplanes = 1, 222 .mipi = { 223 .dt = MIPI_CSI2_DT_RAW10, 224 .compact = true, 225 .type = RKCIF_MIPI_TYPE_RAW10, 226 }, 227 }, 228 { 229 .fourcc = V4L2_PIX_FMT_SBGGR12, 230 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, 231 .depth = 12, 232 .cplanes = 1, 233 .mipi = { 234 .dt = MIPI_CSI2_DT_RAW12, 235 .type = RKCIF_MIPI_TYPE_RAW12, 236 }, 237 }, 238 { 239 .fourcc = V4L2_PIX_FMT_SBGGR12P, 240 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, 241 .depth = 12, 242 .cplanes = 1, 243 .mipi = { 244 .dt = MIPI_CSI2_DT_RAW12, 245 .compact = true, 246 .type = RKCIF_MIPI_TYPE_RAW12, 247 }, 248 }, 249 { 250 .fourcc = V4L2_PIX_FMT_SGBRG12, 251 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, 252 .depth = 12, 253 .cplanes = 1, 254 .mipi = { 255 .dt = MIPI_CSI2_DT_RAW12, 256 .type = RKCIF_MIPI_TYPE_RAW12, 257 }, 258 }, 259 { 260 .fourcc = V4L2_PIX_FMT_SGBRG12P, 261 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, 262 .depth = 12, 263 .cplanes = 1, 264 .mipi = { 265 .dt = MIPI_CSI2_DT_RAW12, 266 .compact = true, 267 .type = RKCIF_MIPI_TYPE_RAW12, 268 }, 269 }, 270 { 271 .fourcc = V4L2_PIX_FMT_SGRBG12, 272 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, 273 .depth = 12, 274 .cplanes = 1, 275 .mipi = { 276 .dt = MIPI_CSI2_DT_RAW12, 277 .type = RKCIF_MIPI_TYPE_RAW12, 278 }, 279 }, 280 { 281 .fourcc = V4L2_PIX_FMT_SGRBG12P, 282 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, 283 .depth = 12, 284 .cplanes = 1, 285 .mipi = { 286 .dt = MIPI_CSI2_DT_RAW12, 287 .compact = true, 288 .type = RKCIF_MIPI_TYPE_RAW12, 289 }, 290 }, 291 { 292 .fourcc = V4L2_PIX_FMT_SRGGB12, 293 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, 294 .depth = 12, 295 .cplanes = 1, 296 .mipi = { 297 .dt = MIPI_CSI2_DT_RAW12, 298 .type = RKCIF_MIPI_TYPE_RAW12, 299 }, 300 }, 301 { 302 .fourcc = V4L2_PIX_FMT_SRGGB12P, 303 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, 304 .depth = 12, 305 .cplanes = 1, 306 .mipi = { 307 .dt = MIPI_CSI2_DT_RAW12, 308 .compact = true, 309 .type = RKCIF_MIPI_TYPE_RAW12, 310 }, 311 }, 312 }; 313 314 static const struct rkcif_input_fmt mipi_in_fmts[] = { 315 /* YUV formats */ 316 { 317 .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16, 318 }, 319 { 320 .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, 321 }, 322 { 323 .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16, 324 }, 325 { 326 .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16, 327 }, 328 /* RGB formats */ 329 { 330 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, 331 }, 332 { 333 .mbus_code = MEDIA_BUS_FMT_BGR888_1X24, 334 }, 335 /* Bayer formats */ 336 { 337 .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, 338 }, 339 { 340 .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, 341 }, 342 { 343 .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, 344 }, 345 { 346 .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, 347 }, 348 { 349 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, 350 }, 351 { 352 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, 353 }, 354 { 355 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, 356 }, 357 { 358 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, 359 }, 360 { 361 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, 362 }, 363 { 364 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, 365 }, 366 { 367 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, 368 }, 369 { 370 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, 371 }, 372 }; 373 374 static u32 375 rkcif_rk3568_mipi_ctrl0(struct rkcif_stream *stream, 376 const struct rkcif_output_fmt *active_out_fmt) 377 { 378 u32 ctrl0 = 0; 379 380 ctrl0 |= RKCIF_MIPI_CTRL0_DT_ID(active_out_fmt->mipi.dt); 381 ctrl0 |= RKCIF_MIPI_CTRL0_CAP_EN; 382 ctrl0 |= RK3568_MIPI_CTRL0_CROP_EN; 383 384 if (active_out_fmt->mipi.compact) 385 ctrl0 |= RK3568_MIPI_CTRL0_COMPACT_EN; 386 387 switch (active_out_fmt->mipi.type) { 388 case RKCIF_MIPI_TYPE_RAW8: 389 break; 390 case RKCIF_MIPI_TYPE_RAW10: 391 ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x1); 392 break; 393 case RKCIF_MIPI_TYPE_RAW12: 394 ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x2); 395 break; 396 case RKCIF_MIPI_TYPE_RGB888: 397 ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x3); 398 break; 399 case RKCIF_MIPI_TYPE_YUV422SP: 400 ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x4); 401 break; 402 case RKCIF_MIPI_TYPE_YUV420SP: 403 ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x5); 404 break; 405 case RKCIF_MIPI_TYPE_YUV400: 406 ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x6); 407 break; 408 default: 409 break; 410 } 411 412 return ctrl0; 413 } 414 415 const struct rkcif_mipi_match_data rkcif_rk3568_vicap_mipi_match_data = { 416 .mipi_num = 1, 417 .mipi_ctrl0 = rkcif_rk3568_mipi_ctrl0, 418 .regs = { 419 [RKCIF_MIPI_CTRL] = 0x20, 420 [RKCIF_MIPI_INTEN] = 0xa4, 421 [RKCIF_MIPI_INTSTAT] = 0xa8, 422 }, 423 .regs_id = { 424 [RKCIF_ID0] = { 425 [RKCIF_MIPI_CTRL0] = 0x00, 426 [RKCIF_MIPI_CTRL1] = 0x04, 427 [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x24, 428 [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x2c, 429 [RKCIF_MIPI_FRAME0_VLW_Y] = 0x34, 430 [RKCIF_MIPI_FRAME0_VLW_UV] = 0x3c, 431 [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x28, 432 [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x30, 433 [RKCIF_MIPI_FRAME1_VLW_Y] = 0x38, 434 [RKCIF_MIPI_FRAME1_VLW_UV] = 0x40, 435 [RKCIF_MIPI_CROP_START] = 0xbc, 436 }, 437 [RKCIF_ID1] = { 438 [RKCIF_MIPI_CTRL0] = 0x08, 439 [RKCIF_MIPI_CTRL1] = 0x0c, 440 [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x44, 441 [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x4c, 442 [RKCIF_MIPI_FRAME0_VLW_Y] = 0x54, 443 [RKCIF_MIPI_FRAME0_VLW_UV] = 0x5c, 444 [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x48, 445 [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x50, 446 [RKCIF_MIPI_FRAME1_VLW_Y] = 0x58, 447 [RKCIF_MIPI_FRAME1_VLW_UV] = 0x60, 448 [RKCIF_MIPI_CROP_START] = 0xc0, 449 }, 450 [RKCIF_ID2] = { 451 [RKCIF_MIPI_CTRL0] = 0x10, 452 [RKCIF_MIPI_CTRL1] = 0x14, 453 [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x64, 454 [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x6c, 455 [RKCIF_MIPI_FRAME0_VLW_Y] = 0x74, 456 [RKCIF_MIPI_FRAME0_VLW_UV] = 0x7c, 457 [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x68, 458 [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x70, 459 [RKCIF_MIPI_FRAME1_VLW_Y] = 0x78, 460 [RKCIF_MIPI_FRAME1_VLW_UV] = 0x80, 461 [RKCIF_MIPI_CROP_START] = 0xc4, 462 }, 463 [RKCIF_ID3] = { 464 [RKCIF_MIPI_CTRL0] = 0x18, 465 [RKCIF_MIPI_CTRL1] = 0x1c, 466 [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x84, 467 [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x8c, 468 [RKCIF_MIPI_FRAME0_VLW_Y] = 0x94, 469 [RKCIF_MIPI_FRAME0_VLW_UV] = 0x9c, 470 [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x88, 471 [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x90, 472 [RKCIF_MIPI_FRAME1_VLW_Y] = 0x98, 473 [RKCIF_MIPI_FRAME1_VLW_UV] = 0xa0, 474 [RKCIF_MIPI_CROP_START] = 0xc8, 475 }, 476 }, 477 .blocks = { 478 { 479 .offset = 0x80, 480 }, 481 }, 482 }; 483 484 static inline unsigned int rkcif_mipi_get_reg(struct rkcif_interface *interface, 485 unsigned int index) 486 { 487 struct rkcif_device *rkcif = interface->rkcif; 488 unsigned int block, offset, reg; 489 490 block = interface->index - RKCIF_MIPI_BASE; 491 492 if (WARN_ON_ONCE(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) || 493 WARN_ON_ONCE(index > RKCIF_MIPI_REGISTER_MAX)) 494 return RKCIF_REGISTER_NOTSUPPORTED; 495 496 offset = rkcif->match_data->mipi->blocks[block].offset; 497 reg = rkcif->match_data->mipi->regs[index]; 498 if (reg == RKCIF_REGISTER_NOTSUPPORTED) 499 return reg; 500 501 return offset + reg; 502 } 503 504 static inline unsigned int rkcif_mipi_id_get_reg(struct rkcif_stream *stream, 505 unsigned int index) 506 { 507 struct rkcif_device *rkcif = stream->rkcif; 508 unsigned int block, id, offset, reg; 509 510 block = stream->interface->index - RKCIF_MIPI_BASE; 511 id = stream->id; 512 513 if (WARN_ON_ONCE(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) || 514 WARN_ON_ONCE(id > RKCIF_ID_MAX) || 515 WARN_ON_ONCE(index > RKCIF_MIPI_ID_REGISTER_MAX)) 516 return RKCIF_REGISTER_NOTSUPPORTED; 517 518 offset = rkcif->match_data->mipi->blocks[block].offset; 519 reg = rkcif->match_data->mipi->regs_id[id][index]; 520 if (reg == RKCIF_REGISTER_NOTSUPPORTED) 521 return reg; 522 523 return offset + reg; 524 } 525 526 static inline __maybe_unused void 527 rkcif_mipi_write(struct rkcif_interface *interface, unsigned int index, u32 val) 528 { 529 unsigned int addr = rkcif_mipi_get_reg(interface, index); 530 531 if (addr == RKCIF_REGISTER_NOTSUPPORTED) 532 return; 533 534 writel(val, interface->rkcif->base_addr + addr); 535 } 536 537 static inline __maybe_unused void 538 rkcif_mipi_stream_write(struct rkcif_stream *stream, unsigned int index, 539 u32 val) 540 { 541 unsigned int addr = rkcif_mipi_id_get_reg(stream, index); 542 543 if (addr == RKCIF_REGISTER_NOTSUPPORTED) 544 return; 545 546 writel(val, stream->rkcif->base_addr + addr); 547 } 548 549 static inline __maybe_unused u32 550 rkcif_mipi_read(struct rkcif_interface *interface, unsigned int index) 551 { 552 unsigned int addr = rkcif_mipi_get_reg(interface, index); 553 554 if (addr == RKCIF_REGISTER_NOTSUPPORTED) 555 return 0; 556 557 return readl(interface->rkcif->base_addr + addr); 558 } 559 560 static inline __maybe_unused u32 561 rkcif_mipi_stream_read(struct rkcif_stream *stream, unsigned int index) 562 { 563 unsigned int addr = rkcif_mipi_id_get_reg(stream, index); 564 565 if (addr == RKCIF_REGISTER_NOTSUPPORTED) 566 return 0; 567 568 return readl(stream->rkcif->base_addr + addr); 569 } 570 571 static void rkcif_mipi_queue_buffer(struct rkcif_stream *stream, 572 unsigned int index) 573 { 574 struct rkcif_buffer *buffer = stream->buffers[index]; 575 u32 frm_addr_y, frm_addr_uv; 576 577 frm_addr_y = index ? RKCIF_MIPI_FRAME1_ADDR_Y : 578 RKCIF_MIPI_FRAME0_ADDR_Y; 579 frm_addr_uv = index ? RKCIF_MIPI_FRAME1_ADDR_UV : 580 RKCIF_MIPI_FRAME0_ADDR_UV; 581 582 rkcif_mipi_stream_write(stream, frm_addr_y, 583 buffer->buff_addr[RKCIF_PLANE_Y]); 584 rkcif_mipi_stream_write(stream, frm_addr_uv, 585 buffer->buff_addr[RKCIF_PLANE_UV]); 586 } 587 588 static int rkcif_mipi_start_streaming(struct rkcif_stream *stream) 589 { 590 struct rkcif_interface *interface = stream->interface; 591 const struct rkcif_output_fmt *active_out_fmt; 592 const struct rkcif_mipi_match_data *match_data; 593 struct v4l2_subdev_state *state; 594 u32 ctrl0 = 0, ctrl1 = 0, int_temp = 0, int_mask = 0, vlw = 0; 595 u16 height, width; 596 int ret = -EINVAL; 597 598 state = v4l2_subdev_lock_and_get_active_state(&interface->sd); 599 600 active_out_fmt = rkcif_stream_find_output_fmt(stream, false, 601 stream->pix.pixelformat); 602 if (!active_out_fmt) 603 goto out; 604 605 height = stream->pix.height; 606 width = stream->pix.width; 607 vlw = stream->pix.plane_fmt[0].bytesperline; 608 609 match_data = stream->rkcif->match_data->mipi; 610 if (match_data->mipi_ctrl0) 611 ctrl0 = match_data->mipi_ctrl0(stream, active_out_fmt); 612 613 ctrl1 = RKCIF_XY_COORD(width, height); 614 615 int_mask |= RKCIF_MIPI_INT_FRAME0_END(stream->id); 616 int_mask |= RKCIF_MIPI_INT_FRAME1_END(stream->id); 617 618 int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTEN); 619 int_temp |= int_mask; 620 rkcif_mipi_write(interface, RKCIF_MIPI_INTEN, int_temp); 621 622 int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT); 623 int_temp &= ~int_mask; 624 rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, int_temp); 625 626 rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME0_VLW_Y, vlw); 627 rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME1_VLW_Y, vlw); 628 rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME0_VLW_UV, vlw); 629 rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME1_VLW_UV, vlw); 630 rkcif_mipi_stream_write(stream, RKCIF_MIPI_CROP_START, 0x0); 631 rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL1, ctrl1); 632 rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL0, ctrl0); 633 634 ret = 0; 635 636 out: 637 v4l2_subdev_unlock_state(state); 638 return ret; 639 } 640 641 static void rkcif_mipi_stop_streaming(struct rkcif_stream *stream) 642 { 643 struct rkcif_interface *interface = stream->interface; 644 struct v4l2_subdev_state *state; 645 u32 int_temp = 0, int_mask = 0; 646 647 state = v4l2_subdev_lock_and_get_active_state(&interface->sd); 648 649 rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL0, 0); 650 651 int_mask |= RKCIF_MIPI_INT_FRAME0_END(stream->id); 652 int_mask |= RKCIF_MIPI_INT_FRAME1_END(stream->id); 653 654 int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTEN); 655 int_temp &= ~int_mask; 656 rkcif_mipi_write(interface, RKCIF_MIPI_INTEN, int_temp); 657 658 int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT); 659 int_temp &= ~int_mask; 660 rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, int_temp); 661 662 stream->stopping = false; 663 664 v4l2_subdev_unlock_state(state); 665 } 666 667 static void rkcif_mipi_set_crop(struct rkcif_stream *stream, u16 left, u16 top) 668 { 669 u32 val; 670 671 val = RKCIF_XY_COORD(left, top); 672 rkcif_mipi_stream_write(stream, RKCIF_MIPI_CROP_START, val); 673 } 674 675 irqreturn_t rkcif_mipi_isr(int irq, void *ctx) 676 { 677 struct device *dev = ctx; 678 struct rkcif_device *rkcif = dev_get_drvdata(dev); 679 irqreturn_t ret = IRQ_NONE; 680 u32 intstat; 681 682 for (unsigned int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) { 683 enum rkcif_interface_index index = RKCIF_MIPI_BASE + i; 684 struct rkcif_interface *interface = &rkcif->interfaces[index]; 685 686 intstat = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT); 687 rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, intstat); 688 689 for (unsigned int j = 0; j < interface->streams_num; j++) { 690 struct rkcif_stream *stream = &interface->streams[j]; 691 692 if (intstat & RKCIF_MIPI_INT_FRAME0_END(stream->id) || 693 intstat & RKCIF_MIPI_INT_FRAME1_END(stream->id)) { 694 ret = IRQ_HANDLED; 695 696 if (stream->stopping) { 697 rkcif_mipi_stop_streaming(stream); 698 wake_up(&stream->wq_stopped); 699 continue; 700 } 701 702 rkcif_stream_pingpong(stream); 703 } 704 } 705 } 706 707 return ret; 708 } 709 710 int rkcif_mipi_register(struct rkcif_device *rkcif) 711 { 712 int ret; 713 714 if (!rkcif->match_data->mipi) 715 return 0; 716 717 for (unsigned int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) { 718 enum rkcif_interface_index index = RKCIF_MIPI_BASE + i; 719 struct rkcif_interface *interface = &rkcif->interfaces[index]; 720 721 interface->index = index; 722 interface->type = RKCIF_IF_MIPI; 723 interface->in_fmts = mipi_in_fmts; 724 interface->in_fmts_num = ARRAY_SIZE(mipi_in_fmts); 725 interface->set_crop = rkcif_mipi_set_crop; 726 interface->streams_num = 0; 727 ret = rkcif_interface_register(rkcif, interface); 728 if (ret) 729 continue; 730 731 for (unsigned int j = 0; j < RKCIF_ID_MAX; j++) { 732 struct rkcif_stream *stream = &interface->streams[j]; 733 734 stream->id = j; 735 stream->interface = interface; 736 stream->out_fmts = mipi_out_fmts; 737 stream->out_fmts_num = ARRAY_SIZE(mipi_out_fmts); 738 stream->queue_buffer = rkcif_mipi_queue_buffer; 739 stream->start_streaming = rkcif_mipi_start_streaming; 740 stream->stop_streaming = rkcif_mipi_stop_streaming; 741 ret = rkcif_stream_register(rkcif, stream); 742 if (ret) 743 goto err; 744 interface->streams_num++; 745 } 746 } 747 748 return 0; 749 750 err: 751 for (unsigned int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) { 752 enum rkcif_interface_index index = RKCIF_MIPI_BASE + i; 753 struct rkcif_interface *interface = &rkcif->interfaces[index]; 754 755 for (unsigned int j = 0; j < interface->streams_num; j++) 756 rkcif_stream_unregister(&interface->streams[j]); 757 758 rkcif_interface_unregister(interface); 759 } 760 return ret; 761 } 762 763 void rkcif_mipi_unregister(struct rkcif_device *rkcif) 764 { 765 if (!rkcif->match_data->mipi) 766 return; 767 768 for (unsigned int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) { 769 enum rkcif_interface_index index = RKCIF_MIPI_BASE + i; 770 struct rkcif_interface *interface = &rkcif->interfaces[index]; 771 772 for (unsigned int j = 0; j < interface->streams_num; j++) 773 rkcif_stream_unregister(&interface->streams[j]); 774 775 rkcif_interface_unregister(interface); 776 } 777 } 778