1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * V4L2 Capture ISI subdev driver for i.MX8QXP/QM platform 4 * 5 * ISI is a Image Sensor Interface of i.MX8QXP/QM platform, which 6 * used to process image from camera sensor to memory or DC 7 * 8 * Copyright (c) 2019 NXP Semiconductor 9 */ 10 11 #include <linux/device.h> 12 #include <linux/dma-mapping.h> 13 #include <linux/errno.h> 14 #include <linux/kernel.h> 15 #include <linux/media-bus-format.h> 16 #include <linux/minmax.h> 17 #include <linux/pm_runtime.h> 18 #include <linux/string.h> 19 #include <linux/types.h> 20 #include <linux/videodev2.h> 21 22 #include <media/media-entity.h> 23 #include <media/v4l2-ctrls.h> 24 #include <media/v4l2-dev.h> 25 #include <media/v4l2-event.h> 26 #include <media/v4l2-fh.h> 27 #include <media/v4l2-ioctl.h> 28 #include <media/v4l2-subdev.h> 29 #include <media/videobuf2-core.h> 30 #include <media/videobuf2-dma-contig.h> 31 #include <media/videobuf2-v4l2.h> 32 33 #include "imx8-isi-core.h" 34 #include "imx8-isi-regs.h" 35 36 /* Keep the first entry matching MXC_ISI_DEF_PIXEL_FORMAT */ 37 static const struct mxc_isi_format_info mxc_isi_formats[] = { 38 /* YUV formats */ 39 { 40 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24, 41 .fourcc = V4L2_PIX_FMT_YUYV, 42 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT 43 | MXC_ISI_VIDEO_M2M_CAP, 44 .isi_in_format = CHNL_MEM_RD_CTRL_IMG_TYPE_YUV422_1P8P, 45 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV422_1P8P, 46 .mem_planes = 1, 47 .color_planes = 1, 48 .depth = { 16 }, 49 .encoding = MXC_ISI_ENC_YUV, 50 }, { 51 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24, 52 .fourcc = V4L2_PIX_FMT_YUVA32, 53 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP, 54 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV444_1P8, 55 .mem_planes = 1, 56 .color_planes = 1, 57 .depth = { 32 }, 58 .encoding = MXC_ISI_ENC_YUV, 59 }, { 60 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24, 61 .fourcc = V4L2_PIX_FMT_NV12, 62 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP, 63 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV420_2P8P, 64 .color_planes = 2, 65 .mem_planes = 1, 66 .depth = { 8, 16 }, 67 .hsub = 2, 68 .vsub = 2, 69 .encoding = MXC_ISI_ENC_YUV, 70 }, { 71 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24, 72 .fourcc = V4L2_PIX_FMT_NV12M, 73 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP, 74 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV420_2P8P, 75 .mem_planes = 2, 76 .color_planes = 2, 77 .depth = { 8, 16 }, 78 .hsub = 2, 79 .vsub = 2, 80 .encoding = MXC_ISI_ENC_YUV, 81 }, { 82 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24, 83 .fourcc = V4L2_PIX_FMT_NV16, 84 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP, 85 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV422_2P8P, 86 .color_planes = 2, 87 .mem_planes = 1, 88 .depth = { 8, 16 }, 89 .hsub = 2, 90 .vsub = 1, 91 .encoding = MXC_ISI_ENC_YUV, 92 }, { 93 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24, 94 .fourcc = V4L2_PIX_FMT_NV16M, 95 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP, 96 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV422_2P8P, 97 .mem_planes = 2, 98 .color_planes = 2, 99 .depth = { 8, 16 }, 100 .hsub = 2, 101 .vsub = 1, 102 .encoding = MXC_ISI_ENC_YUV, 103 }, { 104 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24, 105 .fourcc = V4L2_PIX_FMT_YUV444M, 106 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP, 107 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV444_3P8P, 108 .mem_planes = 3, 109 .color_planes = 3, 110 .depth = { 8, 8, 8 }, 111 .hsub = 1, 112 .vsub = 1, 113 .encoding = MXC_ISI_ENC_YUV, 114 }, 115 /* RGB formats */ 116 { 117 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, 118 .fourcc = V4L2_PIX_FMT_RGB565, 119 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT 120 | MXC_ISI_VIDEO_M2M_CAP, 121 .isi_in_format = CHNL_MEM_RD_CTRL_IMG_TYPE_RGB565, 122 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RGB565, 123 .mem_planes = 1, 124 .color_planes = 1, 125 .depth = { 16 }, 126 .encoding = MXC_ISI_ENC_RGB, 127 }, { 128 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, 129 .fourcc = V4L2_PIX_FMT_RGB24, 130 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT 131 | MXC_ISI_VIDEO_M2M_CAP, 132 .isi_in_format = CHNL_MEM_RD_CTRL_IMG_TYPE_BGR8P, 133 .isi_out_format = CHNL_IMG_CTRL_FORMAT_BGR888P, 134 .mem_planes = 1, 135 .color_planes = 1, 136 .depth = { 24 }, 137 .encoding = MXC_ISI_ENC_RGB, 138 }, { 139 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, 140 .fourcc = V4L2_PIX_FMT_BGR24, 141 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT 142 | MXC_ISI_VIDEO_M2M_CAP, 143 .isi_in_format = CHNL_MEM_RD_CTRL_IMG_TYPE_RGB8P, 144 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RGB888P, 145 .mem_planes = 1, 146 .color_planes = 1, 147 .depth = { 24 }, 148 .encoding = MXC_ISI_ENC_RGB, 149 }, { 150 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, 151 .fourcc = V4L2_PIX_FMT_XBGR32, 152 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT 153 | MXC_ISI_VIDEO_M2M_CAP, 154 .isi_in_format = CHNL_MEM_RD_CTRL_IMG_TYPE_XBGR8, 155 .isi_out_format = CHNL_IMG_CTRL_FORMAT_XRGB888, 156 .mem_planes = 1, 157 .color_planes = 1, 158 .depth = { 32 }, 159 .encoding = MXC_ISI_ENC_RGB, 160 }, { 161 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, 162 .fourcc = V4L2_PIX_FMT_ABGR32, 163 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP, 164 .isi_out_format = CHNL_IMG_CTRL_FORMAT_ARGB8888, 165 .mem_planes = 1, 166 .color_planes = 1, 167 .depth = { 32 }, 168 .encoding = MXC_ISI_ENC_RGB, 169 }, 170 /* 171 * RAW formats 172 * 173 * The ISI shifts the 10-bit and 12-bit formats left by 6 and 4 bits 174 * when using CHNL_IMG_CTRL_FORMAT_RAW10 or MXC_ISI_OUT_FMT_RAW12 175 * respectively, to align the bits to the left and pad with zeros in 176 * the LSBs. The corresponding V4L2 formats are however right-aligned, 177 * we have to use CHNL_IMG_CTRL_FORMAT_RAW16 to avoid the left shift. 178 */ 179 { 180 .mbus_code = MEDIA_BUS_FMT_Y8_1X8, 181 .fourcc = V4L2_PIX_FMT_GREY, 182 .type = MXC_ISI_VIDEO_CAP, 183 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8, 184 .mem_planes = 1, 185 .color_planes = 1, 186 .depth = { 8 }, 187 .encoding = MXC_ISI_ENC_RAW, 188 }, { 189 .mbus_code = MEDIA_BUS_FMT_Y10_1X10, 190 .fourcc = V4L2_PIX_FMT_Y10, 191 .type = MXC_ISI_VIDEO_CAP, 192 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 193 .mem_planes = 1, 194 .color_planes = 1, 195 .depth = { 16 }, 196 .encoding = MXC_ISI_ENC_RAW, 197 }, { 198 .mbus_code = MEDIA_BUS_FMT_Y12_1X12, 199 .fourcc = V4L2_PIX_FMT_Y12, 200 .type = MXC_ISI_VIDEO_CAP, 201 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 202 .mem_planes = 1, 203 .color_planes = 1, 204 .depth = { 16 }, 205 .encoding = MXC_ISI_ENC_RAW, 206 }, { 207 .mbus_code = MEDIA_BUS_FMT_Y14_1X14, 208 .fourcc = V4L2_PIX_FMT_Y14, 209 .type = MXC_ISI_VIDEO_CAP, 210 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 211 .mem_planes = 1, 212 .color_planes = 1, 213 .depth = { 16 }, 214 .encoding = MXC_ISI_ENC_RAW, 215 }, { 216 .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, 217 .fourcc = V4L2_PIX_FMT_SBGGR8, 218 .type = MXC_ISI_VIDEO_CAP, 219 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8, 220 .mem_planes = 1, 221 .color_planes = 1, 222 .depth = { 8 }, 223 .encoding = MXC_ISI_ENC_RAW, 224 }, { 225 .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, 226 .fourcc = V4L2_PIX_FMT_SGBRG8, 227 .type = MXC_ISI_VIDEO_CAP, 228 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8, 229 .mem_planes = 1, 230 .color_planes = 1, 231 .depth = { 8 }, 232 .encoding = MXC_ISI_ENC_RAW, 233 }, { 234 .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, 235 .fourcc = V4L2_PIX_FMT_SGRBG8, 236 .type = MXC_ISI_VIDEO_CAP, 237 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8, 238 .mem_planes = 1, 239 .color_planes = 1, 240 .depth = { 8 }, 241 .encoding = MXC_ISI_ENC_RAW, 242 }, { 243 .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, 244 .fourcc = V4L2_PIX_FMT_SRGGB8, 245 .type = MXC_ISI_VIDEO_CAP, 246 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8, 247 .mem_planes = 1, 248 .color_planes = 1, 249 .depth = { 8 }, 250 .encoding = MXC_ISI_ENC_RAW, 251 }, { 252 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, 253 .fourcc = V4L2_PIX_FMT_SBGGR10, 254 .type = MXC_ISI_VIDEO_CAP, 255 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 256 .mem_planes = 1, 257 .color_planes = 1, 258 .depth = { 16 }, 259 .encoding = MXC_ISI_ENC_RAW, 260 }, { 261 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, 262 .fourcc = V4L2_PIX_FMT_SGBRG10, 263 .type = MXC_ISI_VIDEO_CAP, 264 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 265 .mem_planes = 1, 266 .color_planes = 1, 267 .depth = { 16 }, 268 .encoding = MXC_ISI_ENC_RAW, 269 }, { 270 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, 271 .fourcc = V4L2_PIX_FMT_SGRBG10, 272 .type = MXC_ISI_VIDEO_CAP, 273 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 274 .mem_planes = 1, 275 .color_planes = 1, 276 .depth = { 16 }, 277 .encoding = MXC_ISI_ENC_RAW, 278 }, { 279 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, 280 .fourcc = V4L2_PIX_FMT_SRGGB10, 281 .type = MXC_ISI_VIDEO_CAP, 282 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 283 .mem_planes = 1, 284 .color_planes = 1, 285 .depth = { 16 }, 286 .encoding = MXC_ISI_ENC_RAW, 287 }, { 288 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, 289 .fourcc = V4L2_PIX_FMT_SBGGR12, 290 .type = MXC_ISI_VIDEO_CAP, 291 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 292 .mem_planes = 1, 293 .color_planes = 1, 294 .depth = { 16 }, 295 .encoding = MXC_ISI_ENC_RAW, 296 }, { 297 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, 298 .fourcc = V4L2_PIX_FMT_SGBRG12, 299 .type = MXC_ISI_VIDEO_CAP, 300 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 301 .mem_planes = 1, 302 .color_planes = 1, 303 .depth = { 16 }, 304 .encoding = MXC_ISI_ENC_RAW, 305 }, { 306 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, 307 .fourcc = V4L2_PIX_FMT_SGRBG12, 308 .type = MXC_ISI_VIDEO_CAP, 309 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 310 .mem_planes = 1, 311 .color_planes = 1, 312 .depth = { 16 }, 313 .encoding = MXC_ISI_ENC_RAW, 314 }, { 315 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, 316 .fourcc = V4L2_PIX_FMT_SRGGB12, 317 .type = MXC_ISI_VIDEO_CAP, 318 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 319 .mem_planes = 1, 320 .color_planes = 1, 321 .depth = { 16 }, 322 .encoding = MXC_ISI_ENC_RAW, 323 }, { 324 .mbus_code = MEDIA_BUS_FMT_SBGGR14_1X14, 325 .fourcc = V4L2_PIX_FMT_SBGGR14, 326 .type = MXC_ISI_VIDEO_CAP, 327 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 328 .mem_planes = 1, 329 .color_planes = 1, 330 .depth = { 16 }, 331 .encoding = MXC_ISI_ENC_RAW, 332 }, { 333 .mbus_code = MEDIA_BUS_FMT_SGBRG14_1X14, 334 .fourcc = V4L2_PIX_FMT_SGBRG14, 335 .type = MXC_ISI_VIDEO_CAP, 336 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 337 .mem_planes = 1, 338 .color_planes = 1, 339 .depth = { 16 }, 340 .encoding = MXC_ISI_ENC_RAW, 341 }, { 342 .mbus_code = MEDIA_BUS_FMT_SGRBG14_1X14, 343 .fourcc = V4L2_PIX_FMT_SGRBG14, 344 .type = MXC_ISI_VIDEO_CAP, 345 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 346 .mem_planes = 1, 347 .color_planes = 1, 348 .depth = { 16 }, 349 .encoding = MXC_ISI_ENC_RAW, 350 }, { 351 .mbus_code = MEDIA_BUS_FMT_SRGGB14_1X14, 352 .fourcc = V4L2_PIX_FMT_SRGGB14, 353 .type = MXC_ISI_VIDEO_CAP, 354 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16, 355 .mem_planes = 1, 356 .color_planes = 1, 357 .depth = { 16 }, 358 .encoding = MXC_ISI_ENC_RAW, 359 }, 360 /* JPEG */ 361 { 362 .mbus_code = MEDIA_BUS_FMT_JPEG_1X8, 363 .fourcc = V4L2_PIX_FMT_MJPEG, 364 .type = MXC_ISI_VIDEO_CAP, 365 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8, 366 .mem_planes = 1, 367 .color_planes = 1, 368 .depth = { 8 }, 369 .encoding = MXC_ISI_ENC_RAW, 370 } 371 }; 372 373 const struct mxc_isi_format_info * 374 mxc_isi_format_by_fourcc(u32 fourcc, enum mxc_isi_video_type type) 375 { 376 unsigned int i; 377 378 for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) { 379 const struct mxc_isi_format_info *fmt = &mxc_isi_formats[i]; 380 381 if (fmt->fourcc == fourcc && fmt->type & type) 382 return fmt; 383 } 384 385 return NULL; 386 } 387 388 const struct mxc_isi_format_info * 389 mxc_isi_format_enum(unsigned int index, enum mxc_isi_video_type type) 390 { 391 unsigned int i; 392 393 for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) { 394 const struct mxc_isi_format_info *fmt = &mxc_isi_formats[i]; 395 396 if (!(fmt->type & type)) 397 continue; 398 399 if (!index) 400 return fmt; 401 402 index--; 403 } 404 405 return NULL; 406 } 407 408 const struct mxc_isi_format_info * 409 mxc_isi_format_try(struct mxc_isi_pipe *pipe, struct v4l2_pix_format_mplane *pix, 410 enum mxc_isi_video_type type) 411 { 412 const struct mxc_isi_format_info *fmt; 413 unsigned int max_width; 414 unsigned int i; 415 416 max_width = pipe->id == pipe->isi->pdata->num_channels - 1 417 ? MXC_ISI_MAX_WIDTH_UNCHAINED 418 : MXC_ISI_MAX_WIDTH_CHAINED; 419 420 fmt = mxc_isi_format_by_fourcc(pix->pixelformat, type); 421 if (!fmt) 422 fmt = &mxc_isi_formats[0]; 423 424 pix->width = clamp(pix->width, MXC_ISI_MIN_WIDTH, max_width); 425 pix->height = clamp(pix->height, MXC_ISI_MIN_HEIGHT, MXC_ISI_MAX_HEIGHT); 426 pix->pixelformat = fmt->fourcc; 427 pix->field = V4L2_FIELD_NONE; 428 429 if (pix->colorspace == V4L2_COLORSPACE_DEFAULT) { 430 pix->colorspace = MXC_ISI_DEF_COLOR_SPACE; 431 pix->ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC; 432 pix->quantization = MXC_ISI_DEF_QUANTIZATION; 433 pix->xfer_func = MXC_ISI_DEF_XFER_FUNC; 434 } 435 436 if (pix->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) 437 pix->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace); 438 if (pix->quantization == V4L2_QUANTIZATION_DEFAULT) { 439 bool is_rgb = fmt->encoding == MXC_ISI_ENC_RGB; 440 441 pix->quantization = 442 V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb, pix->colorspace, 443 pix->ycbcr_enc); 444 } 445 if (pix->xfer_func == V4L2_XFER_FUNC_DEFAULT) 446 pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace); 447 448 pix->num_planes = fmt->mem_planes; 449 450 for (i = 0; i < fmt->color_planes; ++i) { 451 struct v4l2_plane_pix_format *plane = &pix->plane_fmt[i]; 452 unsigned int bpl; 453 454 /* The pitch must be identical for all planes. */ 455 if (i == 0) 456 bpl = clamp(plane->bytesperline, 457 pix->width * fmt->depth[0] / 8, 458 65535U); 459 else 460 bpl = pix->plane_fmt[0].bytesperline; 461 462 plane->bytesperline = bpl; 463 464 plane->sizeimage = plane->bytesperline * pix->height; 465 if (i >= 1) 466 plane->sizeimage /= fmt->vsub; 467 } 468 469 /* 470 * For single-planar pixel formats with multiple color planes, 471 * concatenate the size of all planes and clear all planes but the 472 * first one. 473 */ 474 if (fmt->color_planes != fmt->mem_planes) { 475 for (i = 1; i < fmt->color_planes; ++i) { 476 struct v4l2_plane_pix_format *plane = &pix->plane_fmt[i]; 477 478 pix->plane_fmt[0].sizeimage += plane->sizeimage; 479 plane->bytesperline = 0; 480 plane->sizeimage = 0; 481 } 482 } 483 484 return fmt; 485 } 486 487 /* ----------------------------------------------------------------------------- 488 * videobuf2 queue operations 489 */ 490 491 static void mxc_isi_video_frame_write_done(struct mxc_isi_pipe *pipe, 492 u32 status) 493 { 494 struct mxc_isi_video *video = &pipe->video; 495 struct device *dev = pipe->isi->dev; 496 struct mxc_isi_buffer *next_buf; 497 struct mxc_isi_buffer *buf; 498 enum mxc_isi_buf_id buf_id; 499 500 spin_lock(&video->buf_lock); 501 502 /* 503 * The ISI hardware handles buffers using a ping-pong mechanism with 504 * two sets of destination addresses (with shadow registers to allow 505 * programming addresses for all planes atomically) named BUF1 and 506 * BUF2. Addresses can be loaded and copied to shadow registers at any 507 * at any time. 508 * 509 * The hardware keeps track of which buffer is being written to and 510 * automatically switches to the other buffer at frame end, copying the 511 * corresponding address to another set of shadow registers that track 512 * the address being written to. The active buffer tracking bits are 513 * accessible through the CHNL_STS register. 514 * 515 * BUF1 BUF2 | Event | Action 516 * | | 517 * | | Program initial buffers 518 * | | B0 in BUF1, B1 in BUF2 519 * | Start ISI | 520 * +----+ | | 521 * | B0 | | | 522 * +----+ | | 523 * +----+ | FRM IRQ 0 | B0 complete, BUF2 now active 524 * | B1 | | | Program B2 in BUF1 525 * +----+ | | 526 * +----+ | FRM IRQ 1 | B1 complete, BUF1 now active 527 * | B2 | | | Program B3 in BUF2 528 * +----+ | | 529 * +----+ | FRM IRQ 2 | B2 complete, BUF2 now active 530 * | B3 | | | Program B4 in BUF1 531 * +----+ | | 532 * +----+ | FRM IRQ 3 | B3 complete, BUF1 now active 533 * | B4 | | | Program B5 in BUF2 534 * +----+ | | 535 * ... | | 536 * 537 * Races between address programming and buffer switching can be 538 * detected by checking if a frame end interrupt occurred after 539 * programming the addresses. 540 * 541 * As none of the shadow registers are accessible, races can occur 542 * between address programming and buffer switching. It is possible to 543 * detect the race condition by checking if a frame end interrupt 544 * occurred after programming the addresses, but impossible to 545 * determine if the race has been won or lost. 546 * 547 * In addition to this, we need to use discard buffers if no pending 548 * buffers are available. To simplify handling of discard buffer, we 549 * need to allocate three of them, as two can be active concurrently 550 * and we need to still be able to get hold of a next buffer. The logic 551 * could be improved to use two buffers only, but as all discard 552 * buffers share the same memory, an additional buffer is cheap. 553 */ 554 555 /* Check which buffer has just completed. */ 556 buf_id = pipe->isi->pdata->buf_active_reverse 557 ? (status & CHNL_STS_BUF1_ACTIVE ? MXC_ISI_BUF2 : MXC_ISI_BUF1) 558 : (status & CHNL_STS_BUF1_ACTIVE ? MXC_ISI_BUF1 : MXC_ISI_BUF2); 559 560 buf = list_first_entry_or_null(&video->out_active, 561 struct mxc_isi_buffer, list); 562 563 /* Safety check, this should really never happen. */ 564 if (!buf) { 565 dev_warn(dev, "trying to access empty active list\n"); 566 goto done; 567 } 568 569 /* 570 * If the buffer that has completed doesn't match the buffer on the 571 * front of the active list, it means we have lost one frame end 572 * interrupt (or possibly a large odd number of interrupts, although 573 * quite unlikely). 574 * 575 * For instance, if IRQ1 is lost and we handle IRQ2, both B1 and B2 576 * have been completed, but B3 hasn't been programmed, BUF2 still 577 * addresses B1 and the ISI is now writing in B1 instead of B3. We 578 * can't complete B2 as that would result in out-of-order completion. 579 * 580 * The only option is to ignore this interrupt and try again. When IRQ3 581 * will be handled, we will complete B1 and be in sync again. 582 */ 583 if (buf->id != buf_id) { 584 dev_dbg(dev, "buffer ID mismatch (expected %u, got %u), skipping\n", 585 buf->id, buf_id); 586 587 /* 588 * Increment the frame count by two to account for the missed 589 * and the ignored interrupts. 590 */ 591 video->frame_count += 2; 592 goto done; 593 } 594 595 /* Pick the next buffer and queue it to the hardware. */ 596 next_buf = list_first_entry_or_null(&video->out_pending, 597 struct mxc_isi_buffer, list); 598 if (!next_buf) { 599 next_buf = list_first_entry_or_null(&video->out_discard, 600 struct mxc_isi_buffer, list); 601 602 /* Safety check, this should never happen. */ 603 if (!next_buf) { 604 dev_warn(dev, "trying to access empty discard list\n"); 605 goto done; 606 } 607 } 608 609 mxc_isi_channel_set_outbuf(pipe, next_buf->dma_addrs, buf_id); 610 next_buf->id = buf_id; 611 612 /* 613 * Check if we have raced with the end of frame interrupt. If so, we 614 * can't tell if the ISI has recorded the new address, or is still 615 * using the previous buffer. We must assume the latter as that is the 616 * worst case. 617 * 618 * For instance, if we are handling IRQ1 and now detect the FRM 619 * interrupt, assume B2 has completed and the ISI has switched to BUF2 620 * using B1 just before we programmed B3. Unlike in the previous race 621 * condition, B3 has been programmed and will be written to the next 622 * time the ISI switches to BUF2. We can however handle this exactly as 623 * the first race condition, as we'll program B3 (still at the head of 624 * the pending list) when handling IRQ3. 625 */ 626 status = mxc_isi_channel_irq_status(pipe, false); 627 if (status & CHNL_STS_FRM_STRD) { 628 dev_dbg(dev, "raced with frame end interrupt\n"); 629 video->frame_count += 2; 630 goto done; 631 } 632 633 /* 634 * The next buffer has been queued successfully, move it to the active 635 * list, and complete the current buffer. 636 */ 637 list_move_tail(&next_buf->list, &video->out_active); 638 639 if (!buf->discard) { 640 list_del_init(&buf->list); 641 buf->v4l2_buf.sequence = video->frame_count; 642 buf->v4l2_buf.vb2_buf.timestamp = ktime_get_ns(); 643 vb2_buffer_done(&buf->v4l2_buf.vb2_buf, VB2_BUF_STATE_DONE); 644 } else { 645 list_move_tail(&buf->list, &video->out_discard); 646 } 647 648 video->frame_count++; 649 650 done: 651 spin_unlock(&video->buf_lock); 652 } 653 654 static void mxc_isi_video_free_discard_buffers(struct mxc_isi_video *video) 655 { 656 unsigned int i; 657 658 for (i = 0; i < video->pix.num_planes; i++) { 659 struct mxc_isi_dma_buffer *buf = &video->discard_buffer[i]; 660 661 if (!buf->addr) 662 continue; 663 664 dma_free_coherent(video->pipe->isi->dev, buf->size, buf->addr, 665 buf->dma); 666 buf->addr = NULL; 667 } 668 } 669 670 static int mxc_isi_video_alloc_discard_buffers(struct mxc_isi_video *video) 671 { 672 unsigned int i, j; 673 674 /* Allocate memory for each plane. */ 675 for (i = 0; i < video->pix.num_planes; i++) { 676 struct mxc_isi_dma_buffer *buf = &video->discard_buffer[i]; 677 678 buf->size = PAGE_ALIGN(video->pix.plane_fmt[i].sizeimage); 679 buf->addr = dma_alloc_coherent(video->pipe->isi->dev, buf->size, 680 &buf->dma, GFP_DMA | GFP_KERNEL); 681 if (!buf->addr) { 682 mxc_isi_video_free_discard_buffers(video); 683 return -ENOMEM; 684 } 685 686 dev_dbg(video->pipe->isi->dev, 687 "discard buffer plane %u: %zu bytes @%pad (CPU address %p)\n", 688 i, buf->size, &buf->dma, buf->addr); 689 } 690 691 /* Fill the DMA addresses in the discard buffers. */ 692 for (i = 0; i < ARRAY_SIZE(video->buf_discard); ++i) { 693 struct mxc_isi_buffer *buf = &video->buf_discard[i]; 694 695 buf->discard = true; 696 697 for (j = 0; j < video->pix.num_planes; ++j) 698 buf->dma_addrs[j] = video->discard_buffer[j].dma; 699 } 700 701 return 0; 702 } 703 704 static int mxc_isi_video_validate_format(struct mxc_isi_video *video) 705 { 706 const struct v4l2_mbus_framefmt *format; 707 const struct mxc_isi_format_info *info; 708 struct v4l2_subdev_state *state; 709 struct v4l2_subdev *sd = &video->pipe->sd; 710 int ret = 0; 711 712 state = v4l2_subdev_lock_and_get_active_state(sd); 713 714 info = mxc_isi_format_by_fourcc(video->pix.pixelformat, 715 MXC_ISI_VIDEO_CAP); 716 format = v4l2_subdev_state_get_format(state, MXC_ISI_PIPE_PAD_SOURCE); 717 718 if (format->code != info->mbus_code || 719 format->width != video->pix.width || 720 format->height != video->pix.height) { 721 dev_dbg(video->pipe->isi->dev, 722 "%s: configuration mismatch, 0x%04x/%ux%u != 0x%04x/%ux%u\n", 723 __func__, format->code, format->width, format->height, 724 info->mbus_code, video->pix.width, video->pix.height); 725 ret = -EINVAL; 726 } 727 728 v4l2_subdev_unlock_state(state); 729 730 return ret; 731 } 732 733 static void mxc_isi_video_return_buffers(struct mxc_isi_video *video, 734 enum vb2_buffer_state state) 735 { 736 struct mxc_isi_buffer *buf; 737 738 spin_lock_irq(&video->buf_lock); 739 740 while (!list_empty(&video->out_active)) { 741 buf = list_first_entry(&video->out_active, 742 struct mxc_isi_buffer, list); 743 list_del_init(&buf->list); 744 if (buf->discard) 745 continue; 746 747 vb2_buffer_done(&buf->v4l2_buf.vb2_buf, state); 748 } 749 750 while (!list_empty(&video->out_pending)) { 751 buf = list_first_entry(&video->out_pending, 752 struct mxc_isi_buffer, list); 753 list_del_init(&buf->list); 754 vb2_buffer_done(&buf->v4l2_buf.vb2_buf, state); 755 } 756 757 while (!list_empty(&video->out_discard)) { 758 buf = list_first_entry(&video->out_discard, 759 struct mxc_isi_buffer, list); 760 list_del_init(&buf->list); 761 } 762 763 INIT_LIST_HEAD(&video->out_active); 764 INIT_LIST_HEAD(&video->out_pending); 765 INIT_LIST_HEAD(&video->out_discard); 766 767 spin_unlock_irq(&video->buf_lock); 768 } 769 770 static void mxc_isi_video_queue_first_buffers(struct mxc_isi_video *video) 771 { 772 unsigned int discard; 773 unsigned int i; 774 775 lockdep_assert_held(&video->buf_lock); 776 777 /* 778 * Queue two ISI channel output buffers. We are not guaranteed to have 779 * any buffer in the pending list when this function is called from the 780 * system resume handler. Use pending buffers as much as possible, and 781 * use discard buffers to fill the remaining slots. 782 */ 783 784 /* How many discard buffers do we need to queue first ? */ 785 discard = list_empty(&video->out_pending) ? 2 786 : list_is_singular(&video->out_pending) ? 1 787 : 0; 788 789 for (i = 0; i < 2; ++i) { 790 enum mxc_isi_buf_id buf_id = i == 0 ? MXC_ISI_BUF1 791 : MXC_ISI_BUF2; 792 struct mxc_isi_buffer *buf; 793 struct list_head *list; 794 795 list = i < discard ? &video->out_discard : &video->out_pending; 796 buf = list_first_entry(list, struct mxc_isi_buffer, list); 797 798 mxc_isi_channel_set_outbuf(video->pipe, buf->dma_addrs, buf_id); 799 buf->id = buf_id; 800 list_move_tail(&buf->list, &video->out_active); 801 } 802 } 803 804 static inline struct mxc_isi_buffer *to_isi_buffer(struct vb2_v4l2_buffer *v4l2_buf) 805 { 806 return container_of(v4l2_buf, struct mxc_isi_buffer, v4l2_buf); 807 } 808 809 int mxc_isi_video_queue_setup(const struct v4l2_pix_format_mplane *format, 810 const struct mxc_isi_format_info *info, 811 unsigned int *num_buffers, 812 unsigned int *num_planes, unsigned int sizes[]) 813 { 814 unsigned int i; 815 816 if (*num_planes) { 817 if (*num_planes != info->mem_planes) 818 return -EINVAL; 819 820 for (i = 0; i < info->mem_planes; ++i) { 821 if (sizes[i] < format->plane_fmt[i].sizeimage) 822 return -EINVAL; 823 } 824 825 return 0; 826 } 827 828 *num_planes = info->mem_planes; 829 830 for (i = 0; i < info->mem_planes; ++i) 831 sizes[i] = format->plane_fmt[i].sizeimage; 832 833 return 0; 834 } 835 836 void mxc_isi_video_buffer_init(struct vb2_buffer *vb2, dma_addr_t dma_addrs[3], 837 const struct mxc_isi_format_info *info, 838 const struct v4l2_pix_format_mplane *pix) 839 { 840 unsigned int i; 841 842 for (i = 0; i < info->mem_planes; ++i) 843 dma_addrs[i] = vb2_dma_contig_plane_dma_addr(vb2, i); 844 845 /* 846 * For single-planar pixel formats with multiple color planes, split 847 * the buffer into color planes. 848 */ 849 if (info->color_planes != info->mem_planes) { 850 unsigned int size = pix->plane_fmt[0].bytesperline * pix->height; 851 852 for (i = 1; i < info->color_planes; ++i) { 853 unsigned int vsub = i > 1 ? info->vsub : 1; 854 855 dma_addrs[i] = dma_addrs[i - 1] + size / vsub; 856 } 857 } 858 } 859 860 int mxc_isi_video_buffer_prepare(struct mxc_isi_dev *isi, struct vb2_buffer *vb2, 861 const struct mxc_isi_format_info *info, 862 const struct v4l2_pix_format_mplane *pix) 863 { 864 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb2); 865 unsigned int i; 866 867 for (i = 0; i < info->mem_planes; i++) { 868 unsigned long size = pix->plane_fmt[i].sizeimage; 869 870 if (vb2_plane_size(vb2, i) < size) { 871 dev_err(isi->dev, "User buffer too small (%ld < %ld)\n", 872 vb2_plane_size(vb2, i), size); 873 return -EINVAL; 874 } 875 876 vb2_set_plane_payload(vb2, i, size); 877 } 878 879 v4l2_buf->field = pix->field; 880 881 return 0; 882 } 883 884 static int mxc_isi_vb2_queue_setup(struct vb2_queue *q, 885 unsigned int *num_buffers, 886 unsigned int *num_planes, 887 unsigned int sizes[], 888 struct device *alloc_devs[]) 889 { 890 struct mxc_isi_video *video = vb2_get_drv_priv(q); 891 892 return mxc_isi_video_queue_setup(&video->pix, video->fmtinfo, 893 num_buffers, num_planes, sizes); 894 } 895 896 static int mxc_isi_vb2_buffer_init(struct vb2_buffer *vb2) 897 { 898 struct mxc_isi_buffer *buf = to_isi_buffer(to_vb2_v4l2_buffer(vb2)); 899 struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue); 900 901 mxc_isi_video_buffer_init(vb2, buf->dma_addrs, video->fmtinfo, 902 &video->pix); 903 904 return 0; 905 } 906 907 static int mxc_isi_vb2_buffer_prepare(struct vb2_buffer *vb2) 908 { 909 struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue); 910 911 return mxc_isi_video_buffer_prepare(video->pipe->isi, vb2, 912 video->fmtinfo, &video->pix); 913 } 914 915 static void mxc_isi_vb2_buffer_queue(struct vb2_buffer *vb2) 916 { 917 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb2); 918 struct mxc_isi_buffer *buf = to_isi_buffer(v4l2_buf); 919 struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue); 920 921 spin_lock_irq(&video->buf_lock); 922 list_add_tail(&buf->list, &video->out_pending); 923 spin_unlock_irq(&video->buf_lock); 924 } 925 926 static void mxc_isi_video_init_channel(struct mxc_isi_video *video) 927 { 928 struct mxc_isi_pipe *pipe = video->pipe; 929 930 mxc_isi_channel_get(pipe); 931 932 mutex_lock(video->ctrls.handler.lock); 933 mxc_isi_channel_set_alpha(pipe, video->ctrls.alpha); 934 mxc_isi_channel_set_flip(pipe, video->ctrls.hflip, video->ctrls.vflip); 935 mutex_unlock(video->ctrls.handler.lock); 936 937 mxc_isi_channel_set_output_format(pipe, video->fmtinfo, &video->pix); 938 } 939 940 static int mxc_isi_vb2_prepare_streaming(struct vb2_queue *q) 941 { 942 struct mxc_isi_video *video = vb2_get_drv_priv(q); 943 struct media_device *mdev = &video->pipe->isi->media_dev; 944 struct media_pipeline *pipe; 945 int ret; 946 947 /* Get a pipeline for the video node and start it. */ 948 scoped_guard(mutex, &mdev->graph_mutex) { 949 ret = mxc_isi_pipe_acquire(video->pipe, 950 &mxc_isi_video_frame_write_done); 951 if (ret) 952 return ret; 953 954 pipe = media_entity_pipeline(&video->vdev.entity) 955 ? : &video->pipe->pipe; 956 957 ret = __video_device_pipeline_start(&video->vdev, pipe); 958 if (ret) 959 goto err_release; 960 } 961 962 /* Verify that the video format matches the output of the subdev. */ 963 ret = mxc_isi_video_validate_format(video); 964 if (ret) 965 goto err_stop; 966 967 /* Allocate buffers for discard operation. */ 968 ret = mxc_isi_video_alloc_discard_buffers(video); 969 if (ret) 970 goto err_stop; 971 972 return 0; 973 974 err_stop: 975 video_device_pipeline_stop(&video->vdev); 976 err_release: 977 mxc_isi_pipe_release(video->pipe); 978 return ret; 979 } 980 981 static int mxc_isi_vb2_start_streaming(struct vb2_queue *q, unsigned int count) 982 { 983 struct mxc_isi_video *video = vb2_get_drv_priv(q); 984 unsigned int i; 985 int ret; 986 987 /* Initialize the ISI channel. */ 988 mxc_isi_video_init_channel(video); 989 990 spin_lock_irq(&video->buf_lock); 991 992 /* Add the discard buffers to the out_discard list. */ 993 for (i = 0; i < ARRAY_SIZE(video->buf_discard); ++i) { 994 struct mxc_isi_buffer *buf = &video->buf_discard[i]; 995 996 list_add_tail(&buf->list, &video->out_discard); 997 } 998 999 /* Queue the first buffers. */ 1000 mxc_isi_video_queue_first_buffers(video); 1001 1002 /* Clear frame count */ 1003 video->frame_count = 0; 1004 1005 spin_unlock_irq(&video->buf_lock); 1006 1007 ret = mxc_isi_pipe_enable(video->pipe); 1008 if (ret) 1009 goto error; 1010 1011 return 0; 1012 1013 error: 1014 mxc_isi_channel_put(video->pipe); 1015 mxc_isi_video_return_buffers(video, VB2_BUF_STATE_QUEUED); 1016 return ret; 1017 } 1018 1019 static void mxc_isi_vb2_stop_streaming(struct vb2_queue *q) 1020 { 1021 struct mxc_isi_video *video = vb2_get_drv_priv(q); 1022 1023 mxc_isi_pipe_disable(video->pipe); 1024 mxc_isi_channel_put(video->pipe); 1025 1026 mxc_isi_video_return_buffers(video, VB2_BUF_STATE_ERROR); 1027 } 1028 1029 static void mxc_isi_vb2_unprepare_streaming(struct vb2_queue *q) 1030 { 1031 struct mxc_isi_video *video = vb2_get_drv_priv(q); 1032 1033 mxc_isi_video_free_discard_buffers(video); 1034 video_device_pipeline_stop(&video->vdev); 1035 mxc_isi_pipe_release(video->pipe); 1036 } 1037 1038 static const struct vb2_ops mxc_isi_vb2_qops = { 1039 .queue_setup = mxc_isi_vb2_queue_setup, 1040 .buf_init = mxc_isi_vb2_buffer_init, 1041 .buf_prepare = mxc_isi_vb2_buffer_prepare, 1042 .buf_queue = mxc_isi_vb2_buffer_queue, 1043 .prepare_streaming = mxc_isi_vb2_prepare_streaming, 1044 .start_streaming = mxc_isi_vb2_start_streaming, 1045 .stop_streaming = mxc_isi_vb2_stop_streaming, 1046 .unprepare_streaming = mxc_isi_vb2_unprepare_streaming, 1047 }; 1048 1049 /* ----------------------------------------------------------------------------- 1050 * V4L2 controls 1051 */ 1052 1053 static inline struct mxc_isi_video *ctrl_to_isi_video(struct v4l2_ctrl *ctrl) 1054 { 1055 return container_of(ctrl->handler, struct mxc_isi_video, ctrls.handler); 1056 } 1057 1058 static int mxc_isi_video_s_ctrl(struct v4l2_ctrl *ctrl) 1059 { 1060 struct mxc_isi_video *video = ctrl_to_isi_video(ctrl); 1061 1062 switch (ctrl->id) { 1063 case V4L2_CID_ALPHA_COMPONENT: 1064 video->ctrls.alpha = ctrl->val; 1065 break; 1066 case V4L2_CID_VFLIP: 1067 video->ctrls.vflip = ctrl->val; 1068 break; 1069 case V4L2_CID_HFLIP: 1070 video->ctrls.hflip = ctrl->val; 1071 break; 1072 } 1073 1074 return 0; 1075 } 1076 1077 static const struct v4l2_ctrl_ops mxc_isi_video_ctrl_ops = { 1078 .s_ctrl = mxc_isi_video_s_ctrl, 1079 }; 1080 1081 static int mxc_isi_video_ctrls_create(struct mxc_isi_video *video) 1082 { 1083 struct v4l2_ctrl_handler *handler = &video->ctrls.handler; 1084 int ret; 1085 1086 v4l2_ctrl_handler_init(handler, 3); 1087 1088 v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops, 1089 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0); 1090 1091 v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops, 1092 V4L2_CID_VFLIP, 0, 1, 1, 0); 1093 1094 v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops, 1095 V4L2_CID_HFLIP, 0, 1, 1, 0); 1096 1097 if (handler->error) { 1098 ret = handler->error; 1099 v4l2_ctrl_handler_free(handler); 1100 return ret; 1101 } 1102 1103 video->vdev.ctrl_handler = handler; 1104 1105 return 0; 1106 } 1107 1108 static void mxc_isi_video_ctrls_delete(struct mxc_isi_video *video) 1109 { 1110 v4l2_ctrl_handler_free(&video->ctrls.handler); 1111 } 1112 1113 /* ----------------------------------------------------------------------------- 1114 * V4L2 ioctls 1115 */ 1116 1117 static int mxc_isi_video_querycap(struct file *file, void *priv, 1118 struct v4l2_capability *cap) 1119 { 1120 strscpy(cap->driver, MXC_ISI_DRIVER_NAME, sizeof(cap->driver)); 1121 strscpy(cap->card, MXC_ISI_CAPTURE, sizeof(cap->card)); 1122 1123 return 0; 1124 } 1125 1126 static int mxc_isi_video_enum_fmt(struct file *file, void *priv, 1127 struct v4l2_fmtdesc *f) 1128 { 1129 const struct mxc_isi_format_info *fmt; 1130 unsigned int index = f->index; 1131 unsigned int i; 1132 1133 if (f->mbus_code) { 1134 /* 1135 * If a media bus code is specified, only enumerate formats 1136 * compatible with it. 1137 */ 1138 for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) { 1139 fmt = &mxc_isi_formats[i]; 1140 if (fmt->mbus_code != f->mbus_code) 1141 continue; 1142 1143 if (index == 0) 1144 break; 1145 1146 index--; 1147 } 1148 1149 if (i == ARRAY_SIZE(mxc_isi_formats)) 1150 return -EINVAL; 1151 } else { 1152 /* Otherwise, enumerate all formatS. */ 1153 if (f->index >= ARRAY_SIZE(mxc_isi_formats)) 1154 return -EINVAL; 1155 1156 fmt = &mxc_isi_formats[f->index]; 1157 } 1158 1159 f->pixelformat = fmt->fourcc; 1160 f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE | V4L2_FMT_FLAG_CSC_YCBCR_ENC 1161 | V4L2_FMT_FLAG_CSC_QUANTIZATION | V4L2_FMT_FLAG_CSC_XFER_FUNC; 1162 1163 return 0; 1164 } 1165 1166 static int mxc_isi_video_g_fmt(struct file *file, void *fh, 1167 struct v4l2_format *f) 1168 { 1169 struct mxc_isi_video *video = video_drvdata(file); 1170 1171 f->fmt.pix_mp = video->pix; 1172 1173 return 0; 1174 } 1175 1176 static int mxc_isi_video_try_fmt(struct file *file, void *fh, 1177 struct v4l2_format *f) 1178 { 1179 struct mxc_isi_video *video = video_drvdata(file); 1180 1181 mxc_isi_format_try(video->pipe, &f->fmt.pix_mp, MXC_ISI_VIDEO_CAP); 1182 return 0; 1183 } 1184 1185 static int mxc_isi_video_s_fmt(struct file *file, void *priv, 1186 struct v4l2_format *f) 1187 { 1188 struct mxc_isi_video *video = video_drvdata(file); 1189 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; 1190 1191 if (vb2_is_busy(&video->vb2_q)) 1192 return -EBUSY; 1193 1194 video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP); 1195 video->pix = *pix; 1196 1197 return 0; 1198 } 1199 1200 static int mxc_isi_video_enum_framesizes(struct file *file, void *priv, 1201 struct v4l2_frmsizeenum *fsize) 1202 { 1203 struct mxc_isi_video *video = video_drvdata(file); 1204 const struct mxc_isi_format_info *info; 1205 unsigned int max_width; 1206 unsigned int h_align; 1207 unsigned int v_align; 1208 1209 if (fsize->index) 1210 return -EINVAL; 1211 1212 info = mxc_isi_format_by_fourcc(fsize->pixel_format, MXC_ISI_VIDEO_CAP); 1213 if (!info) 1214 return -EINVAL; 1215 1216 h_align = max_t(unsigned int, info->hsub, 1); 1217 v_align = max_t(unsigned int, info->vsub, 1); 1218 1219 max_width = video->pipe->id == video->pipe->isi->pdata->num_channels - 1 1220 ? MXC_ISI_MAX_WIDTH_UNCHAINED 1221 : MXC_ISI_MAX_WIDTH_CHAINED; 1222 1223 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; 1224 fsize->stepwise.min_width = ALIGN(MXC_ISI_MIN_WIDTH, h_align); 1225 fsize->stepwise.min_height = ALIGN(MXC_ISI_MIN_HEIGHT, v_align); 1226 fsize->stepwise.max_width = ALIGN_DOWN(max_width, h_align); 1227 fsize->stepwise.max_height = ALIGN_DOWN(MXC_ISI_MAX_HEIGHT, v_align); 1228 fsize->stepwise.step_width = h_align; 1229 fsize->stepwise.step_height = v_align; 1230 1231 /* 1232 * The width can be further restricted due to line buffer sharing 1233 * between pipelines when scaling, but we have no way to know here if 1234 * the scaler will be used. 1235 */ 1236 1237 return 0; 1238 } 1239 1240 static const struct v4l2_ioctl_ops mxc_isi_video_ioctl_ops = { 1241 .vidioc_querycap = mxc_isi_video_querycap, 1242 1243 .vidioc_enum_fmt_vid_cap = mxc_isi_video_enum_fmt, 1244 .vidioc_try_fmt_vid_cap_mplane = mxc_isi_video_try_fmt, 1245 .vidioc_s_fmt_vid_cap_mplane = mxc_isi_video_s_fmt, 1246 .vidioc_g_fmt_vid_cap_mplane = mxc_isi_video_g_fmt, 1247 1248 .vidioc_reqbufs = vb2_ioctl_reqbufs, 1249 .vidioc_querybuf = vb2_ioctl_querybuf, 1250 .vidioc_qbuf = vb2_ioctl_qbuf, 1251 .vidioc_dqbuf = vb2_ioctl_dqbuf, 1252 .vidioc_expbuf = vb2_ioctl_expbuf, 1253 .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 1254 .vidioc_create_bufs = vb2_ioctl_create_bufs, 1255 .vidioc_streamon = vb2_ioctl_streamon, 1256 .vidioc_streamoff = vb2_ioctl_streamoff, 1257 1258 .vidioc_enum_framesizes = mxc_isi_video_enum_framesizes, 1259 1260 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 1261 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 1262 }; 1263 1264 /* ----------------------------------------------------------------------------- 1265 * Video device file operations 1266 */ 1267 1268 static int mxc_isi_video_open(struct file *file) 1269 { 1270 struct mxc_isi_video *video = video_drvdata(file); 1271 int ret; 1272 1273 ret = v4l2_fh_open(file); 1274 if (ret) 1275 return ret; 1276 1277 ret = pm_runtime_resume_and_get(video->pipe->isi->dev); 1278 if (ret) { 1279 v4l2_fh_release(file); 1280 return ret; 1281 } 1282 1283 return 0; 1284 } 1285 1286 static int mxc_isi_video_release(struct file *file) 1287 { 1288 struct mxc_isi_video *video = video_drvdata(file); 1289 int ret; 1290 1291 ret = vb2_fop_release(file); 1292 if (ret) 1293 dev_err(video->pipe->isi->dev, "%s fail\n", __func__); 1294 1295 pm_runtime_put(video->pipe->isi->dev); 1296 return ret; 1297 } 1298 1299 static const struct v4l2_file_operations mxc_isi_video_fops = { 1300 .owner = THIS_MODULE, 1301 .open = mxc_isi_video_open, 1302 .release = mxc_isi_video_release, 1303 .poll = vb2_fop_poll, 1304 .unlocked_ioctl = video_ioctl2, 1305 .mmap = vb2_fop_mmap, 1306 }; 1307 1308 /* ----------------------------------------------------------------------------- 1309 * Suspend & resume 1310 */ 1311 1312 void mxc_isi_video_suspend(struct mxc_isi_pipe *pipe) 1313 { 1314 struct mxc_isi_video *video = &pipe->video; 1315 1316 if (!vb2_is_streaming(&video->vb2_q)) 1317 return; 1318 1319 mxc_isi_pipe_disable(pipe); 1320 mxc_isi_channel_put(pipe); 1321 1322 spin_lock_irq(&video->buf_lock); 1323 1324 /* 1325 * Move the active buffers back to the pending or discard list. We must 1326 * iterate the active list backward and move the buffers to the head of 1327 * the pending list to preserve the buffer queueing order. 1328 */ 1329 while (!list_empty(&video->out_active)) { 1330 struct mxc_isi_buffer *buf = 1331 list_last_entry(&video->out_active, 1332 struct mxc_isi_buffer, list); 1333 1334 if (buf->discard) 1335 list_move(&buf->list, &video->out_discard); 1336 else 1337 list_move(&buf->list, &video->out_pending); 1338 } 1339 1340 spin_unlock_irq(&video->buf_lock); 1341 } 1342 1343 int mxc_isi_video_resume(struct mxc_isi_pipe *pipe) 1344 { 1345 struct mxc_isi_video *video = &pipe->video; 1346 1347 if (!vb2_is_streaming(&video->vb2_q)) 1348 return 0; 1349 1350 mxc_isi_video_init_channel(video); 1351 1352 spin_lock_irq(&video->buf_lock); 1353 mxc_isi_video_queue_first_buffers(video); 1354 spin_unlock_irq(&video->buf_lock); 1355 1356 return mxc_isi_pipe_enable(pipe); 1357 } 1358 1359 /* ----------------------------------------------------------------------------- 1360 * Registration 1361 */ 1362 1363 int mxc_isi_video_register(struct mxc_isi_pipe *pipe, 1364 struct v4l2_device *v4l2_dev) 1365 { 1366 struct mxc_isi_video *video = &pipe->video; 1367 struct v4l2_pix_format_mplane *pix = &video->pix; 1368 struct video_device *vdev = &video->vdev; 1369 struct vb2_queue *q = &video->vb2_q; 1370 int ret = -ENOMEM; 1371 1372 video->pipe = pipe; 1373 1374 mutex_init(&video->lock); 1375 spin_lock_init(&video->buf_lock); 1376 1377 pix->width = MXC_ISI_DEF_WIDTH; 1378 pix->height = MXC_ISI_DEF_HEIGHT; 1379 pix->pixelformat = MXC_ISI_DEF_PIXEL_FORMAT; 1380 pix->colorspace = MXC_ISI_DEF_COLOR_SPACE; 1381 pix->ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC; 1382 pix->quantization = MXC_ISI_DEF_QUANTIZATION; 1383 pix->xfer_func = MXC_ISI_DEF_XFER_FUNC; 1384 video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP); 1385 1386 memset(vdev, 0, sizeof(*vdev)); 1387 snprintf(vdev->name, sizeof(vdev->name), "mxc_isi.%d.capture", pipe->id); 1388 1389 vdev->fops = &mxc_isi_video_fops; 1390 vdev->ioctl_ops = &mxc_isi_video_ioctl_ops; 1391 vdev->v4l2_dev = v4l2_dev; 1392 vdev->minor = -1; 1393 vdev->release = video_device_release_empty; 1394 vdev->queue = q; 1395 vdev->lock = &video->lock; 1396 1397 vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE 1398 | V4L2_CAP_IO_MC; 1399 video_set_drvdata(vdev, video); 1400 1401 INIT_LIST_HEAD(&video->out_pending); 1402 INIT_LIST_HEAD(&video->out_active); 1403 INIT_LIST_HEAD(&video->out_discard); 1404 1405 memset(q, 0, sizeof(*q)); 1406 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1407 q->io_modes = VB2_MMAP | VB2_DMABUF; 1408 q->drv_priv = video; 1409 q->ops = &mxc_isi_vb2_qops; 1410 q->mem_ops = &vb2_dma_contig_memops; 1411 q->buf_struct_size = sizeof(struct mxc_isi_buffer); 1412 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 1413 q->min_queued_buffers = 2; 1414 q->lock = &video->lock; 1415 q->dev = pipe->isi->dev; 1416 1417 ret = vb2_queue_init(q); 1418 if (ret) 1419 goto err_free_ctx; 1420 1421 video->pad.flags = MEDIA_PAD_FL_SINK; 1422 vdev->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER; 1423 ret = media_entity_pads_init(&vdev->entity, 1, &video->pad); 1424 if (ret) 1425 goto err_free_ctx; 1426 1427 ret = mxc_isi_video_ctrls_create(video); 1428 if (ret) 1429 goto err_me_cleanup; 1430 1431 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 1432 if (ret) 1433 goto err_ctrl_free; 1434 1435 ret = media_create_pad_link(&pipe->sd.entity, 1436 MXC_ISI_PIPE_PAD_SOURCE, 1437 &vdev->entity, 0, 1438 MEDIA_LNK_FL_IMMUTABLE | 1439 MEDIA_LNK_FL_ENABLED); 1440 if (ret) 1441 goto err_video_unreg; 1442 1443 return 0; 1444 1445 err_video_unreg: 1446 video_unregister_device(vdev); 1447 err_ctrl_free: 1448 mxc_isi_video_ctrls_delete(video); 1449 err_me_cleanup: 1450 media_entity_cleanup(&vdev->entity); 1451 err_free_ctx: 1452 return ret; 1453 } 1454 1455 void mxc_isi_video_unregister(struct mxc_isi_pipe *pipe) 1456 { 1457 struct mxc_isi_video *video = &pipe->video; 1458 struct video_device *vdev = &video->vdev; 1459 1460 mutex_lock(&video->lock); 1461 1462 if (video_is_registered(vdev)) { 1463 video_unregister_device(vdev); 1464 mxc_isi_video_ctrls_delete(video); 1465 media_entity_cleanup(&vdev->entity); 1466 } 1467 1468 mutex_unlock(&video->lock); 1469 } 1470