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) 2020 Maxime Chevallier <maxime.chevallier@bootlin.com> 7 * Copyright (C) 2023 Mehdi Djait <mehdi.djait@bootlin.com> 8 * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net> 9 * Copyright (C) 2025 Collabora, Ltd. 10 */ 11 12 #include <media/v4l2-common.h> 13 #include <media/v4l2-fwnode.h> 14 #include <media/v4l2-mc.h> 15 #include <media/v4l2-subdev.h> 16 17 #include "rkcif-capture-dvp.h" 18 #include "rkcif-common.h" 19 #include "rkcif-interface.h" 20 #include "rkcif-regs.h" 21 #include "rkcif-stream.h" 22 23 static const struct rkcif_output_fmt dvp_out_fmts[] = { 24 { 25 .fourcc = V4L2_PIX_FMT_NV16, 26 .dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 | 27 RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV, 28 .cplanes = 2, 29 }, 30 { 31 .fourcc = V4L2_PIX_FMT_NV16M, 32 .dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 | 33 RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV, 34 .cplanes = 2, 35 }, 36 { 37 .fourcc = V4L2_PIX_FMT_NV61, 38 .dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 | 39 RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU, 40 .cplanes = 2, 41 }, 42 { 43 .fourcc = V4L2_PIX_FMT_NV61M, 44 .dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 | 45 RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU, 46 .cplanes = 2, 47 }, 48 { 49 .fourcc = V4L2_PIX_FMT_NV12, 50 .dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 | 51 RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV, 52 .cplanes = 2, 53 }, 54 { 55 .fourcc = V4L2_PIX_FMT_NV12M, 56 .dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 | 57 RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV, 58 .cplanes = 2, 59 }, 60 { 61 .fourcc = V4L2_PIX_FMT_NV21, 62 .dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 | 63 RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU, 64 .cplanes = 2, 65 }, 66 { 67 .fourcc = V4L2_PIX_FMT_NV21M, 68 .dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 | 69 RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU, 70 .cplanes = 2, 71 }, 72 { 73 .fourcc = V4L2_PIX_FMT_RGB24, 74 .cplanes = 1, 75 }, 76 { 77 .fourcc = V4L2_PIX_FMT_RGB565, 78 .cplanes = 1, 79 }, 80 { 81 .fourcc = V4L2_PIX_FMT_BGR666, 82 .cplanes = 1, 83 }, 84 { 85 .fourcc = V4L2_PIX_FMT_SRGGB8, 86 .cplanes = 1, 87 }, 88 { 89 .fourcc = V4L2_PIX_FMT_SGRBG8, 90 .cplanes = 1, 91 }, 92 { 93 .fourcc = V4L2_PIX_FMT_SGBRG8, 94 .cplanes = 1, 95 }, 96 { 97 .fourcc = V4L2_PIX_FMT_SBGGR8, 98 .cplanes = 1, 99 }, 100 { 101 .fourcc = V4L2_PIX_FMT_SRGGB10, 102 .cplanes = 1, 103 }, 104 { 105 .fourcc = V4L2_PIX_FMT_SGRBG10, 106 .cplanes = 1, 107 }, 108 { 109 .fourcc = V4L2_PIX_FMT_SGBRG10, 110 .cplanes = 1, 111 }, 112 { 113 .fourcc = V4L2_PIX_FMT_SBGGR10, 114 .cplanes = 1, 115 }, 116 { 117 .fourcc = V4L2_PIX_FMT_SRGGB12, 118 .cplanes = 1, 119 }, 120 { 121 .fourcc = V4L2_PIX_FMT_SGRBG12, 122 .cplanes = 1, 123 }, 124 { 125 .fourcc = V4L2_PIX_FMT_SGBRG12, 126 .cplanes = 1, 127 }, 128 { 129 .fourcc = V4L2_PIX_FMT_SBGGR12, 130 .cplanes = 1, 131 }, 132 { 133 .fourcc = V4L2_PIX_FMT_SBGGR16, 134 .cplanes = 1, 135 }, 136 { 137 .fourcc = V4L2_PIX_FMT_Y16, 138 .cplanes = 1, 139 }, 140 }; 141 142 static const struct rkcif_input_fmt px30_dvp_in_fmts[] = { 143 { 144 .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, 145 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 146 RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV, 147 .fmt_type = RKCIF_FMT_TYPE_YUV, 148 .field = V4L2_FIELD_NONE, 149 }, 150 { 151 .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, 152 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 153 RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV, 154 .fmt_type = RKCIF_FMT_TYPE_YUV, 155 .field = V4L2_FIELD_INTERLACED, 156 }, 157 { 158 .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, 159 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 160 RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU, 161 .fmt_type = RKCIF_FMT_TYPE_YUV, 162 .field = V4L2_FIELD_NONE, 163 }, 164 { 165 .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, 166 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 167 RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU, 168 .fmt_type = RKCIF_FMT_TYPE_YUV, 169 .field = V4L2_FIELD_INTERLACED, 170 }, 171 { 172 .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, 173 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 174 RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY, 175 .fmt_type = RKCIF_FMT_TYPE_YUV, 176 .field = V4L2_FIELD_NONE, 177 }, 178 { 179 .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, 180 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 181 RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY, 182 .fmt_type = RKCIF_FMT_TYPE_YUV, 183 .field = V4L2_FIELD_INTERLACED, 184 }, 185 { 186 .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, 187 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 188 RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY, 189 .fmt_type = RKCIF_FMT_TYPE_YUV, 190 .field = V4L2_FIELD_NONE, 191 }, 192 { 193 .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, 194 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 195 RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY, 196 .fmt_type = RKCIF_FMT_TYPE_YUV, 197 .field = V4L2_FIELD_INTERLACED, 198 }, 199 { 200 .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, 201 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 202 RKCIF_FORMAT_RAW_DATA_WIDTH_8, 203 .fmt_type = RKCIF_FMT_TYPE_RAW, 204 .field = V4L2_FIELD_NONE, 205 }, 206 { 207 .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, 208 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 209 RKCIF_FORMAT_RAW_DATA_WIDTH_8, 210 .fmt_type = RKCIF_FMT_TYPE_RAW, 211 .field = V4L2_FIELD_NONE, 212 }, 213 { 214 .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, 215 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 216 RKCIF_FORMAT_RAW_DATA_WIDTH_8, 217 .fmt_type = RKCIF_FMT_TYPE_RAW, 218 .field = V4L2_FIELD_NONE, 219 }, 220 { 221 .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, 222 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 223 RKCIF_FORMAT_RAW_DATA_WIDTH_8, 224 .fmt_type = RKCIF_FMT_TYPE_RAW, 225 .field = V4L2_FIELD_NONE, 226 }, 227 { 228 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, 229 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 230 RKCIF_FORMAT_RAW_DATA_WIDTH_10, 231 .fmt_type = RKCIF_FMT_TYPE_RAW, 232 .field = V4L2_FIELD_NONE, 233 }, 234 { 235 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, 236 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 237 RKCIF_FORMAT_RAW_DATA_WIDTH_10, 238 .fmt_type = RKCIF_FMT_TYPE_RAW, 239 .field = V4L2_FIELD_NONE, 240 }, 241 { 242 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, 243 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 244 RKCIF_FORMAT_RAW_DATA_WIDTH_10, 245 .fmt_type = RKCIF_FMT_TYPE_RAW, 246 .field = V4L2_FIELD_NONE, 247 }, 248 { 249 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, 250 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 251 RKCIF_FORMAT_RAW_DATA_WIDTH_10, 252 .fmt_type = RKCIF_FMT_TYPE_RAW, 253 .field = V4L2_FIELD_NONE, 254 }, 255 { 256 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, 257 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 258 RKCIF_FORMAT_RAW_DATA_WIDTH_12, 259 .fmt_type = RKCIF_FMT_TYPE_RAW, 260 .field = V4L2_FIELD_NONE, 261 }, 262 { 263 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, 264 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 265 RKCIF_FORMAT_RAW_DATA_WIDTH_12, 266 .fmt_type = RKCIF_FMT_TYPE_RAW, 267 .field = V4L2_FIELD_NONE, 268 }, 269 { 270 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, 271 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 272 RKCIF_FORMAT_RAW_DATA_WIDTH_12, 273 .fmt_type = RKCIF_FMT_TYPE_RAW, 274 .field = V4L2_FIELD_NONE, 275 }, 276 { 277 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, 278 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 279 RKCIF_FORMAT_RAW_DATA_WIDTH_12, 280 .fmt_type = RKCIF_FMT_TYPE_RAW, 281 .field = V4L2_FIELD_NONE, 282 }, 283 { 284 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, 285 .field = V4L2_FIELD_NONE, 286 }, 287 { 288 .mbus_code = MEDIA_BUS_FMT_Y8_1X8, 289 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 290 RKCIF_FORMAT_RAW_DATA_WIDTH_8, 291 .fmt_type = RKCIF_FMT_TYPE_RAW, 292 .field = V4L2_FIELD_NONE, 293 }, 294 { 295 .mbus_code = MEDIA_BUS_FMT_Y10_1X10, 296 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 297 RKCIF_FORMAT_RAW_DATA_WIDTH_10, 298 .fmt_type = RKCIF_FMT_TYPE_RAW, 299 .field = V4L2_FIELD_NONE, 300 }, 301 { 302 .mbus_code = MEDIA_BUS_FMT_Y12_1X12, 303 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 304 RKCIF_FORMAT_RAW_DATA_WIDTH_12, 305 .fmt_type = RKCIF_FMT_TYPE_RAW, 306 .field = V4L2_FIELD_NONE, 307 } 308 }; 309 310 const struct rkcif_dvp_match_data rkcif_px30_vip_dvp_match_data = { 311 .in_fmts = px30_dvp_in_fmts, 312 .in_fmts_num = ARRAY_SIZE(px30_dvp_in_fmts), 313 .out_fmts = dvp_out_fmts, 314 .out_fmts_num = ARRAY_SIZE(dvp_out_fmts), 315 .has_scaler = true, 316 .regs = { 317 [RKCIF_DVP_CTRL] = 0x00, 318 [RKCIF_DVP_INTEN] = 0x04, 319 [RKCIF_DVP_INTSTAT] = 0x08, 320 [RKCIF_DVP_FOR] = 0x0c, 321 [RKCIF_DVP_LINE_NUM_ADDR] = 0x10, 322 [RKCIF_DVP_FRM0_ADDR_Y] = 0x14, 323 [RKCIF_DVP_FRM0_ADDR_UV] = 0x18, 324 [RKCIF_DVP_FRM1_ADDR_Y] = 0x1c, 325 [RKCIF_DVP_FRM1_ADDR_UV] = 0x20, 326 [RKCIF_DVP_VIR_LINE_WIDTH] = 0x24, 327 [RKCIF_DVP_SET_SIZE] = 0x28, 328 [RKCIF_DVP_SCL_CTRL] = 0x48, 329 [RKCIF_DVP_FRAME_STATUS] = 0x60, 330 [RKCIF_DVP_LAST_LINE] = 0x68, 331 [RKCIF_DVP_LAST_PIX] = 0x6c, 332 }, 333 }; 334 335 static const struct rkcif_input_fmt rk3568_dvp_in_fmts[] = { 336 { 337 .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, 338 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 339 RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV, 340 .fmt_type = RKCIF_FMT_TYPE_YUV, 341 .field = V4L2_FIELD_NONE, 342 }, 343 { 344 .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, 345 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 346 RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV, 347 .fmt_type = RKCIF_FMT_TYPE_YUV, 348 .field = V4L2_FIELD_INTERLACED, 349 }, 350 { 351 .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, 352 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 353 RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU, 354 .fmt_type = RKCIF_FMT_TYPE_YUV, 355 .field = V4L2_FIELD_NONE, 356 }, 357 { 358 .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, 359 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 360 RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU, 361 .fmt_type = RKCIF_FMT_TYPE_YUV, 362 .field = V4L2_FIELD_INTERLACED, 363 }, 364 { 365 .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, 366 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 367 RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY, 368 .fmt_type = RKCIF_FMT_TYPE_YUV, 369 .field = V4L2_FIELD_NONE, 370 }, 371 { 372 .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, 373 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 374 RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY, 375 .fmt_type = RKCIF_FMT_TYPE_YUV, 376 .field = V4L2_FIELD_INTERLACED, 377 }, 378 { 379 .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, 380 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 381 RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY, 382 .fmt_type = RKCIF_FMT_TYPE_YUV, 383 .field = V4L2_FIELD_NONE, 384 }, 385 { 386 .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, 387 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 388 RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY, 389 .fmt_type = RKCIF_FMT_TYPE_YUV, 390 .field = V4L2_FIELD_INTERLACED, 391 }, 392 { 393 .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16, 394 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 395 RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV | 396 RKCIF_FORMAT_INPUT_MODE_BT1120 | 397 RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS, 398 .field = V4L2_FIELD_NONE, 399 }, 400 { 401 .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16, 402 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 403 RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV | 404 RKCIF_FORMAT_INPUT_MODE_BT1120, 405 .field = V4L2_FIELD_INTERLACED, 406 }, 407 { 408 .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16, 409 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 410 RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU | 411 RKCIF_FORMAT_INPUT_MODE_BT1120 | 412 RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS, 413 .field = V4L2_FIELD_NONE, 414 }, 415 { 416 .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16, 417 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 418 RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU | 419 RKCIF_FORMAT_INPUT_MODE_BT1120, 420 .field = V4L2_FIELD_INTERLACED, 421 }, 422 { 423 .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, 424 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 425 RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV | 426 RKCIF_FORMAT_INPUT_MODE_BT1120 | 427 RKCIF_FORMAT_BT1120_YC_SWAP | 428 RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS, 429 .field = V4L2_FIELD_NONE, 430 }, 431 { 432 .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, 433 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 434 RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV | 435 RKCIF_FORMAT_BT1120_YC_SWAP | 436 RKCIF_FORMAT_INPUT_MODE_BT1120, 437 .field = V4L2_FIELD_INTERLACED, 438 }, 439 { 440 .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16, 441 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 442 RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU | 443 RKCIF_FORMAT_INPUT_MODE_BT1120 | 444 RKCIF_FORMAT_BT1120_YC_SWAP | 445 RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS, 446 .field = V4L2_FIELD_NONE, 447 }, 448 { 449 .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16, 450 .dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 | 451 RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU | 452 RKCIF_FORMAT_BT1120_YC_SWAP | 453 RKCIF_FORMAT_INPUT_MODE_BT1120, 454 .field = V4L2_FIELD_INTERLACED, 455 }, 456 { 457 .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, 458 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 459 RKCIF_FORMAT_RAW_DATA_WIDTH_8, 460 .fmt_type = RKCIF_FMT_TYPE_RAW, 461 .field = V4L2_FIELD_NONE, 462 }, 463 { 464 .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, 465 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 466 RKCIF_FORMAT_RAW_DATA_WIDTH_8, 467 .fmt_type = RKCIF_FMT_TYPE_RAW, 468 .field = V4L2_FIELD_NONE, 469 }, 470 { 471 .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, 472 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 473 RKCIF_FORMAT_RAW_DATA_WIDTH_8, 474 .fmt_type = RKCIF_FMT_TYPE_RAW, 475 .field = V4L2_FIELD_NONE, 476 }, 477 { 478 .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, 479 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 480 RKCIF_FORMAT_RAW_DATA_WIDTH_8, 481 .fmt_type = RKCIF_FMT_TYPE_RAW, 482 .field = V4L2_FIELD_NONE, 483 }, 484 { 485 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, 486 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 487 RKCIF_FORMAT_RAW_DATA_WIDTH_10, 488 .fmt_type = RKCIF_FMT_TYPE_RAW, 489 .field = V4L2_FIELD_NONE, 490 }, 491 { 492 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, 493 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 494 RKCIF_FORMAT_RAW_DATA_WIDTH_10, 495 .fmt_type = RKCIF_FMT_TYPE_RAW, 496 .field = V4L2_FIELD_NONE, 497 }, 498 { 499 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, 500 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 501 RKCIF_FORMAT_RAW_DATA_WIDTH_10, 502 .fmt_type = RKCIF_FMT_TYPE_RAW, 503 .field = V4L2_FIELD_NONE, 504 }, 505 { 506 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, 507 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 508 RKCIF_FORMAT_RAW_DATA_WIDTH_10, 509 .fmt_type = RKCIF_FMT_TYPE_RAW, 510 .field = V4L2_FIELD_NONE, 511 }, 512 { 513 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, 514 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 515 RKCIF_FORMAT_RAW_DATA_WIDTH_12, 516 .fmt_type = RKCIF_FMT_TYPE_RAW, 517 .field = V4L2_FIELD_NONE, 518 }, 519 { 520 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, 521 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 522 RKCIF_FORMAT_RAW_DATA_WIDTH_12, 523 .fmt_type = RKCIF_FMT_TYPE_RAW, 524 .field = V4L2_FIELD_NONE, 525 }, 526 { 527 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, 528 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 529 RKCIF_FORMAT_RAW_DATA_WIDTH_12, 530 .fmt_type = RKCIF_FMT_TYPE_RAW, 531 .field = V4L2_FIELD_NONE, 532 }, 533 { 534 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, 535 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 536 RKCIF_FORMAT_RAW_DATA_WIDTH_12, 537 .fmt_type = RKCIF_FMT_TYPE_RAW, 538 .field = V4L2_FIELD_NONE, 539 }, 540 { 541 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, 542 .field = V4L2_FIELD_NONE, 543 }, 544 { 545 .mbus_code = MEDIA_BUS_FMT_Y8_1X8, 546 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 547 RKCIF_FORMAT_RAW_DATA_WIDTH_8, 548 .fmt_type = RKCIF_FMT_TYPE_RAW, 549 .field = V4L2_FIELD_NONE, 550 }, 551 { 552 .mbus_code = MEDIA_BUS_FMT_Y10_1X10, 553 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 554 RKCIF_FORMAT_RAW_DATA_WIDTH_10, 555 .fmt_type = RKCIF_FMT_TYPE_RAW, 556 .field = V4L2_FIELD_NONE, 557 }, 558 { 559 .mbus_code = MEDIA_BUS_FMT_Y12_1X12, 560 .dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW | 561 RKCIF_FORMAT_RAW_DATA_WIDTH_12, 562 .fmt_type = RKCIF_FMT_TYPE_RAW, 563 .field = V4L2_FIELD_NONE, 564 }, 565 }; 566 567 static void rk3568_dvp_grf_setup(struct rkcif_device *rkcif) 568 { 569 u32 con1 = RK3568_GRF_WRITE_ENABLE(RK3568_GRF_VI_CON1_CIF_DATAPATH | 570 RK3568_GRF_VI_CON1_CIF_CLK_DELAYNUM); 571 572 if (!rkcif->grf) 573 return; 574 575 con1 |= rkcif->interfaces[RKCIF_DVP].dvp.dvp_clk_delay & 576 RK3568_GRF_VI_CON1_CIF_CLK_DELAYNUM; 577 578 if (rkcif->interfaces[RKCIF_DVP].vep.bus.parallel.flags & 579 V4L2_MBUS_PCLK_SAMPLE_DUALEDGE) 580 con1 |= RK3568_GRF_VI_CON1_CIF_DATAPATH; 581 582 regmap_write(rkcif->grf, RK3568_GRF_VI_CON1, con1); 583 } 584 585 const struct rkcif_dvp_match_data rkcif_rk3568_vicap_dvp_match_data = { 586 .in_fmts = rk3568_dvp_in_fmts, 587 .in_fmts_num = ARRAY_SIZE(rk3568_dvp_in_fmts), 588 .out_fmts = dvp_out_fmts, 589 .out_fmts_num = ARRAY_SIZE(dvp_out_fmts), 590 .setup = rk3568_dvp_grf_setup, 591 .has_scaler = false, 592 .regs = { 593 [RKCIF_DVP_CTRL] = 0x00, 594 [RKCIF_DVP_INTEN] = 0x04, 595 [RKCIF_DVP_INTSTAT] = 0x08, 596 [RKCIF_DVP_FOR] = 0x0c, 597 [RKCIF_DVP_LINE_NUM_ADDR] = 0x2c, 598 [RKCIF_DVP_FRM0_ADDR_Y] = 0x14, 599 [RKCIF_DVP_FRM0_ADDR_UV] = 0x18, 600 [RKCIF_DVP_FRM1_ADDR_Y] = 0x1c, 601 [RKCIF_DVP_FRM1_ADDR_UV] = 0x20, 602 [RKCIF_DVP_VIR_LINE_WIDTH] = 0x24, 603 [RKCIF_DVP_SET_SIZE] = 0x28, 604 [RKCIF_DVP_CROP] = 0x34, 605 [RKCIF_DVP_FRAME_STATUS] = 0x3c, 606 [RKCIF_DVP_LAST_LINE] = 0x44, 607 [RKCIF_DVP_LAST_PIX] = 0x48, 608 }, 609 }; 610 611 static inline unsigned int rkcif_dvp_get_addr(struct rkcif_device *rkcif, 612 unsigned int index) 613 { 614 if (WARN_ON_ONCE(index >= RKCIF_DVP_REGISTER_MAX)) 615 return RKCIF_REGISTER_NOTSUPPORTED; 616 617 return rkcif->match_data->dvp->regs[index]; 618 } 619 620 static inline __maybe_unused void rkcif_dvp_write(struct rkcif_device *rkcif, 621 unsigned int index, u32 val) 622 { 623 unsigned int addr = rkcif_dvp_get_addr(rkcif, index); 624 625 if (addr == RKCIF_REGISTER_NOTSUPPORTED) 626 return; 627 628 writel(val, rkcif->base_addr + addr); 629 } 630 631 static inline __maybe_unused u32 rkcif_dvp_read(struct rkcif_device *rkcif, 632 unsigned int index) 633 { 634 unsigned int addr = rkcif_dvp_get_addr(rkcif, index); 635 636 if (addr == RKCIF_REGISTER_NOTSUPPORTED) 637 return 0; 638 639 return readl(rkcif->base_addr + addr); 640 } 641 642 static void rkcif_dvp_queue_buffer(struct rkcif_stream *stream, 643 unsigned int index) 644 { 645 struct rkcif_device *rkcif = stream->rkcif; 646 struct rkcif_buffer *buffer = stream->buffers[index]; 647 u32 frm_addr_y, frm_addr_uv; 648 649 frm_addr_y = index ? RKCIF_DVP_FRM1_ADDR_Y : RKCIF_DVP_FRM0_ADDR_Y; 650 frm_addr_uv = index ? RKCIF_DVP_FRM1_ADDR_UV : RKCIF_DVP_FRM0_ADDR_UV; 651 652 rkcif_dvp_write(rkcif, frm_addr_y, buffer->buff_addr[RKCIF_PLANE_Y]); 653 rkcif_dvp_write(rkcif, frm_addr_uv, buffer->buff_addr[RKCIF_PLANE_UV]); 654 } 655 656 static int rkcif_dvp_start_streaming(struct rkcif_stream *stream) 657 { 658 struct rkcif_device *rkcif = stream->rkcif; 659 struct rkcif_interface *interface = stream->interface; 660 struct v4l2_mbus_config_parallel *parallel; 661 struct v4l2_mbus_framefmt *source_fmt; 662 struct v4l2_subdev_state *state; 663 const struct rkcif_input_fmt *active_in_fmt; 664 const struct rkcif_output_fmt *active_out_fmt; 665 u32 val = 0; 666 int ret = -EINVAL; 667 668 state = v4l2_subdev_lock_and_get_active_state(&interface->sd); 669 source_fmt = v4l2_subdev_state_get_format(state, RKCIF_IF_PAD_SRC, 670 stream->id); 671 if (!source_fmt) 672 goto out; 673 674 active_in_fmt = rkcif_interface_find_input_fmt(interface, false, 675 source_fmt->code); 676 active_out_fmt = rkcif_stream_find_output_fmt(stream, false, 677 stream->pix.pixelformat); 678 if (!active_in_fmt || !active_out_fmt) 679 goto out; 680 681 parallel = &interface->vep.bus.parallel; 682 if (parallel->bus_width == 16 && 683 (parallel->flags & V4L2_MBUS_PCLK_SAMPLE_DUALEDGE)) 684 val |= RKCIF_FORMAT_BT1120_CLOCK_DOUBLE_EDGES; 685 val |= active_in_fmt->dvp_fmt_val; 686 val |= active_out_fmt->dvp_fmt_val; 687 rkcif_dvp_write(rkcif, RKCIF_DVP_FOR, val); 688 689 val = stream->pix.width; 690 if (active_in_fmt->fmt_type == RKCIF_FMT_TYPE_RAW) 691 val = stream->pix.width * 2; 692 rkcif_dvp_write(rkcif, RKCIF_DVP_VIR_LINE_WIDTH, val); 693 694 val = RKCIF_XY_COORD(stream->pix.width, stream->pix.height); 695 rkcif_dvp_write(rkcif, RKCIF_DVP_SET_SIZE, val); 696 697 rkcif_dvp_write(rkcif, RKCIF_DVP_FRAME_STATUS, RKCIF_FRAME_STAT_CLS); 698 rkcif_dvp_write(rkcif, RKCIF_DVP_INTSTAT, RKCIF_INTSTAT_CLS); 699 if (rkcif->match_data->dvp->has_scaler) { 700 val = active_in_fmt->fmt_type == RKCIF_FMT_TYPE_YUV ? 701 RKCIF_SCL_CTRL_ENABLE_YUV_16BIT_BYPASS : 702 RKCIF_SCL_CTRL_ENABLE_RAW_16BIT_BYPASS; 703 rkcif_dvp_write(rkcif, RKCIF_DVP_SCL_CTRL, val); 704 } 705 706 rkcif_dvp_write(rkcif, RKCIF_DVP_INTEN, 707 RKCIF_INTEN_FRAME_END_EN | 708 RKCIF_INTEN_PST_INF_FRAME_END_EN); 709 710 rkcif_dvp_write(rkcif, RKCIF_DVP_CTRL, 711 RKCIF_CTRL_AXI_BURST_16 | RKCIF_CTRL_MODE_PINGPONG | 712 RKCIF_CTRL_ENABLE_CAPTURE); 713 714 ret = 0; 715 716 out: 717 v4l2_subdev_unlock_state(state); 718 return ret; 719 } 720 721 static void rkcif_dvp_stop_streaming(struct rkcif_stream *stream) 722 { 723 struct rkcif_device *rkcif = stream->rkcif; 724 u32 val; 725 726 val = rkcif_dvp_read(rkcif, RKCIF_DVP_CTRL); 727 rkcif_dvp_write(rkcif, RKCIF_DVP_CTRL, 728 val & (~RKCIF_CTRL_ENABLE_CAPTURE)); 729 rkcif_dvp_write(rkcif, RKCIF_DVP_INTEN, 0x0); 730 rkcif_dvp_write(rkcif, RKCIF_DVP_INTSTAT, 0x3ff); 731 rkcif_dvp_write(rkcif, RKCIF_DVP_FRAME_STATUS, 0x0); 732 733 stream->stopping = false; 734 } 735 736 static void rkcif_dvp_reset_stream(struct rkcif_device *rkcif) 737 { 738 u32 ctl = rkcif_dvp_read(rkcif, RKCIF_DVP_CTRL); 739 740 rkcif_dvp_write(rkcif, RKCIF_DVP_CTRL, 741 ctl & (~RKCIF_CTRL_ENABLE_CAPTURE)); 742 rkcif_dvp_write(rkcif, RKCIF_DVP_CTRL, ctl | RKCIF_CTRL_ENABLE_CAPTURE); 743 } 744 745 static void rkcif_dvp_set_crop(struct rkcif_stream *stream, u16 left, u16 top) 746 { 747 struct rkcif_device *rkcif = stream->rkcif; 748 u32 val; 749 750 val = RKCIF_XY_COORD(left, top); 751 rkcif_dvp_write(rkcif, RKCIF_DVP_CROP, val); 752 } 753 754 irqreturn_t rkcif_dvp_isr(int irq, void *ctx) 755 { 756 struct device *dev = ctx; 757 struct rkcif_device *rkcif = dev_get_drvdata(dev); 758 struct rkcif_stream *stream; 759 u32 intstat, lastline, lastpix, cif_frmst; 760 irqreturn_t ret = IRQ_NONE; 761 762 if (!rkcif->match_data->dvp) 763 return ret; 764 765 intstat = rkcif_dvp_read(rkcif, RKCIF_DVP_INTSTAT); 766 cif_frmst = rkcif_dvp_read(rkcif, RKCIF_DVP_FRAME_STATUS); 767 lastline = RKCIF_FETCH_Y(rkcif_dvp_read(rkcif, RKCIF_DVP_LAST_LINE)); 768 lastpix = RKCIF_FETCH_Y(rkcif_dvp_read(rkcif, RKCIF_DVP_LAST_PIX)); 769 770 if (intstat & RKCIF_INTSTAT_FRAME_END) { 771 rkcif_dvp_write(rkcif, RKCIF_DVP_INTSTAT, 772 RKCIF_INTSTAT_FRAME_END_CLR | 773 RKCIF_INTSTAT_LINE_END_CLR); 774 775 stream = &rkcif->interfaces[RKCIF_DVP].streams[RKCIF_ID0]; 776 777 if (stream->stopping) { 778 rkcif_dvp_stop_streaming(stream); 779 wake_up(&stream->wq_stopped); 780 ret = IRQ_HANDLED; 781 goto out; 782 } 783 784 if (lastline != stream->pix.height) { 785 v4l2_err(&rkcif->v4l2_dev, 786 "bad frame, irq:%#x frmst:%#x size:%dx%d\n", 787 intstat, cif_frmst, lastpix, lastline); 788 789 rkcif_dvp_reset_stream(rkcif); 790 } 791 792 rkcif_stream_pingpong(stream); 793 794 ret = IRQ_HANDLED; 795 } 796 out: 797 return ret; 798 } 799 800 int rkcif_dvp_register(struct rkcif_device *rkcif) 801 { 802 struct rkcif_interface *interface; 803 unsigned int streams_num; 804 int ret; 805 806 if (!rkcif->match_data->dvp) 807 return 0; 808 809 interface = &rkcif->interfaces[RKCIF_DVP]; 810 interface->index = RKCIF_DVP; 811 interface->type = RKCIF_IF_DVP; 812 interface->in_fmts = rkcif->match_data->dvp->in_fmts; 813 interface->in_fmts_num = rkcif->match_data->dvp->in_fmts_num; 814 interface->set_crop = rkcif_dvp_set_crop; 815 ret = rkcif_interface_register(rkcif, interface); 816 if (ret) 817 return ret; 818 819 if (rkcif->match_data->dvp->setup) 820 rkcif->match_data->dvp->setup(rkcif); 821 822 streams_num = rkcif->match_data->dvp->has_ids ? 4 : 1; 823 for (unsigned int i = 0; i < streams_num; i++) { 824 struct rkcif_stream *stream = &interface->streams[i]; 825 826 stream->id = i; 827 stream->interface = interface; 828 stream->out_fmts = rkcif->match_data->dvp->out_fmts; 829 stream->out_fmts_num = rkcif->match_data->dvp->out_fmts_num; 830 stream->queue_buffer = rkcif_dvp_queue_buffer; 831 stream->start_streaming = rkcif_dvp_start_streaming; 832 stream->stop_streaming = rkcif_dvp_stop_streaming; 833 834 ret = rkcif_stream_register(rkcif, stream); 835 if (ret) 836 goto err_streams_unregister; 837 838 interface->streams_num++; 839 } 840 841 return 0; 842 843 err_streams_unregister: 844 for (unsigned int i = 0; i < interface->streams_num; i++) 845 rkcif_stream_unregister(&interface->streams[i]); 846 847 rkcif_interface_unregister(interface); 848 849 return ret; 850 } 851 852 void rkcif_dvp_unregister(struct rkcif_device *rkcif) 853 { 854 struct rkcif_interface *interface; 855 856 if (!rkcif->match_data->dvp) 857 return; 858 859 interface = &rkcif->interfaces[RKCIF_DVP]; 860 861 for (unsigned int i = 0; i < interface->streams_num; i++) 862 rkcif_stream_unregister(&interface->streams[i]); 863 864 rkcif_interface_unregister(interface); 865 } 866