1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2011-2018 Magewell Electronics Co., Ltd. (Nanjing) 4 * Author: Yong Deng <yong.deng@magewell.com> 5 * Copyright 2021-2022 Bootlin 6 * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com> 7 */ 8 9 #include <linux/of.h> 10 #include <linux/regmap.h> 11 #include <media/v4l2-device.h> 12 #include <media/v4l2-event.h> 13 #include <media/v4l2-ioctl.h> 14 #include <media/v4l2-mc.h> 15 #include <media/videobuf2-dma-contig.h> 16 #include <media/videobuf2-v4l2.h> 17 18 #include "sun6i_csi.h" 19 #include "sun6i_csi_bridge.h" 20 #include "sun6i_csi_capture.h" 21 #include "sun6i_csi_reg.h" 22 23 /* Helpers */ 24 25 void sun6i_csi_capture_dimensions(struct sun6i_csi_device *csi_dev, 26 unsigned int *width, unsigned int *height) 27 { 28 if (width) 29 *width = csi_dev->capture.format.fmt.pix.width; 30 if (height) 31 *height = csi_dev->capture.format.fmt.pix.height; 32 } 33 34 void sun6i_csi_capture_format(struct sun6i_csi_device *csi_dev, 35 u32 *pixelformat, u32 *field) 36 { 37 if (pixelformat) 38 *pixelformat = csi_dev->capture.format.fmt.pix.pixelformat; 39 40 if (field) 41 *field = csi_dev->capture.format.fmt.pix.field; 42 } 43 44 /* Format */ 45 46 static const struct sun6i_csi_capture_format sun6i_csi_capture_formats[] = { 47 /* Bayer */ 48 { 49 .pixelformat = V4L2_PIX_FMT_SBGGR8, 50 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8, 51 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8, 52 }, 53 { 54 .pixelformat = V4L2_PIX_FMT_SGBRG8, 55 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8, 56 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8, 57 }, 58 { 59 .pixelformat = V4L2_PIX_FMT_SGRBG8, 60 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8, 61 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8, 62 }, 63 { 64 .pixelformat = V4L2_PIX_FMT_SRGGB8, 65 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8, 66 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8, 67 }, 68 { 69 .pixelformat = V4L2_PIX_FMT_SBGGR10, 70 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_10, 71 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_10, 72 }, 73 { 74 .pixelformat = V4L2_PIX_FMT_SGBRG10, 75 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_10, 76 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_10, 77 }, 78 { 79 .pixelformat = V4L2_PIX_FMT_SGRBG10, 80 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_10, 81 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_10, 82 }, 83 { 84 .pixelformat = V4L2_PIX_FMT_SRGGB10, 85 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_10, 86 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_10, 87 }, 88 { 89 .pixelformat = V4L2_PIX_FMT_SBGGR12, 90 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_12, 91 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_12, 92 }, 93 { 94 .pixelformat = V4L2_PIX_FMT_SGBRG12, 95 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_12, 96 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_12, 97 }, 98 { 99 .pixelformat = V4L2_PIX_FMT_SGRBG12, 100 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_12, 101 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_12, 102 }, 103 { 104 .pixelformat = V4L2_PIX_FMT_SRGGB12, 105 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_12, 106 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_12, 107 }, 108 /* RGB */ 109 { 110 .pixelformat = V4L2_PIX_FMT_RGB565, 111 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RGB565, 112 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RGB565, 113 }, 114 { 115 .pixelformat = V4L2_PIX_FMT_RGB565X, 116 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RGB565, 117 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RGB565, 118 }, 119 /* YUV422 */ 120 { 121 .pixelformat = V4L2_PIX_FMT_YUYV, 122 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8, 123 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8, 124 .input_format_raw = true, 125 .hsize_len_factor = 2, 126 }, 127 { 128 .pixelformat = V4L2_PIX_FMT_YVYU, 129 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8, 130 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8, 131 .input_format_raw = true, 132 .hsize_len_factor = 2, 133 }, 134 { 135 .pixelformat = V4L2_PIX_FMT_UYVY, 136 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8, 137 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8, 138 .input_format_raw = true, 139 .hsize_len_factor = 2, 140 }, 141 { 142 .pixelformat = V4L2_PIX_FMT_VYUY, 143 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8, 144 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8, 145 .input_format_raw = true, 146 .hsize_len_factor = 2, 147 }, 148 { 149 .pixelformat = V4L2_PIX_FMT_NV16, 150 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_YUV422SP, 151 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_YUV422SP, 152 }, 153 { 154 .pixelformat = V4L2_PIX_FMT_NV61, 155 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_YUV422SP, 156 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_YUV422SP, 157 .input_yuv_seq_invert = true, 158 }, 159 { 160 .pixelformat = V4L2_PIX_FMT_YUV422P, 161 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_YUV422P, 162 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_YUV422P, 163 }, 164 /* YUV420 */ 165 { 166 .pixelformat = V4L2_PIX_FMT_NV12_16L16, 167 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_YUV420MB, 168 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_YUV420MB, 169 }, 170 { 171 .pixelformat = V4L2_PIX_FMT_NV12, 172 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_YUV420SP, 173 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_YUV420SP, 174 }, 175 { 176 .pixelformat = V4L2_PIX_FMT_NV21, 177 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_YUV420SP, 178 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_YUV420SP, 179 .input_yuv_seq_invert = true, 180 }, 181 182 { 183 .pixelformat = V4L2_PIX_FMT_YUV420, 184 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_YUV420P, 185 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_YUV420P, 186 }, 187 { 188 .pixelformat = V4L2_PIX_FMT_YVU420, 189 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_YUV420P, 190 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_YUV420P, 191 .input_yuv_seq_invert = true, 192 }, 193 /* Compressed */ 194 { 195 .pixelformat = V4L2_PIX_FMT_JPEG, 196 .output_format_frame = SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8, 197 .output_format_field = SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8, 198 }, 199 }; 200 201 const 202 struct sun6i_csi_capture_format *sun6i_csi_capture_format_find(u32 pixelformat) 203 { 204 unsigned int i; 205 206 for (i = 0; i < ARRAY_SIZE(sun6i_csi_capture_formats); i++) 207 if (sun6i_csi_capture_formats[i].pixelformat == pixelformat) 208 return &sun6i_csi_capture_formats[i]; 209 210 return NULL; 211 } 212 213 /* RAW formats need an exact match between pixel and mbus formats. */ 214 static const 215 struct sun6i_csi_capture_format_match sun6i_csi_capture_format_matches[] = { 216 /* YUV420 */ 217 { 218 .pixelformat = V4L2_PIX_FMT_YUYV, 219 .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, 220 }, 221 { 222 .pixelformat = V4L2_PIX_FMT_YUYV, 223 .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16, 224 }, 225 { 226 .pixelformat = V4L2_PIX_FMT_YVYU, 227 .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8, 228 }, 229 { 230 .pixelformat = V4L2_PIX_FMT_YVYU, 231 .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16, 232 }, 233 { 234 .pixelformat = V4L2_PIX_FMT_UYVY, 235 .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, 236 }, 237 { 238 .pixelformat = V4L2_PIX_FMT_UYVY, 239 .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, 240 }, 241 { 242 .pixelformat = V4L2_PIX_FMT_VYUY, 243 .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, 244 }, 245 { 246 .pixelformat = V4L2_PIX_FMT_VYUY, 247 .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16, 248 }, 249 /* RGB */ 250 { 251 .pixelformat = V4L2_PIX_FMT_RGB565, 252 .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE, 253 }, 254 { 255 .pixelformat = V4L2_PIX_FMT_RGB565X, 256 .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_BE, 257 }, 258 /* Bayer */ 259 { 260 .pixelformat = V4L2_PIX_FMT_SBGGR8, 261 .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, 262 }, 263 { 264 .pixelformat = V4L2_PIX_FMT_SGBRG8, 265 .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, 266 }, 267 { 268 .pixelformat = V4L2_PIX_FMT_SGRBG8, 269 .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, 270 }, 271 { 272 .pixelformat = V4L2_PIX_FMT_SRGGB8, 273 .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, 274 }, 275 { 276 .pixelformat = V4L2_PIX_FMT_SBGGR10, 277 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, 278 }, 279 { 280 .pixelformat = V4L2_PIX_FMT_SGBRG10, 281 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, 282 }, 283 { 284 .pixelformat = V4L2_PIX_FMT_SGRBG10, 285 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, 286 }, 287 { 288 .pixelformat = V4L2_PIX_FMT_SRGGB10, 289 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, 290 }, 291 { 292 .pixelformat = V4L2_PIX_FMT_SBGGR12, 293 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, 294 }, 295 { 296 .pixelformat = V4L2_PIX_FMT_SGBRG12, 297 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, 298 }, 299 { 300 .pixelformat = V4L2_PIX_FMT_SGRBG12, 301 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, 302 }, 303 { 304 .pixelformat = V4L2_PIX_FMT_SRGGB12, 305 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, 306 }, 307 /* Compressed */ 308 { 309 .pixelformat = V4L2_PIX_FMT_JPEG, 310 .mbus_code = MEDIA_BUS_FMT_JPEG_1X8, 311 }, 312 }; 313 314 static bool sun6i_csi_capture_format_match(u32 pixelformat, u32 mbus_code) 315 { 316 unsigned int i; 317 318 for (i = 0; i < ARRAY_SIZE(sun6i_csi_capture_format_matches); i++) { 319 const struct sun6i_csi_capture_format_match *match = 320 &sun6i_csi_capture_format_matches[i]; 321 322 if (match->pixelformat == pixelformat && 323 match->mbus_code == mbus_code) 324 return true; 325 } 326 327 return false; 328 } 329 330 /* Capture */ 331 332 static void 333 sun6i_csi_capture_buffer_configure(struct sun6i_csi_device *csi_dev, 334 struct sun6i_csi_buffer *csi_buffer) 335 { 336 struct regmap *regmap = csi_dev->regmap; 337 const struct v4l2_format_info *info; 338 struct vb2_buffer *vb2_buffer; 339 unsigned int width, height; 340 dma_addr_t address; 341 u32 pixelformat; 342 343 vb2_buffer = &csi_buffer->v4l2_buffer.vb2_buf; 344 address = vb2_dma_contig_plane_dma_addr(vb2_buffer, 0); 345 346 regmap_write(regmap, SUN6I_CSI_CH_FIFO0_ADDR_REG, 347 SUN6I_CSI_ADDR_VALUE(address)); 348 349 sun6i_csi_capture_dimensions(csi_dev, &width, &height); 350 sun6i_csi_capture_format(csi_dev, &pixelformat, NULL); 351 352 info = v4l2_format_info(pixelformat); 353 /* Unsupported formats are single-plane, so we can stop here. */ 354 if (!info) 355 return; 356 357 if (info->comp_planes > 1) { 358 address += info->bpp[0] * width * height; 359 360 regmap_write(regmap, SUN6I_CSI_CH_FIFO1_ADDR_REG, 361 SUN6I_CSI_ADDR_VALUE(address)); 362 } 363 364 if (info->comp_planes > 2) { 365 address += info->bpp[1] * DIV_ROUND_UP(width, info->hdiv) * 366 DIV_ROUND_UP(height, info->vdiv); 367 368 regmap_write(regmap, SUN6I_CSI_CH_FIFO2_ADDR_REG, 369 SUN6I_CSI_ADDR_VALUE(address)); 370 } 371 } 372 373 void sun6i_csi_capture_configure(struct sun6i_csi_device *csi_dev) 374 { 375 struct regmap *regmap = csi_dev->regmap; 376 const struct sun6i_csi_capture_format *format; 377 const struct v4l2_format_info *info; 378 u32 hsize_len, vsize_len; 379 u32 luma_line, chroma_line = 0; 380 u32 pixelformat, field; 381 u32 width, height; 382 383 sun6i_csi_capture_dimensions(csi_dev, &width, &height); 384 sun6i_csi_capture_format(csi_dev, &pixelformat, &field); 385 386 format = sun6i_csi_capture_format_find(pixelformat); 387 if (WARN_ON(!format)) 388 return; 389 390 hsize_len = width; 391 vsize_len = height; 392 393 /* 394 * When using 8-bit raw input/output (for packed YUV), we need to adapt 395 * the width to account for the difference in bpp when it's not 8-bit. 396 */ 397 if (format->hsize_len_factor) 398 hsize_len *= format->hsize_len_factor; 399 400 regmap_write(regmap, SUN6I_CSI_CH_HSIZE_REG, 401 SUN6I_CSI_CH_HSIZE_LEN(hsize_len) | 402 SUN6I_CSI_CH_HSIZE_START(0)); 403 404 regmap_write(regmap, SUN6I_CSI_CH_VSIZE_REG, 405 SUN6I_CSI_CH_VSIZE_LEN(vsize_len) | 406 SUN6I_CSI_CH_VSIZE_START(0)); 407 408 switch (pixelformat) { 409 case V4L2_PIX_FMT_RGB565X: 410 luma_line = width * 2; 411 break; 412 case V4L2_PIX_FMT_NV12_16L16: 413 luma_line = width; 414 chroma_line = width; 415 break; 416 case V4L2_PIX_FMT_JPEG: 417 luma_line = width; 418 break; 419 default: 420 info = v4l2_format_info(pixelformat); 421 if (WARN_ON(!info)) 422 return; 423 424 luma_line = width * info->bpp[0]; 425 426 if (info->comp_planes > 1) 427 chroma_line = width * info->bpp[1] / info->hdiv; 428 break; 429 } 430 431 regmap_write(regmap, SUN6I_CSI_CH_BUF_LEN_REG, 432 SUN6I_CSI_CH_BUF_LEN_CHROMA_LINE(chroma_line) | 433 SUN6I_CSI_CH_BUF_LEN_LUMA_LINE(luma_line)); 434 } 435 436 /* State */ 437 438 static void sun6i_csi_capture_state_cleanup(struct sun6i_csi_device *csi_dev, 439 bool error) 440 { 441 struct sun6i_csi_capture_state *state = &csi_dev->capture.state; 442 struct sun6i_csi_buffer **csi_buffer_states[] = { 443 &state->pending, &state->current, &state->complete, 444 }; 445 struct sun6i_csi_buffer *csi_buffer; 446 struct vb2_buffer *vb2_buffer; 447 unsigned long flags; 448 unsigned int i; 449 450 spin_lock_irqsave(&state->lock, flags); 451 452 for (i = 0; i < ARRAY_SIZE(csi_buffer_states); i++) { 453 csi_buffer = *csi_buffer_states[i]; 454 if (!csi_buffer) 455 continue; 456 457 vb2_buffer = &csi_buffer->v4l2_buffer.vb2_buf; 458 vb2_buffer_done(vb2_buffer, error ? VB2_BUF_STATE_ERROR : 459 VB2_BUF_STATE_QUEUED); 460 461 *csi_buffer_states[i] = NULL; 462 } 463 464 list_for_each_entry(csi_buffer, &state->queue, list) { 465 vb2_buffer = &csi_buffer->v4l2_buffer.vb2_buf; 466 vb2_buffer_done(vb2_buffer, error ? VB2_BUF_STATE_ERROR : 467 VB2_BUF_STATE_QUEUED); 468 } 469 470 INIT_LIST_HEAD(&state->queue); 471 472 spin_unlock_irqrestore(&state->lock, flags); 473 } 474 475 void sun6i_csi_capture_state_update(struct sun6i_csi_device *csi_dev) 476 { 477 struct sun6i_csi_capture_state *state = &csi_dev->capture.state; 478 struct sun6i_csi_buffer *csi_buffer; 479 unsigned long flags; 480 481 spin_lock_irqsave(&state->lock, flags); 482 483 if (list_empty(&state->queue)) 484 goto complete; 485 486 if (state->pending) 487 goto complete; 488 489 csi_buffer = list_first_entry(&state->queue, struct sun6i_csi_buffer, 490 list); 491 492 sun6i_csi_capture_buffer_configure(csi_dev, csi_buffer); 493 494 list_del(&csi_buffer->list); 495 496 state->pending = csi_buffer; 497 498 complete: 499 spin_unlock_irqrestore(&state->lock, flags); 500 } 501 502 static void sun6i_csi_capture_state_complete(struct sun6i_csi_device *csi_dev) 503 { 504 struct sun6i_csi_capture_state *state = &csi_dev->capture.state; 505 unsigned long flags; 506 507 spin_lock_irqsave(&state->lock, flags); 508 509 if (!state->pending) 510 goto complete; 511 512 state->complete = state->current; 513 state->current = state->pending; 514 state->pending = NULL; 515 516 if (state->complete) { 517 struct sun6i_csi_buffer *csi_buffer = state->complete; 518 struct vb2_buffer *vb2_buffer = 519 &csi_buffer->v4l2_buffer.vb2_buf; 520 521 vb2_buffer->timestamp = ktime_get_ns(); 522 csi_buffer->v4l2_buffer.sequence = state->sequence; 523 524 vb2_buffer_done(vb2_buffer, VB2_BUF_STATE_DONE); 525 526 state->complete = NULL; 527 } 528 529 complete: 530 spin_unlock_irqrestore(&state->lock, flags); 531 } 532 533 void sun6i_csi_capture_frame_done(struct sun6i_csi_device *csi_dev) 534 { 535 struct sun6i_csi_capture_state *state = &csi_dev->capture.state; 536 unsigned long flags; 537 538 spin_lock_irqsave(&state->lock, flags); 539 state->sequence++; 540 spin_unlock_irqrestore(&state->lock, flags); 541 } 542 543 void sun6i_csi_capture_sync(struct sun6i_csi_device *csi_dev) 544 { 545 sun6i_csi_capture_state_complete(csi_dev); 546 sun6i_csi_capture_state_update(csi_dev); 547 } 548 549 /* Queue */ 550 551 static int sun6i_csi_capture_queue_setup(struct vb2_queue *queue, 552 unsigned int *buffers_count, 553 unsigned int *planes_count, 554 unsigned int sizes[], 555 struct device *alloc_devs[]) 556 { 557 struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue); 558 unsigned int size = csi_dev->capture.format.fmt.pix.sizeimage; 559 560 if (*planes_count) 561 return sizes[0] < size ? -EINVAL : 0; 562 563 *planes_count = 1; 564 sizes[0] = size; 565 566 return 0; 567 } 568 569 static int sun6i_csi_capture_buffer_prepare(struct vb2_buffer *buffer) 570 { 571 struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(buffer->vb2_queue); 572 struct sun6i_csi_capture *capture = &csi_dev->capture; 573 struct v4l2_device *v4l2_dev = csi_dev->v4l2_dev; 574 struct vb2_v4l2_buffer *v4l2_buffer = to_vb2_v4l2_buffer(buffer); 575 unsigned long size = capture->format.fmt.pix.sizeimage; 576 577 if (vb2_plane_size(buffer, 0) < size) { 578 v4l2_err(v4l2_dev, "buffer too small (%lu < %lu)\n", 579 vb2_plane_size(buffer, 0), size); 580 return -EINVAL; 581 } 582 583 vb2_set_plane_payload(buffer, 0, size); 584 585 v4l2_buffer->field = capture->format.fmt.pix.field; 586 587 return 0; 588 } 589 590 static void sun6i_csi_capture_buffer_queue(struct vb2_buffer *buffer) 591 { 592 struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(buffer->vb2_queue); 593 struct sun6i_csi_capture_state *state = &csi_dev->capture.state; 594 struct vb2_v4l2_buffer *v4l2_buffer = to_vb2_v4l2_buffer(buffer); 595 struct sun6i_csi_buffer *csi_buffer = 596 container_of(v4l2_buffer, struct sun6i_csi_buffer, v4l2_buffer); 597 unsigned long flags; 598 599 spin_lock_irqsave(&state->lock, flags); 600 list_add_tail(&csi_buffer->list, &state->queue); 601 spin_unlock_irqrestore(&state->lock, flags); 602 } 603 604 static int sun6i_csi_capture_start_streaming(struct vb2_queue *queue, 605 unsigned int count) 606 { 607 struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue); 608 struct sun6i_csi_capture_state *state = &csi_dev->capture.state; 609 struct video_device *video_dev = &csi_dev->capture.video_dev; 610 struct v4l2_subdev *subdev = &csi_dev->bridge.subdev; 611 int ret; 612 613 state->sequence = 0; 614 615 ret = video_device_pipeline_alloc_start(video_dev); 616 if (ret < 0) 617 goto error_state; 618 619 state->streaming = true; 620 621 ret = v4l2_subdev_call(subdev, video, s_stream, 1); 622 if (ret && ret != -ENOIOCTLCMD) 623 goto error_streaming; 624 625 return 0; 626 627 error_streaming: 628 state->streaming = false; 629 630 video_device_pipeline_stop(video_dev); 631 632 error_state: 633 sun6i_csi_capture_state_cleanup(csi_dev, false); 634 635 return ret; 636 } 637 638 static void sun6i_csi_capture_stop_streaming(struct vb2_queue *queue) 639 { 640 struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue); 641 struct sun6i_csi_capture_state *state = &csi_dev->capture.state; 642 struct video_device *video_dev = &csi_dev->capture.video_dev; 643 struct v4l2_subdev *subdev = &csi_dev->bridge.subdev; 644 645 v4l2_subdev_call(subdev, video, s_stream, 0); 646 647 state->streaming = false; 648 649 video_device_pipeline_stop(video_dev); 650 651 sun6i_csi_capture_state_cleanup(csi_dev, true); 652 } 653 654 static const struct vb2_ops sun6i_csi_capture_queue_ops = { 655 .queue_setup = sun6i_csi_capture_queue_setup, 656 .buf_prepare = sun6i_csi_capture_buffer_prepare, 657 .buf_queue = sun6i_csi_capture_buffer_queue, 658 .start_streaming = sun6i_csi_capture_start_streaming, 659 .stop_streaming = sun6i_csi_capture_stop_streaming, 660 .wait_prepare = vb2_ops_wait_prepare, 661 .wait_finish = vb2_ops_wait_finish, 662 }; 663 664 /* V4L2 Device */ 665 666 static void sun6i_csi_capture_format_prepare(struct v4l2_format *format) 667 { 668 struct v4l2_pix_format *pix_format = &format->fmt.pix; 669 const struct v4l2_format_info *info; 670 unsigned int width, height; 671 672 v4l_bound_align_image(&pix_format->width, SUN6I_CSI_CAPTURE_WIDTH_MIN, 673 SUN6I_CSI_CAPTURE_WIDTH_MAX, 1, 674 &pix_format->height, SUN6I_CSI_CAPTURE_HEIGHT_MIN, 675 SUN6I_CSI_CAPTURE_HEIGHT_MAX, 1, 0); 676 677 if (!sun6i_csi_capture_format_find(pix_format->pixelformat)) 678 pix_format->pixelformat = 679 sun6i_csi_capture_formats[0].pixelformat; 680 681 width = pix_format->width; 682 height = pix_format->height; 683 684 info = v4l2_format_info(pix_format->pixelformat); 685 686 switch (pix_format->pixelformat) { 687 case V4L2_PIX_FMT_NV12_16L16: 688 pix_format->bytesperline = width * 12 / 8; 689 pix_format->sizeimage = pix_format->bytesperline * height; 690 break; 691 case V4L2_PIX_FMT_JPEG: 692 pix_format->bytesperline = width; 693 pix_format->sizeimage = pix_format->bytesperline * height; 694 break; 695 default: 696 v4l2_fill_pixfmt(pix_format, pix_format->pixelformat, 697 width, height); 698 break; 699 } 700 701 if (pix_format->field == V4L2_FIELD_ANY) 702 pix_format->field = V4L2_FIELD_NONE; 703 704 if (pix_format->pixelformat == V4L2_PIX_FMT_JPEG) 705 pix_format->colorspace = V4L2_COLORSPACE_JPEG; 706 else if (info && info->pixel_enc == V4L2_PIXEL_ENC_BAYER) 707 pix_format->colorspace = V4L2_COLORSPACE_RAW; 708 else 709 pix_format->colorspace = V4L2_COLORSPACE_SRGB; 710 711 pix_format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 712 pix_format->quantization = V4L2_QUANTIZATION_DEFAULT; 713 pix_format->xfer_func = V4L2_XFER_FUNC_DEFAULT; 714 } 715 716 static int sun6i_csi_capture_querycap(struct file *file, void *private, 717 struct v4l2_capability *capability) 718 { 719 struct sun6i_csi_device *csi_dev = video_drvdata(file); 720 struct video_device *video_dev = &csi_dev->capture.video_dev; 721 722 strscpy(capability->driver, SUN6I_CSI_NAME, sizeof(capability->driver)); 723 strscpy(capability->card, video_dev->name, sizeof(capability->card)); 724 snprintf(capability->bus_info, sizeof(capability->bus_info), 725 "platform:%s", dev_name(csi_dev->dev)); 726 727 return 0; 728 } 729 730 static int sun6i_csi_capture_enum_fmt(struct file *file, void *private, 731 struct v4l2_fmtdesc *fmtdesc) 732 { 733 u32 index = fmtdesc->index; 734 735 if (index >= ARRAY_SIZE(sun6i_csi_capture_formats)) 736 return -EINVAL; 737 738 fmtdesc->pixelformat = sun6i_csi_capture_formats[index].pixelformat; 739 740 return 0; 741 } 742 743 static int sun6i_csi_capture_g_fmt(struct file *file, void *private, 744 struct v4l2_format *format) 745 { 746 struct sun6i_csi_device *csi_dev = video_drvdata(file); 747 748 *format = csi_dev->capture.format; 749 750 return 0; 751 } 752 753 static int sun6i_csi_capture_s_fmt(struct file *file, void *private, 754 struct v4l2_format *format) 755 { 756 struct sun6i_csi_device *csi_dev = video_drvdata(file); 757 struct sun6i_csi_capture *capture = &csi_dev->capture; 758 759 if (vb2_is_busy(&capture->queue)) 760 return -EBUSY; 761 762 sun6i_csi_capture_format_prepare(format); 763 764 csi_dev->capture.format = *format; 765 766 return 0; 767 } 768 769 static int sun6i_csi_capture_try_fmt(struct file *file, void *private, 770 struct v4l2_format *format) 771 { 772 sun6i_csi_capture_format_prepare(format); 773 774 return 0; 775 } 776 777 static int sun6i_csi_capture_enum_input(struct file *file, void *private, 778 struct v4l2_input *input) 779 { 780 if (input->index != 0) 781 return -EINVAL; 782 783 input->type = V4L2_INPUT_TYPE_CAMERA; 784 strscpy(input->name, "Camera", sizeof(input->name)); 785 786 return 0; 787 } 788 789 static int sun6i_csi_capture_g_input(struct file *file, void *private, 790 unsigned int *index) 791 { 792 *index = 0; 793 794 return 0; 795 } 796 797 static int sun6i_csi_capture_s_input(struct file *file, void *private, 798 unsigned int index) 799 { 800 if (index != 0) 801 return -EINVAL; 802 803 return 0; 804 } 805 806 static const struct v4l2_ioctl_ops sun6i_csi_capture_ioctl_ops = { 807 .vidioc_querycap = sun6i_csi_capture_querycap, 808 809 .vidioc_enum_fmt_vid_cap = sun6i_csi_capture_enum_fmt, 810 .vidioc_g_fmt_vid_cap = sun6i_csi_capture_g_fmt, 811 .vidioc_s_fmt_vid_cap = sun6i_csi_capture_s_fmt, 812 .vidioc_try_fmt_vid_cap = sun6i_csi_capture_try_fmt, 813 814 .vidioc_enum_input = sun6i_csi_capture_enum_input, 815 .vidioc_g_input = sun6i_csi_capture_g_input, 816 .vidioc_s_input = sun6i_csi_capture_s_input, 817 818 .vidioc_create_bufs = vb2_ioctl_create_bufs, 819 .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 820 .vidioc_reqbufs = vb2_ioctl_reqbufs, 821 .vidioc_querybuf = vb2_ioctl_querybuf, 822 .vidioc_expbuf = vb2_ioctl_expbuf, 823 .vidioc_qbuf = vb2_ioctl_qbuf, 824 .vidioc_dqbuf = vb2_ioctl_dqbuf, 825 .vidioc_streamon = vb2_ioctl_streamon, 826 .vidioc_streamoff = vb2_ioctl_streamoff, 827 }; 828 829 /* V4L2 File */ 830 831 static int sun6i_csi_capture_open(struct file *file) 832 { 833 struct sun6i_csi_device *csi_dev = video_drvdata(file); 834 struct sun6i_csi_capture *capture = &csi_dev->capture; 835 int ret; 836 837 if (mutex_lock_interruptible(&capture->lock)) 838 return -ERESTARTSYS; 839 840 ret = v4l2_pipeline_pm_get(&capture->video_dev.entity); 841 if (ret < 0) 842 goto error_lock; 843 844 ret = v4l2_fh_open(file); 845 if (ret < 0) 846 goto error_pipeline; 847 848 mutex_unlock(&capture->lock); 849 850 return 0; 851 852 error_pipeline: 853 v4l2_pipeline_pm_put(&capture->video_dev.entity); 854 855 error_lock: 856 mutex_unlock(&capture->lock); 857 858 return ret; 859 } 860 861 static int sun6i_csi_capture_close(struct file *file) 862 { 863 struct sun6i_csi_device *csi_dev = video_drvdata(file); 864 struct sun6i_csi_capture *capture = &csi_dev->capture; 865 866 mutex_lock(&capture->lock); 867 868 _vb2_fop_release(file, NULL); 869 v4l2_pipeline_pm_put(&capture->video_dev.entity); 870 871 mutex_unlock(&capture->lock); 872 873 return 0; 874 } 875 876 static const struct v4l2_file_operations sun6i_csi_capture_fops = { 877 .owner = THIS_MODULE, 878 .open = sun6i_csi_capture_open, 879 .release = sun6i_csi_capture_close, 880 .unlocked_ioctl = video_ioctl2, 881 .mmap = vb2_fop_mmap, 882 .poll = vb2_fop_poll 883 }; 884 885 /* Media Entity */ 886 887 static int sun6i_csi_capture_link_validate(struct media_link *link) 888 { 889 struct video_device *video_dev = 890 media_entity_to_video_device(link->sink->entity); 891 struct sun6i_csi_device *csi_dev = video_get_drvdata(video_dev); 892 struct v4l2_device *v4l2_dev = csi_dev->v4l2_dev; 893 const struct sun6i_csi_capture_format *capture_format; 894 const struct sun6i_csi_bridge_format *bridge_format; 895 unsigned int capture_width, capture_height; 896 unsigned int bridge_width, bridge_height; 897 const struct v4l2_format_info *format_info; 898 u32 pixelformat, capture_field; 899 u32 mbus_code, bridge_field; 900 bool match; 901 902 sun6i_csi_capture_dimensions(csi_dev, &capture_width, &capture_height); 903 904 sun6i_csi_capture_format(csi_dev, &pixelformat, &capture_field); 905 capture_format = sun6i_csi_capture_format_find(pixelformat); 906 if (WARN_ON(!capture_format)) 907 return -EINVAL; 908 909 sun6i_csi_bridge_dimensions(csi_dev, &bridge_width, &bridge_height); 910 911 sun6i_csi_bridge_format(csi_dev, &mbus_code, &bridge_field); 912 bridge_format = sun6i_csi_bridge_format_find(mbus_code); 913 if (WARN_ON(!bridge_format)) 914 return -EINVAL; 915 916 /* No cropping/scaling is supported. */ 917 if (capture_width != bridge_width || capture_height != bridge_height) { 918 v4l2_err(v4l2_dev, 919 "invalid input/output dimensions: %ux%u/%ux%u\n", 920 bridge_width, bridge_height, capture_width, 921 capture_height); 922 return -EINVAL; 923 } 924 925 format_info = v4l2_format_info(pixelformat); 926 /* Some formats are not listed. */ 927 if (!format_info) 928 return 0; 929 930 if (format_info->pixel_enc == V4L2_PIXEL_ENC_BAYER && 931 bridge_format->input_format != SUN6I_CSI_INPUT_FMT_RAW) 932 goto invalid; 933 934 if (format_info->pixel_enc == V4L2_PIXEL_ENC_RGB && 935 bridge_format->input_format != SUN6I_CSI_INPUT_FMT_RAW) 936 goto invalid; 937 938 if (format_info->pixel_enc == V4L2_PIXEL_ENC_YUV) { 939 if (bridge_format->input_format != SUN6I_CSI_INPUT_FMT_YUV420 && 940 bridge_format->input_format != SUN6I_CSI_INPUT_FMT_YUV422) 941 goto invalid; 942 943 /* YUV420 input can't produce YUV422 output. */ 944 if (bridge_format->input_format == SUN6I_CSI_INPUT_FMT_YUV420 && 945 format_info->vdiv == 1) 946 goto invalid; 947 } 948 949 /* With raw input mode, we need a 1:1 match between input and output. */ 950 if (bridge_format->input_format == SUN6I_CSI_INPUT_FMT_RAW || 951 capture_format->input_format_raw) { 952 match = sun6i_csi_capture_format_match(pixelformat, mbus_code); 953 if (!match) 954 goto invalid; 955 } 956 957 return 0; 958 959 invalid: 960 v4l2_err(v4l2_dev, "invalid input/output format combination\n"); 961 return -EINVAL; 962 } 963 964 static const struct media_entity_operations sun6i_csi_capture_media_ops = { 965 .link_validate = sun6i_csi_capture_link_validate 966 }; 967 968 /* Capture */ 969 970 int sun6i_csi_capture_setup(struct sun6i_csi_device *csi_dev) 971 { 972 struct sun6i_csi_capture *capture = &csi_dev->capture; 973 struct sun6i_csi_capture_state *state = &capture->state; 974 struct v4l2_device *v4l2_dev = csi_dev->v4l2_dev; 975 struct v4l2_subdev *bridge_subdev = &csi_dev->bridge.subdev; 976 struct video_device *video_dev = &capture->video_dev; 977 struct vb2_queue *queue = &capture->queue; 978 struct media_pad *pad = &capture->pad; 979 struct v4l2_format *format = &csi_dev->capture.format; 980 struct v4l2_pix_format *pix_format = &format->fmt.pix; 981 int ret; 982 983 /* This may happen with multiple bridge notifier bound calls. */ 984 if (state->setup) 985 return 0; 986 987 /* State */ 988 989 INIT_LIST_HEAD(&state->queue); 990 spin_lock_init(&state->lock); 991 992 /* Media Entity */ 993 994 video_dev->entity.ops = &sun6i_csi_capture_media_ops; 995 996 /* Media Pad */ 997 998 pad->flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; 999 1000 ret = media_entity_pads_init(&video_dev->entity, 1, pad); 1001 if (ret < 0) 1002 return ret; 1003 1004 /* Queue */ 1005 1006 mutex_init(&capture->lock); 1007 1008 queue->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1009 queue->io_modes = VB2_MMAP | VB2_DMABUF; 1010 queue->buf_struct_size = sizeof(struct sun6i_csi_buffer); 1011 queue->ops = &sun6i_csi_capture_queue_ops; 1012 queue->mem_ops = &vb2_dma_contig_memops; 1013 queue->min_buffers_needed = 2; 1014 queue->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 1015 queue->lock = &capture->lock; 1016 queue->dev = csi_dev->dev; 1017 queue->drv_priv = csi_dev; 1018 1019 ret = vb2_queue_init(queue); 1020 if (ret) { 1021 v4l2_err(v4l2_dev, "failed to initialize vb2 queue: %d\n", ret); 1022 goto error_media_entity; 1023 } 1024 1025 /* V4L2 Format */ 1026 1027 format->type = queue->type; 1028 pix_format->pixelformat = sun6i_csi_capture_formats[0].pixelformat; 1029 pix_format->width = 1280; 1030 pix_format->height = 720; 1031 pix_format->field = V4L2_FIELD_NONE; 1032 1033 sun6i_csi_capture_format_prepare(format); 1034 1035 /* Video Device */ 1036 1037 strscpy(video_dev->name, SUN6I_CSI_CAPTURE_NAME, 1038 sizeof(video_dev->name)); 1039 video_dev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; 1040 video_dev->vfl_dir = VFL_DIR_RX; 1041 video_dev->release = video_device_release_empty; 1042 video_dev->fops = &sun6i_csi_capture_fops; 1043 video_dev->ioctl_ops = &sun6i_csi_capture_ioctl_ops; 1044 video_dev->v4l2_dev = v4l2_dev; 1045 video_dev->queue = queue; 1046 video_dev->lock = &capture->lock; 1047 1048 video_set_drvdata(video_dev, csi_dev); 1049 1050 ret = video_register_device(video_dev, VFL_TYPE_VIDEO, -1); 1051 if (ret < 0) { 1052 v4l2_err(v4l2_dev, "failed to register video device: %d\n", 1053 ret); 1054 goto error_media_entity; 1055 } 1056 1057 /* Media Pad Link */ 1058 1059 ret = media_create_pad_link(&bridge_subdev->entity, 1060 SUN6I_CSI_BRIDGE_PAD_SOURCE, 1061 &video_dev->entity, 0, 1062 csi_dev->isp_available ? 0 : 1063 MEDIA_LNK_FL_ENABLED | 1064 MEDIA_LNK_FL_IMMUTABLE); 1065 if (ret < 0) { 1066 v4l2_err(v4l2_dev, "failed to create %s:%u -> %s:%u link\n", 1067 bridge_subdev->entity.name, 1068 SUN6I_CSI_BRIDGE_PAD_SOURCE, 1069 video_dev->entity.name, 0); 1070 goto error_video_device; 1071 } 1072 1073 state->setup = true; 1074 1075 return 0; 1076 1077 error_video_device: 1078 vb2_video_unregister_device(video_dev); 1079 1080 error_media_entity: 1081 media_entity_cleanup(&video_dev->entity); 1082 1083 mutex_destroy(&capture->lock); 1084 1085 return ret; 1086 } 1087 1088 void sun6i_csi_capture_cleanup(struct sun6i_csi_device *csi_dev) 1089 { 1090 struct sun6i_csi_capture *capture = &csi_dev->capture; 1091 struct video_device *video_dev = &capture->video_dev; 1092 1093 /* This may happen if async registration failed to complete. */ 1094 if (!capture->state.setup) 1095 return; 1096 1097 vb2_video_unregister_device(video_dev); 1098 media_entity_cleanup(&video_dev->entity); 1099 mutex_destroy(&capture->lock); 1100 1101 capture->state.setup = false; 1102 } 1103