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