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 unsigned int i; 865 866 for (i = 0; i < info->mem_planes; i++) { 867 unsigned long size = pix->plane_fmt[i].sizeimage; 868 869 if (vb2_plane_size(vb2, i) < size) { 870 dev_err(isi->dev, "User buffer too small (%ld < %ld)\n", 871 vb2_plane_size(vb2, i), size); 872 return -EINVAL; 873 } 874 875 vb2_set_plane_payload(vb2, i, size); 876 } 877 878 return 0; 879 } 880 881 static int mxc_isi_vb2_queue_setup(struct vb2_queue *q, 882 unsigned int *num_buffers, 883 unsigned int *num_planes, 884 unsigned int sizes[], 885 struct device *alloc_devs[]) 886 { 887 struct mxc_isi_video *video = vb2_get_drv_priv(q); 888 889 return mxc_isi_video_queue_setup(&video->pix, video->fmtinfo, 890 num_buffers, num_planes, sizes); 891 } 892 893 static int mxc_isi_vb2_buffer_init(struct vb2_buffer *vb2) 894 { 895 struct mxc_isi_buffer *buf = to_isi_buffer(to_vb2_v4l2_buffer(vb2)); 896 struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue); 897 898 mxc_isi_video_buffer_init(vb2, buf->dma_addrs, video->fmtinfo, 899 &video->pix); 900 901 return 0; 902 } 903 904 static int mxc_isi_vb2_buffer_prepare(struct vb2_buffer *vb2) 905 { 906 struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue); 907 908 return mxc_isi_video_buffer_prepare(video->pipe->isi, vb2, 909 video->fmtinfo, &video->pix); 910 } 911 912 static void mxc_isi_vb2_buffer_queue(struct vb2_buffer *vb2) 913 { 914 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb2); 915 struct mxc_isi_buffer *buf = to_isi_buffer(v4l2_buf); 916 struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue); 917 918 spin_lock_irq(&video->buf_lock); 919 list_add_tail(&buf->list, &video->out_pending); 920 spin_unlock_irq(&video->buf_lock); 921 } 922 923 static void mxc_isi_video_init_channel(struct mxc_isi_video *video) 924 { 925 struct mxc_isi_pipe *pipe = video->pipe; 926 927 mxc_isi_channel_get(pipe); 928 929 mutex_lock(video->ctrls.handler.lock); 930 mxc_isi_channel_set_alpha(pipe, video->ctrls.alpha); 931 mxc_isi_channel_set_flip(pipe, video->ctrls.hflip, video->ctrls.vflip); 932 mutex_unlock(video->ctrls.handler.lock); 933 934 mxc_isi_channel_set_output_format(pipe, video->fmtinfo, &video->pix); 935 } 936 937 static int mxc_isi_vb2_start_streaming(struct vb2_queue *q, unsigned int count) 938 { 939 struct mxc_isi_video *video = vb2_get_drv_priv(q); 940 unsigned int i; 941 int ret; 942 943 /* Initialize the ISI channel. */ 944 mxc_isi_video_init_channel(video); 945 946 spin_lock_irq(&video->buf_lock); 947 948 /* Add the discard buffers to the out_discard list. */ 949 for (i = 0; i < ARRAY_SIZE(video->buf_discard); ++i) { 950 struct mxc_isi_buffer *buf = &video->buf_discard[i]; 951 952 list_add_tail(&buf->list, &video->out_discard); 953 } 954 955 /* Queue the first buffers. */ 956 mxc_isi_video_queue_first_buffers(video); 957 958 /* Clear frame count */ 959 video->frame_count = 0; 960 961 spin_unlock_irq(&video->buf_lock); 962 963 ret = mxc_isi_pipe_enable(video->pipe); 964 if (ret) 965 goto error; 966 967 return 0; 968 969 error: 970 mxc_isi_channel_put(video->pipe); 971 mxc_isi_video_return_buffers(video, VB2_BUF_STATE_QUEUED); 972 return ret; 973 } 974 975 static void mxc_isi_vb2_stop_streaming(struct vb2_queue *q) 976 { 977 struct mxc_isi_video *video = vb2_get_drv_priv(q); 978 979 mxc_isi_pipe_disable(video->pipe); 980 mxc_isi_channel_put(video->pipe); 981 982 mxc_isi_video_return_buffers(video, VB2_BUF_STATE_ERROR); 983 } 984 985 static const struct vb2_ops mxc_isi_vb2_qops = { 986 .queue_setup = mxc_isi_vb2_queue_setup, 987 .buf_init = mxc_isi_vb2_buffer_init, 988 .buf_prepare = mxc_isi_vb2_buffer_prepare, 989 .buf_queue = mxc_isi_vb2_buffer_queue, 990 .start_streaming = mxc_isi_vb2_start_streaming, 991 .stop_streaming = mxc_isi_vb2_stop_streaming, 992 }; 993 994 /* ----------------------------------------------------------------------------- 995 * V4L2 controls 996 */ 997 998 static inline struct mxc_isi_video *ctrl_to_isi_video(struct v4l2_ctrl *ctrl) 999 { 1000 return container_of(ctrl->handler, struct mxc_isi_video, ctrls.handler); 1001 } 1002 1003 static int mxc_isi_video_s_ctrl(struct v4l2_ctrl *ctrl) 1004 { 1005 struct mxc_isi_video *video = ctrl_to_isi_video(ctrl); 1006 1007 switch (ctrl->id) { 1008 case V4L2_CID_ALPHA_COMPONENT: 1009 video->ctrls.alpha = ctrl->val; 1010 break; 1011 case V4L2_CID_VFLIP: 1012 video->ctrls.vflip = ctrl->val; 1013 break; 1014 case V4L2_CID_HFLIP: 1015 video->ctrls.hflip = ctrl->val; 1016 break; 1017 } 1018 1019 return 0; 1020 } 1021 1022 static const struct v4l2_ctrl_ops mxc_isi_video_ctrl_ops = { 1023 .s_ctrl = mxc_isi_video_s_ctrl, 1024 }; 1025 1026 static int mxc_isi_video_ctrls_create(struct mxc_isi_video *video) 1027 { 1028 struct v4l2_ctrl_handler *handler = &video->ctrls.handler; 1029 int ret; 1030 1031 v4l2_ctrl_handler_init(handler, 3); 1032 1033 v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops, 1034 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0); 1035 1036 v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops, 1037 V4L2_CID_VFLIP, 0, 1, 1, 0); 1038 1039 v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops, 1040 V4L2_CID_HFLIP, 0, 1, 1, 0); 1041 1042 if (handler->error) { 1043 ret = handler->error; 1044 v4l2_ctrl_handler_free(handler); 1045 return ret; 1046 } 1047 1048 video->vdev.ctrl_handler = handler; 1049 1050 return 0; 1051 } 1052 1053 static void mxc_isi_video_ctrls_delete(struct mxc_isi_video *video) 1054 { 1055 v4l2_ctrl_handler_free(&video->ctrls.handler); 1056 } 1057 1058 /* ----------------------------------------------------------------------------- 1059 * V4L2 ioctls 1060 */ 1061 1062 static int mxc_isi_video_querycap(struct file *file, void *priv, 1063 struct v4l2_capability *cap) 1064 { 1065 strscpy(cap->driver, MXC_ISI_DRIVER_NAME, sizeof(cap->driver)); 1066 strscpy(cap->card, MXC_ISI_CAPTURE, sizeof(cap->card)); 1067 1068 return 0; 1069 } 1070 1071 static int mxc_isi_video_enum_fmt(struct file *file, void *priv, 1072 struct v4l2_fmtdesc *f) 1073 { 1074 const struct mxc_isi_format_info *fmt; 1075 unsigned int index = f->index; 1076 unsigned int i; 1077 1078 if (f->mbus_code) { 1079 /* 1080 * If a media bus code is specified, only enumerate formats 1081 * compatible with it. 1082 */ 1083 for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) { 1084 fmt = &mxc_isi_formats[i]; 1085 if (fmt->mbus_code != f->mbus_code) 1086 continue; 1087 1088 if (index == 0) 1089 break; 1090 1091 index--; 1092 } 1093 1094 if (i == ARRAY_SIZE(mxc_isi_formats)) 1095 return -EINVAL; 1096 } else { 1097 /* Otherwise, enumerate all formatS. */ 1098 if (f->index >= ARRAY_SIZE(mxc_isi_formats)) 1099 return -EINVAL; 1100 1101 fmt = &mxc_isi_formats[f->index]; 1102 } 1103 1104 f->pixelformat = fmt->fourcc; 1105 f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE | V4L2_FMT_FLAG_CSC_YCBCR_ENC 1106 | V4L2_FMT_FLAG_CSC_QUANTIZATION | V4L2_FMT_FLAG_CSC_XFER_FUNC; 1107 1108 return 0; 1109 } 1110 1111 static int mxc_isi_video_g_fmt(struct file *file, void *fh, 1112 struct v4l2_format *f) 1113 { 1114 struct mxc_isi_video *video = video_drvdata(file); 1115 1116 f->fmt.pix_mp = video->pix; 1117 1118 return 0; 1119 } 1120 1121 static int mxc_isi_video_try_fmt(struct file *file, void *fh, 1122 struct v4l2_format *f) 1123 { 1124 struct mxc_isi_video *video = video_drvdata(file); 1125 1126 mxc_isi_format_try(video->pipe, &f->fmt.pix_mp, MXC_ISI_VIDEO_CAP); 1127 return 0; 1128 } 1129 1130 static int mxc_isi_video_s_fmt(struct file *file, void *priv, 1131 struct v4l2_format *f) 1132 { 1133 struct mxc_isi_video *video = video_drvdata(file); 1134 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; 1135 1136 if (vb2_is_busy(&video->vb2_q)) 1137 return -EBUSY; 1138 1139 video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP); 1140 video->pix = *pix; 1141 1142 return 0; 1143 } 1144 1145 static int mxc_isi_video_streamon(struct file *file, void *priv, 1146 enum v4l2_buf_type type) 1147 { 1148 struct mxc_isi_video *video = video_drvdata(file); 1149 struct media_device *mdev = &video->pipe->isi->media_dev; 1150 struct media_pipeline *pipe; 1151 int ret; 1152 1153 if (vb2_queue_is_busy(&video->vb2_q, file)) 1154 return -EBUSY; 1155 1156 /* 1157 * Get a pipeline for the video node and start it. This must be done 1158 * here and not in the queue .start_streaming() handler, so that 1159 * pipeline start errors can be reported from VIDIOC_STREAMON and not 1160 * delayed until subsequent VIDIOC_QBUF calls. 1161 */ 1162 mutex_lock(&mdev->graph_mutex); 1163 1164 ret = mxc_isi_pipe_acquire(video->pipe, &mxc_isi_video_frame_write_done); 1165 if (ret) { 1166 mutex_unlock(&mdev->graph_mutex); 1167 return ret; 1168 } 1169 1170 pipe = media_entity_pipeline(&video->vdev.entity) ? : &video->pipe->pipe; 1171 1172 ret = __video_device_pipeline_start(&video->vdev, pipe); 1173 if (ret) { 1174 mutex_unlock(&mdev->graph_mutex); 1175 goto err_release; 1176 } 1177 1178 mutex_unlock(&mdev->graph_mutex); 1179 1180 /* Verify that the video format matches the output of the subdev. */ 1181 ret = mxc_isi_video_validate_format(video); 1182 if (ret) 1183 goto err_stop; 1184 1185 /* Allocate buffers for discard operation. */ 1186 ret = mxc_isi_video_alloc_discard_buffers(video); 1187 if (ret) 1188 goto err_stop; 1189 1190 ret = vb2_streamon(&video->vb2_q, type); 1191 if (ret) 1192 goto err_free; 1193 1194 video->is_streaming = true; 1195 1196 return 0; 1197 1198 err_free: 1199 mxc_isi_video_free_discard_buffers(video); 1200 err_stop: 1201 video_device_pipeline_stop(&video->vdev); 1202 err_release: 1203 mxc_isi_pipe_release(video->pipe); 1204 return ret; 1205 } 1206 1207 static void mxc_isi_video_cleanup_streaming(struct mxc_isi_video *video) 1208 { 1209 lockdep_assert_held(&video->lock); 1210 1211 if (!video->is_streaming) 1212 return; 1213 1214 mxc_isi_video_free_discard_buffers(video); 1215 video_device_pipeline_stop(&video->vdev); 1216 mxc_isi_pipe_release(video->pipe); 1217 1218 video->is_streaming = false; 1219 } 1220 1221 static int mxc_isi_video_streamoff(struct file *file, void *priv, 1222 enum v4l2_buf_type type) 1223 { 1224 struct mxc_isi_video *video = video_drvdata(file); 1225 int ret; 1226 1227 ret = vb2_ioctl_streamoff(file, priv, type); 1228 if (ret) 1229 return ret; 1230 1231 mxc_isi_video_cleanup_streaming(video); 1232 1233 return 0; 1234 } 1235 1236 static int mxc_isi_video_enum_framesizes(struct file *file, void *priv, 1237 struct v4l2_frmsizeenum *fsize) 1238 { 1239 struct mxc_isi_video *video = video_drvdata(file); 1240 const struct mxc_isi_format_info *info; 1241 unsigned int max_width; 1242 unsigned int h_align; 1243 unsigned int v_align; 1244 1245 if (fsize->index) 1246 return -EINVAL; 1247 1248 info = mxc_isi_format_by_fourcc(fsize->pixel_format, MXC_ISI_VIDEO_CAP); 1249 if (!info) 1250 return -EINVAL; 1251 1252 h_align = max_t(unsigned int, info->hsub, 1); 1253 v_align = max_t(unsigned int, info->vsub, 1); 1254 1255 max_width = video->pipe->id == video->pipe->isi->pdata->num_channels - 1 1256 ? MXC_ISI_MAX_WIDTH_UNCHAINED 1257 : MXC_ISI_MAX_WIDTH_CHAINED; 1258 1259 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; 1260 fsize->stepwise.min_width = ALIGN(MXC_ISI_MIN_WIDTH, h_align); 1261 fsize->stepwise.min_height = ALIGN(MXC_ISI_MIN_HEIGHT, v_align); 1262 fsize->stepwise.max_width = ALIGN_DOWN(max_width, h_align); 1263 fsize->stepwise.max_height = ALIGN_DOWN(MXC_ISI_MAX_HEIGHT, v_align); 1264 fsize->stepwise.step_width = h_align; 1265 fsize->stepwise.step_height = v_align; 1266 1267 /* 1268 * The width can be further restricted due to line buffer sharing 1269 * between pipelines when scaling, but we have no way to know here if 1270 * the scaler will be used. 1271 */ 1272 1273 return 0; 1274 } 1275 1276 static const struct v4l2_ioctl_ops mxc_isi_video_ioctl_ops = { 1277 .vidioc_querycap = mxc_isi_video_querycap, 1278 1279 .vidioc_enum_fmt_vid_cap = mxc_isi_video_enum_fmt, 1280 .vidioc_try_fmt_vid_cap_mplane = mxc_isi_video_try_fmt, 1281 .vidioc_s_fmt_vid_cap_mplane = mxc_isi_video_s_fmt, 1282 .vidioc_g_fmt_vid_cap_mplane = mxc_isi_video_g_fmt, 1283 1284 .vidioc_reqbufs = vb2_ioctl_reqbufs, 1285 .vidioc_querybuf = vb2_ioctl_querybuf, 1286 .vidioc_qbuf = vb2_ioctl_qbuf, 1287 .vidioc_dqbuf = vb2_ioctl_dqbuf, 1288 .vidioc_expbuf = vb2_ioctl_expbuf, 1289 .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 1290 .vidioc_create_bufs = vb2_ioctl_create_bufs, 1291 1292 .vidioc_streamon = mxc_isi_video_streamon, 1293 .vidioc_streamoff = mxc_isi_video_streamoff, 1294 1295 .vidioc_enum_framesizes = mxc_isi_video_enum_framesizes, 1296 1297 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 1298 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 1299 }; 1300 1301 /* ----------------------------------------------------------------------------- 1302 * Video device file operations 1303 */ 1304 1305 static int mxc_isi_video_open(struct file *file) 1306 { 1307 struct mxc_isi_video *video = video_drvdata(file); 1308 int ret; 1309 1310 ret = v4l2_fh_open(file); 1311 if (ret) 1312 return ret; 1313 1314 ret = pm_runtime_resume_and_get(video->pipe->isi->dev); 1315 if (ret) { 1316 v4l2_fh_release(file); 1317 return ret; 1318 } 1319 1320 return 0; 1321 } 1322 1323 static int mxc_isi_video_release(struct file *file) 1324 { 1325 struct mxc_isi_video *video = video_drvdata(file); 1326 int ret; 1327 1328 ret = vb2_fop_release(file); 1329 if (ret) 1330 dev_err(video->pipe->isi->dev, "%s fail\n", __func__); 1331 1332 mutex_lock(&video->lock); 1333 mxc_isi_video_cleanup_streaming(video); 1334 mutex_unlock(&video->lock); 1335 1336 pm_runtime_put(video->pipe->isi->dev); 1337 return ret; 1338 } 1339 1340 static const struct v4l2_file_operations mxc_isi_video_fops = { 1341 .owner = THIS_MODULE, 1342 .open = mxc_isi_video_open, 1343 .release = mxc_isi_video_release, 1344 .poll = vb2_fop_poll, 1345 .unlocked_ioctl = video_ioctl2, 1346 .mmap = vb2_fop_mmap, 1347 }; 1348 1349 /* ----------------------------------------------------------------------------- 1350 * Suspend & resume 1351 */ 1352 1353 void mxc_isi_video_suspend(struct mxc_isi_pipe *pipe) 1354 { 1355 struct mxc_isi_video *video = &pipe->video; 1356 1357 if (!video->is_streaming) 1358 return; 1359 1360 mxc_isi_pipe_disable(pipe); 1361 mxc_isi_channel_put(pipe); 1362 1363 spin_lock_irq(&video->buf_lock); 1364 1365 /* 1366 * Move the active buffers back to the pending or discard list. We must 1367 * iterate the active list backward and move the buffers to the head of 1368 * the pending list to preserve the buffer queueing order. 1369 */ 1370 while (!list_empty(&video->out_active)) { 1371 struct mxc_isi_buffer *buf = 1372 list_last_entry(&video->out_active, 1373 struct mxc_isi_buffer, list); 1374 1375 if (buf->discard) 1376 list_move(&buf->list, &video->out_discard); 1377 else 1378 list_move(&buf->list, &video->out_pending); 1379 } 1380 1381 spin_unlock_irq(&video->buf_lock); 1382 } 1383 1384 int mxc_isi_video_resume(struct mxc_isi_pipe *pipe) 1385 { 1386 struct mxc_isi_video *video = &pipe->video; 1387 1388 if (!video->is_streaming) 1389 return 0; 1390 1391 mxc_isi_video_init_channel(video); 1392 1393 spin_lock_irq(&video->buf_lock); 1394 mxc_isi_video_queue_first_buffers(video); 1395 spin_unlock_irq(&video->buf_lock); 1396 1397 return mxc_isi_pipe_enable(pipe); 1398 } 1399 1400 /* ----------------------------------------------------------------------------- 1401 * Registration 1402 */ 1403 1404 int mxc_isi_video_register(struct mxc_isi_pipe *pipe, 1405 struct v4l2_device *v4l2_dev) 1406 { 1407 struct mxc_isi_video *video = &pipe->video; 1408 struct v4l2_pix_format_mplane *pix = &video->pix; 1409 struct video_device *vdev = &video->vdev; 1410 struct vb2_queue *q = &video->vb2_q; 1411 int ret = -ENOMEM; 1412 1413 video->pipe = pipe; 1414 1415 mutex_init(&video->lock); 1416 spin_lock_init(&video->buf_lock); 1417 1418 pix->width = MXC_ISI_DEF_WIDTH; 1419 pix->height = MXC_ISI_DEF_HEIGHT; 1420 pix->pixelformat = MXC_ISI_DEF_PIXEL_FORMAT; 1421 pix->colorspace = MXC_ISI_DEF_COLOR_SPACE; 1422 pix->ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC; 1423 pix->quantization = MXC_ISI_DEF_QUANTIZATION; 1424 pix->xfer_func = MXC_ISI_DEF_XFER_FUNC; 1425 video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP); 1426 1427 memset(vdev, 0, sizeof(*vdev)); 1428 snprintf(vdev->name, sizeof(vdev->name), "mxc_isi.%d.capture", pipe->id); 1429 1430 vdev->fops = &mxc_isi_video_fops; 1431 vdev->ioctl_ops = &mxc_isi_video_ioctl_ops; 1432 vdev->v4l2_dev = v4l2_dev; 1433 vdev->minor = -1; 1434 vdev->release = video_device_release_empty; 1435 vdev->queue = q; 1436 vdev->lock = &video->lock; 1437 1438 vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE 1439 | V4L2_CAP_IO_MC; 1440 video_set_drvdata(vdev, video); 1441 1442 INIT_LIST_HEAD(&video->out_pending); 1443 INIT_LIST_HEAD(&video->out_active); 1444 INIT_LIST_HEAD(&video->out_discard); 1445 1446 memset(q, 0, sizeof(*q)); 1447 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1448 q->io_modes = VB2_MMAP | VB2_DMABUF; 1449 q->drv_priv = video; 1450 q->ops = &mxc_isi_vb2_qops; 1451 q->mem_ops = &vb2_dma_contig_memops; 1452 q->buf_struct_size = sizeof(struct mxc_isi_buffer); 1453 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 1454 q->min_queued_buffers = 2; 1455 q->lock = &video->lock; 1456 q->dev = pipe->isi->dev; 1457 1458 ret = vb2_queue_init(q); 1459 if (ret) 1460 goto err_free_ctx; 1461 1462 video->pad.flags = MEDIA_PAD_FL_SINK; 1463 vdev->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER; 1464 ret = media_entity_pads_init(&vdev->entity, 1, &video->pad); 1465 if (ret) 1466 goto err_free_ctx; 1467 1468 ret = mxc_isi_video_ctrls_create(video); 1469 if (ret) 1470 goto err_me_cleanup; 1471 1472 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 1473 if (ret) 1474 goto err_ctrl_free; 1475 1476 ret = media_create_pad_link(&pipe->sd.entity, 1477 MXC_ISI_PIPE_PAD_SOURCE, 1478 &vdev->entity, 0, 1479 MEDIA_LNK_FL_IMMUTABLE | 1480 MEDIA_LNK_FL_ENABLED); 1481 if (ret) 1482 goto err_video_unreg; 1483 1484 return 0; 1485 1486 err_video_unreg: 1487 video_unregister_device(vdev); 1488 err_ctrl_free: 1489 mxc_isi_video_ctrls_delete(video); 1490 err_me_cleanup: 1491 media_entity_cleanup(&vdev->entity); 1492 err_free_ctx: 1493 return ret; 1494 } 1495 1496 void mxc_isi_video_unregister(struct mxc_isi_pipe *pipe) 1497 { 1498 struct mxc_isi_video *video = &pipe->video; 1499 struct video_device *vdev = &video->vdev; 1500 1501 mutex_lock(&video->lock); 1502 1503 if (video_is_registered(vdev)) { 1504 video_unregister_device(vdev); 1505 mxc_isi_video_ctrls_delete(video); 1506 media_entity_cleanup(&vdev->entity); 1507 } 1508 1509 mutex_unlock(&video->lock); 1510 } 1511