1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * ISI V4L2 memory to memory 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 or memory to memory or DC 7 * 8 * Copyright (c) 2019 NXP Semiconductor 9 */ 10 11 #include <linux/container_of.h> 12 #include <linux/device.h> 13 #include <linux/errno.h> 14 #include <linux/kernel.h> 15 #include <linux/limits.h> 16 #include <linux/minmax.h> 17 #include <linux/mutex.h> 18 #include <linux/pm_runtime.h> 19 #include <linux/slab.h> 20 #include <linux/spinlock.h> 21 #include <linux/string.h> 22 #include <linux/types.h> 23 #include <linux/videodev2.h> 24 25 #include <media/media-entity.h> 26 #include <media/v4l2-ctrls.h> 27 #include <media/v4l2-device.h> 28 #include <media/v4l2-event.h> 29 #include <media/v4l2-fh.h> 30 #include <media/v4l2-ioctl.h> 31 #include <media/v4l2-mem2mem.h> 32 #include <media/videobuf2-core.h> 33 #include <media/videobuf2-dma-contig.h> 34 35 #include "imx8-isi-core.h" 36 37 struct mxc_isi_m2m_buffer { 38 struct v4l2_m2m_buffer buf; 39 dma_addr_t dma_addrs[3]; 40 }; 41 42 struct mxc_isi_m2m_ctx_queue_data { 43 struct v4l2_pix_format_mplane format; 44 const struct mxc_isi_format_info *info; 45 u32 sequence; 46 bool streaming; 47 }; 48 49 struct mxc_isi_m2m_ctx { 50 struct v4l2_fh fh; 51 struct mxc_isi_m2m *m2m; 52 53 /* Protects the m2m vb2 queues */ 54 struct mutex vb2_lock; 55 56 struct { 57 struct mxc_isi_m2m_ctx_queue_data out; 58 struct mxc_isi_m2m_ctx_queue_data cap; 59 } queues; 60 61 struct { 62 struct v4l2_ctrl_handler handler; 63 unsigned int alpha; 64 bool hflip; 65 bool vflip; 66 } ctrls; 67 68 bool chained; 69 }; 70 71 static inline struct mxc_isi_m2m_buffer * 72 to_isi_m2m_buffer(struct vb2_v4l2_buffer *buf) 73 { 74 return container_of(buf, struct mxc_isi_m2m_buffer, buf.vb); 75 } 76 77 static inline struct mxc_isi_m2m_ctx *to_isi_m2m_ctx(struct v4l2_fh *fh) 78 { 79 return container_of(fh, struct mxc_isi_m2m_ctx, fh); 80 } 81 82 static inline struct mxc_isi_m2m_ctx_queue_data * 83 mxc_isi_m2m_ctx_qdata(struct mxc_isi_m2m_ctx *ctx, enum v4l2_buf_type type) 84 { 85 if (V4L2_TYPE_IS_OUTPUT(type)) 86 return &ctx->queues.out; 87 else 88 return &ctx->queues.cap; 89 } 90 91 /* ----------------------------------------------------------------------------- 92 * V4L2 M2M device operations 93 */ 94 95 static void mxc_isi_m2m_frame_write_done(struct mxc_isi_pipe *pipe, u32 status) 96 { 97 struct mxc_isi_m2m *m2m = &pipe->isi->m2m; 98 struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf; 99 struct mxc_isi_m2m_ctx *ctx; 100 101 ctx = v4l2_m2m_get_curr_priv(m2m->m2m_dev); 102 if (!ctx) { 103 dev_err(m2m->isi->dev, 104 "Instance released before the end of transaction\n"); 105 return; 106 } 107 108 src_vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 109 dst_vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 110 111 v4l2_m2m_buf_copy_metadata(src_vbuf, dst_vbuf, false); 112 113 src_vbuf->sequence = ctx->queues.out.sequence++; 114 dst_vbuf->sequence = ctx->queues.cap.sequence++; 115 116 v4l2_m2m_buf_done(src_vbuf, VB2_BUF_STATE_DONE); 117 v4l2_m2m_buf_done(dst_vbuf, VB2_BUF_STATE_DONE); 118 119 v4l2_m2m_job_finish(m2m->m2m_dev, ctx->fh.m2m_ctx); 120 } 121 122 static void mxc_isi_m2m_device_run(void *priv) 123 { 124 struct mxc_isi_m2m_ctx *ctx = priv; 125 struct mxc_isi_m2m *m2m = ctx->m2m; 126 struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf; 127 struct mxc_isi_m2m_buffer *src_buf, *dst_buf; 128 129 mxc_isi_channel_disable(m2m->pipe); 130 131 mutex_lock(&m2m->lock); 132 133 /* If the context has changed, reconfigure the channel. */ 134 if (m2m->last_ctx != ctx) { 135 const struct v4l2_area in_size = { 136 .width = ctx->queues.out.format.width, 137 .height = ctx->queues.out.format.height, 138 }; 139 const struct v4l2_area scale = { 140 .width = ctx->queues.cap.format.width, 141 .height = ctx->queues.cap.format.height, 142 }; 143 const struct v4l2_rect crop = { 144 .width = ctx->queues.cap.format.width, 145 .height = ctx->queues.cap.format.height, 146 }; 147 148 mxc_isi_channel_config(m2m->pipe, MXC_ISI_INPUT_MEM, 149 &in_size, &scale, &crop, 150 ctx->queues.out.info->encoding, 151 ctx->queues.cap.info->encoding); 152 mxc_isi_channel_set_input_format(m2m->pipe, 153 ctx->queues.out.info, 154 &ctx->queues.out.format); 155 mxc_isi_channel_set_output_format(m2m->pipe, 156 ctx->queues.cap.info, 157 &ctx->queues.cap.format); 158 159 m2m->last_ctx = ctx; 160 } 161 162 mutex_unlock(&m2m->lock); 163 164 mutex_lock(ctx->ctrls.handler.lock); 165 mxc_isi_channel_set_alpha(m2m->pipe, ctx->ctrls.alpha); 166 mxc_isi_channel_set_flip(m2m->pipe, ctx->ctrls.hflip, ctx->ctrls.vflip); 167 mutex_unlock(ctx->ctrls.handler.lock); 168 169 src_vbuf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); 170 dst_vbuf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); 171 172 src_buf = to_isi_m2m_buffer(src_vbuf); 173 dst_buf = to_isi_m2m_buffer(dst_vbuf); 174 175 mxc_isi_channel_set_inbuf(m2m->pipe, src_buf->dma_addrs[0]); 176 mxc_isi_channel_set_outbuf(m2m->pipe, dst_buf->dma_addrs, MXC_ISI_BUF1); 177 mxc_isi_channel_set_outbuf(m2m->pipe, dst_buf->dma_addrs, MXC_ISI_BUF2); 178 179 mxc_isi_channel_enable(m2m->pipe); 180 181 mxc_isi_channel_m2m_start(m2m->pipe); 182 } 183 184 static const struct v4l2_m2m_ops mxc_isi_m2m_ops = { 185 .device_run = mxc_isi_m2m_device_run, 186 }; 187 188 /* ----------------------------------------------------------------------------- 189 * videobuf2 queue operations 190 */ 191 192 static int mxc_isi_m2m_vb2_queue_setup(struct vb2_queue *q, 193 unsigned int *num_buffers, 194 unsigned int *num_planes, 195 unsigned int sizes[], 196 struct device *alloc_devs[]) 197 { 198 struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q); 199 const struct mxc_isi_m2m_ctx_queue_data *qdata = 200 mxc_isi_m2m_ctx_qdata(ctx, q->type); 201 202 return mxc_isi_video_queue_setup(&qdata->format, qdata->info, 203 num_buffers, num_planes, sizes); 204 } 205 206 static int mxc_isi_m2m_vb2_buffer_init(struct vb2_buffer *vb2) 207 { 208 struct vb2_queue *vq = vb2->vb2_queue; 209 struct mxc_isi_m2m_buffer *buf = to_isi_m2m_buffer(to_vb2_v4l2_buffer(vb2)); 210 struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(vb2->vb2_queue); 211 const struct mxc_isi_m2m_ctx_queue_data *qdata = 212 mxc_isi_m2m_ctx_qdata(ctx, vq->type); 213 214 mxc_isi_video_buffer_init(vb2, buf->dma_addrs, qdata->info, 215 &qdata->format); 216 217 return 0; 218 } 219 220 static int mxc_isi_m2m_vb2_buffer_prepare(struct vb2_buffer *vb2) 221 { 222 struct vb2_queue *vq = vb2->vb2_queue; 223 struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(vq); 224 const struct mxc_isi_m2m_ctx_queue_data *qdata = 225 mxc_isi_m2m_ctx_qdata(ctx, vq->type); 226 227 return mxc_isi_video_buffer_prepare(ctx->m2m->isi, vb2, qdata->info, 228 &qdata->format); 229 } 230 231 static void mxc_isi_m2m_vb2_buffer_queue(struct vb2_buffer *vb2) 232 { 233 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2); 234 struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(vb2->vb2_queue); 235 236 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); 237 } 238 239 static int mxc_isi_m2m_vb2_start_streaming(struct vb2_queue *q, 240 unsigned int count) 241 { 242 struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q); 243 struct mxc_isi_m2m_ctx_queue_data *qdata = 244 mxc_isi_m2m_ctx_qdata(ctx, q->type); 245 246 qdata->sequence = 0; 247 248 return 0; 249 } 250 251 static void mxc_isi_m2m_vb2_stop_streaming(struct vb2_queue *q) 252 { 253 struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q); 254 struct vb2_v4l2_buffer *vbuf; 255 256 for (;;) { 257 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 258 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 259 else 260 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 261 if (!vbuf) 262 break; 263 264 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); 265 } 266 } 267 268 static const struct vb2_ops mxc_isi_m2m_vb2_qops = { 269 .queue_setup = mxc_isi_m2m_vb2_queue_setup, 270 .buf_init = mxc_isi_m2m_vb2_buffer_init, 271 .buf_prepare = mxc_isi_m2m_vb2_buffer_prepare, 272 .buf_queue = mxc_isi_m2m_vb2_buffer_queue, 273 .start_streaming = mxc_isi_m2m_vb2_start_streaming, 274 .stop_streaming = mxc_isi_m2m_vb2_stop_streaming, 275 }; 276 277 static int mxc_isi_m2m_queue_init(void *priv, struct vb2_queue *src_vq, 278 struct vb2_queue *dst_vq) 279 { 280 struct mxc_isi_m2m_ctx *ctx = priv; 281 struct mxc_isi_m2m *m2m = ctx->m2m; 282 int ret; 283 284 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 285 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 286 src_vq->drv_priv = ctx; 287 src_vq->buf_struct_size = sizeof(struct mxc_isi_m2m_buffer); 288 src_vq->ops = &mxc_isi_m2m_vb2_qops; 289 src_vq->mem_ops = &vb2_dma_contig_memops; 290 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 291 src_vq->lock = &ctx->vb2_lock; 292 src_vq->dev = m2m->isi->dev; 293 294 ret = vb2_queue_init(src_vq); 295 if (ret) 296 return ret; 297 298 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 299 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 300 dst_vq->drv_priv = ctx; 301 dst_vq->buf_struct_size = sizeof(struct mxc_isi_m2m_buffer); 302 dst_vq->ops = &mxc_isi_m2m_vb2_qops; 303 dst_vq->mem_ops = &vb2_dma_contig_memops; 304 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 305 dst_vq->lock = &ctx->vb2_lock; 306 dst_vq->dev = m2m->isi->dev; 307 308 return vb2_queue_init(dst_vq); 309 } 310 311 /* ----------------------------------------------------------------------------- 312 * V4L2 controls 313 */ 314 315 static inline struct mxc_isi_m2m_ctx * 316 ctrl_to_mxc_isi_m2m_ctx(struct v4l2_ctrl *ctrl) 317 { 318 return container_of(ctrl->handler, struct mxc_isi_m2m_ctx, ctrls.handler); 319 } 320 321 static int mxc_isi_m2m_ctx_s_ctrl(struct v4l2_ctrl *ctrl) 322 { 323 struct mxc_isi_m2m_ctx *ctx = ctrl_to_mxc_isi_m2m_ctx(ctrl); 324 325 switch (ctrl->id) { 326 case V4L2_CID_HFLIP: 327 ctx->ctrls.hflip = ctrl->val; 328 break; 329 330 case V4L2_CID_VFLIP: 331 ctx->ctrls.vflip = ctrl->val; 332 break; 333 334 case V4L2_CID_ALPHA_COMPONENT: 335 ctx->ctrls.alpha = ctrl->val; 336 break; 337 } 338 339 return 0; 340 } 341 342 static const struct v4l2_ctrl_ops mxc_isi_m2m_ctx_ctrl_ops = { 343 .s_ctrl = mxc_isi_m2m_ctx_s_ctrl, 344 }; 345 346 static int mxc_isi_m2m_ctx_ctrls_create(struct mxc_isi_m2m_ctx *ctx) 347 { 348 struct v4l2_ctrl_handler *handler = &ctx->ctrls.handler; 349 int ret; 350 351 v4l2_ctrl_handler_init(handler, 3); 352 353 v4l2_ctrl_new_std(handler, &mxc_isi_m2m_ctx_ctrl_ops, 354 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0); 355 v4l2_ctrl_new_std(handler, &mxc_isi_m2m_ctx_ctrl_ops, 356 V4L2_CID_HFLIP, 0, 1, 1, 0); 357 v4l2_ctrl_new_std(handler, &mxc_isi_m2m_ctx_ctrl_ops, 358 V4L2_CID_VFLIP, 0, 1, 1, 0); 359 360 if (handler->error) { 361 ret = handler->error; 362 v4l2_ctrl_handler_free(handler); 363 return ret; 364 } 365 366 ctx->fh.ctrl_handler = handler; 367 368 return 0; 369 } 370 371 static void mxc_isi_m2m_ctx_ctrls_delete(struct mxc_isi_m2m_ctx *ctx) 372 { 373 v4l2_ctrl_handler_free(&ctx->ctrls.handler); 374 } 375 376 /* ----------------------------------------------------------------------------- 377 * V4L2 ioctls 378 */ 379 380 static int mxc_isi_m2m_querycap(struct file *file, void *fh, 381 struct v4l2_capability *cap) 382 { 383 strscpy(cap->driver, MXC_ISI_DRIVER_NAME, sizeof(cap->driver)); 384 strscpy(cap->card, MXC_ISI_M2M, sizeof(cap->card)); 385 cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE; 386 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; 387 388 return 0; 389 } 390 391 static int mxc_isi_m2m_enum_fmt_vid(struct file *file, void *fh, 392 struct v4l2_fmtdesc *f) 393 { 394 const enum mxc_isi_video_type type = 395 f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ? 396 MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP; 397 const struct mxc_isi_format_info *info; 398 399 info = mxc_isi_format_enum(f->index, type); 400 if (!info) 401 return -EINVAL; 402 403 f->pixelformat = info->fourcc; 404 f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE | V4L2_FMT_FLAG_CSC_YCBCR_ENC 405 | V4L2_FMT_FLAG_CSC_QUANTIZATION | V4L2_FMT_FLAG_CSC_XFER_FUNC; 406 407 return 0; 408 } 409 410 static const struct mxc_isi_format_info * 411 __mxc_isi_m2m_try_fmt_vid(struct mxc_isi_m2m_ctx *ctx, 412 struct v4l2_pix_format_mplane *pix, 413 const enum mxc_isi_video_type type) 414 { 415 if (type == MXC_ISI_VIDEO_M2M_CAP) { 416 /* Downscaling only */ 417 pix->width = min(pix->width, ctx->queues.out.format.width); 418 pix->height = min(pix->height, ctx->queues.out.format.height); 419 } 420 421 return mxc_isi_format_try(ctx->m2m->pipe, pix, type); 422 } 423 424 static int mxc_isi_m2m_try_fmt_vid(struct file *file, void *fh, 425 struct v4l2_format *f) 426 { 427 const enum mxc_isi_video_type type = 428 f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ? 429 MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP; 430 struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); 431 432 __mxc_isi_m2m_try_fmt_vid(ctx, &f->fmt.pix_mp, type); 433 434 return 0; 435 } 436 437 static int mxc_isi_m2m_g_fmt_vid(struct file *file, void *fh, 438 struct v4l2_format *f) 439 { 440 struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); 441 const struct mxc_isi_m2m_ctx_queue_data *qdata = 442 mxc_isi_m2m_ctx_qdata(ctx, f->type); 443 444 f->fmt.pix_mp = qdata->format; 445 446 return 0; 447 } 448 449 static int mxc_isi_m2m_s_fmt_vid(struct file *file, void *fh, 450 struct v4l2_format *f) 451 { 452 const enum mxc_isi_video_type type = 453 f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ? 454 MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP; 455 struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); 456 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; 457 const struct mxc_isi_format_info *info; 458 struct vb2_queue *vq; 459 460 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); 461 if (!vq) 462 return -EINVAL; 463 464 if (vb2_is_busy(vq)) 465 return -EBUSY; 466 467 info = __mxc_isi_m2m_try_fmt_vid(ctx, pix, type); 468 469 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 470 ctx->queues.out.format = *pix; 471 ctx->queues.out.info = info; 472 } 473 474 /* 475 * Always set the format on the capture side, due to either format 476 * propagation or direct setting. 477 */ 478 ctx->queues.cap.format = *pix; 479 ctx->queues.cap.info = info; 480 481 return 0; 482 } 483 484 static int mxc_isi_m2m_streamon(struct file *file, void *fh, 485 enum v4l2_buf_type type) 486 { 487 struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); 488 struct mxc_isi_m2m_ctx_queue_data *q = mxc_isi_m2m_ctx_qdata(ctx, type); 489 const struct v4l2_pix_format_mplane *out_pix = &ctx->queues.out.format; 490 const struct v4l2_pix_format_mplane *cap_pix = &ctx->queues.cap.format; 491 const struct mxc_isi_format_info *cap_info = ctx->queues.cap.info; 492 const struct mxc_isi_format_info *out_info = ctx->queues.out.info; 493 struct mxc_isi_m2m *m2m = ctx->m2m; 494 bool bypass; 495 int ret; 496 497 if (q->streaming) 498 return 0; 499 500 mutex_lock(&m2m->lock); 501 502 if (m2m->usage_count == INT_MAX) { 503 ret = -EOVERFLOW; 504 goto unlock; 505 } 506 507 bypass = cap_pix->width == out_pix->width && 508 cap_pix->height == out_pix->height && 509 cap_info->encoding == out_info->encoding; 510 511 /* 512 * Acquire the pipe and initialize the channel with the first user of 513 * the M2M device. 514 */ 515 if (m2m->usage_count == 0) { 516 ret = mxc_isi_channel_acquire(m2m->pipe, 517 &mxc_isi_m2m_frame_write_done, 518 bypass); 519 if (ret) 520 goto unlock; 521 522 mxc_isi_channel_get(m2m->pipe); 523 } 524 525 m2m->usage_count++; 526 527 /* 528 * Allocate resources for the channel, counting how many users require 529 * buffer chaining. 530 */ 531 if (!ctx->chained && out_pix->width > MXC_ISI_MAX_WIDTH_UNCHAINED) { 532 ret = mxc_isi_channel_chain(m2m->pipe, bypass); 533 if (ret) 534 goto deinit; 535 536 m2m->chained_count++; 537 ctx->chained = true; 538 } 539 540 /* 541 * Drop the lock to start the stream, as the .device_run() operation 542 * needs to acquire it. 543 */ 544 mutex_unlock(&m2m->lock); 545 ret = v4l2_m2m_ioctl_streamon(file, fh, type); 546 if (ret) { 547 /* Reacquire the lock for the cleanup path. */ 548 mutex_lock(&m2m->lock); 549 goto unchain; 550 } 551 552 q->streaming = true; 553 554 return 0; 555 556 unchain: 557 if (ctx->chained && --m2m->chained_count == 0) 558 mxc_isi_channel_unchain(m2m->pipe); 559 ctx->chained = false; 560 561 deinit: 562 if (--m2m->usage_count == 0) { 563 mxc_isi_channel_put(m2m->pipe); 564 mxc_isi_channel_release(m2m->pipe); 565 } 566 567 unlock: 568 mutex_unlock(&m2m->lock); 569 return ret; 570 } 571 572 static int mxc_isi_m2m_streamoff(struct file *file, void *fh, 573 enum v4l2_buf_type type) 574 { 575 struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh); 576 struct mxc_isi_m2m_ctx_queue_data *q = mxc_isi_m2m_ctx_qdata(ctx, type); 577 struct mxc_isi_m2m *m2m = ctx->m2m; 578 579 v4l2_m2m_ioctl_streamoff(file, fh, type); 580 581 if (!q->streaming) 582 return 0; 583 584 mutex_lock(&m2m->lock); 585 586 /* 587 * If the last context is this one, reset it to make sure the device 588 * will be reconfigured when streaming is restarted. 589 */ 590 if (m2m->last_ctx == ctx) 591 m2m->last_ctx = NULL; 592 593 /* Free the channel resources if this is the last chained context. */ 594 if (ctx->chained && --m2m->chained_count == 0) 595 mxc_isi_channel_unchain(m2m->pipe); 596 ctx->chained = false; 597 598 /* Turn off the light with the last user. */ 599 if (--m2m->usage_count == 0) { 600 mxc_isi_channel_disable(m2m->pipe); 601 mxc_isi_channel_put(m2m->pipe); 602 mxc_isi_channel_release(m2m->pipe); 603 } 604 605 WARN_ON(m2m->usage_count < 0); 606 607 mutex_unlock(&m2m->lock); 608 609 q->streaming = false; 610 611 return 0; 612 } 613 614 static const struct v4l2_ioctl_ops mxc_isi_m2m_ioctl_ops = { 615 .vidioc_querycap = mxc_isi_m2m_querycap, 616 617 .vidioc_enum_fmt_vid_cap = mxc_isi_m2m_enum_fmt_vid, 618 .vidioc_enum_fmt_vid_out = mxc_isi_m2m_enum_fmt_vid, 619 .vidioc_g_fmt_vid_cap_mplane = mxc_isi_m2m_g_fmt_vid, 620 .vidioc_g_fmt_vid_out_mplane = mxc_isi_m2m_g_fmt_vid, 621 .vidioc_s_fmt_vid_cap_mplane = mxc_isi_m2m_s_fmt_vid, 622 .vidioc_s_fmt_vid_out_mplane = mxc_isi_m2m_s_fmt_vid, 623 .vidioc_try_fmt_vid_cap_mplane = mxc_isi_m2m_try_fmt_vid, 624 .vidioc_try_fmt_vid_out_mplane = mxc_isi_m2m_try_fmt_vid, 625 626 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 627 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 628 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 629 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 630 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 631 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 632 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 633 634 .vidioc_streamon = mxc_isi_m2m_streamon, 635 .vidioc_streamoff = mxc_isi_m2m_streamoff, 636 637 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 638 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 639 }; 640 641 /* ----------------------------------------------------------------------------- 642 * Video device file operations 643 */ 644 645 static void mxc_isi_m2m_init_format(struct mxc_isi_m2m_ctx *ctx, 646 struct mxc_isi_m2m_ctx_queue_data *qdata, 647 enum mxc_isi_video_type type) 648 { 649 qdata->format.width = MXC_ISI_DEF_WIDTH; 650 qdata->format.height = MXC_ISI_DEF_HEIGHT; 651 qdata->format.pixelformat = MXC_ISI_DEF_PIXEL_FORMAT; 652 653 qdata->info = mxc_isi_format_try(ctx->m2m->pipe, &qdata->format, type); 654 } 655 656 static int mxc_isi_m2m_open(struct file *file) 657 { 658 struct video_device *vdev = video_devdata(file); 659 struct mxc_isi_m2m *m2m = video_drvdata(file); 660 struct mxc_isi_m2m_ctx *ctx; 661 int ret; 662 663 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 664 if (!ctx) 665 return -ENOMEM; 666 667 ctx->m2m = m2m; 668 mutex_init(&ctx->vb2_lock); 669 670 v4l2_fh_init(&ctx->fh, vdev); 671 file->private_data = &ctx->fh; 672 673 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(m2m->m2m_dev, ctx, 674 &mxc_isi_m2m_queue_init); 675 if (IS_ERR(ctx->fh.m2m_ctx)) { 676 ret = PTR_ERR(ctx->fh.m2m_ctx); 677 ctx->fh.m2m_ctx = NULL; 678 goto err_fh; 679 } 680 681 mxc_isi_m2m_init_format(ctx, &ctx->queues.out, MXC_ISI_VIDEO_M2M_OUT); 682 mxc_isi_m2m_init_format(ctx, &ctx->queues.cap, MXC_ISI_VIDEO_M2M_CAP); 683 684 ret = mxc_isi_m2m_ctx_ctrls_create(ctx); 685 if (ret) 686 goto err_ctx; 687 688 ret = pm_runtime_resume_and_get(m2m->isi->dev); 689 if (ret) 690 goto err_ctrls; 691 692 v4l2_fh_add(&ctx->fh); 693 694 return 0; 695 696 err_ctrls: 697 mxc_isi_m2m_ctx_ctrls_delete(ctx); 698 err_ctx: 699 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); 700 err_fh: 701 v4l2_fh_exit(&ctx->fh); 702 mutex_destroy(&ctx->vb2_lock); 703 kfree(ctx); 704 return ret; 705 } 706 707 static int mxc_isi_m2m_release(struct file *file) 708 { 709 struct mxc_isi_m2m *m2m = video_drvdata(file); 710 struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(file->private_data); 711 712 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); 713 mxc_isi_m2m_ctx_ctrls_delete(ctx); 714 715 v4l2_fh_del(&ctx->fh); 716 v4l2_fh_exit(&ctx->fh); 717 718 mutex_destroy(&ctx->vb2_lock); 719 kfree(ctx); 720 721 pm_runtime_put(m2m->isi->dev); 722 723 return 0; 724 } 725 726 static const struct v4l2_file_operations mxc_isi_m2m_fops = { 727 .owner = THIS_MODULE, 728 .open = mxc_isi_m2m_open, 729 .release = mxc_isi_m2m_release, 730 .poll = v4l2_m2m_fop_poll, 731 .unlocked_ioctl = video_ioctl2, 732 .mmap = v4l2_m2m_fop_mmap, 733 }; 734 735 /* ----------------------------------------------------------------------------- 736 * Registration 737 */ 738 739 int mxc_isi_m2m_register(struct mxc_isi_dev *isi, struct v4l2_device *v4l2_dev) 740 { 741 struct mxc_isi_m2m *m2m = &isi->m2m; 742 struct video_device *vdev = &m2m->vdev; 743 struct media_link *link; 744 int ret; 745 746 m2m->isi = isi; 747 m2m->pipe = &isi->pipes[0]; 748 749 mutex_init(&m2m->lock); 750 751 /* Initialize the video device and create controls. */ 752 snprintf(vdev->name, sizeof(vdev->name), "mxc_isi.m2m"); 753 754 vdev->fops = &mxc_isi_m2m_fops; 755 vdev->ioctl_ops = &mxc_isi_m2m_ioctl_ops; 756 vdev->v4l2_dev = v4l2_dev; 757 vdev->minor = -1; 758 vdev->release = video_device_release_empty; 759 vdev->vfl_dir = VFL_DIR_M2M; 760 761 vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE; 762 video_set_drvdata(vdev, m2m); 763 764 /* Create the M2M device. */ 765 m2m->m2m_dev = v4l2_m2m_init(&mxc_isi_m2m_ops); 766 if (IS_ERR(m2m->m2m_dev)) { 767 dev_err(isi->dev, "failed to initialize m2m device\n"); 768 ret = PTR_ERR(m2m->m2m_dev); 769 goto err_mutex; 770 } 771 772 /* Register the video device. */ 773 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 774 if (ret < 0) { 775 dev_err(isi->dev, "failed to register m2m device\n"); 776 goto err_m2m; 777 } 778 779 /* 780 * Populate the media graph. We can't use the mem2mem helper 781 * v4l2_m2m_register_media_controller() as the M2M interface needs to 782 * be connected to the existing entities in the graph, so we have to 783 * wire things up manually: 784 * 785 * - The entity in the video_device, which isn't touched by the V4L2 786 * core for M2M devices, is used as the source I/O entity in the 787 * graph, connected to the crossbar switch. 788 * 789 * - The video device at the end of the pipeline provides the sink 790 * entity, and is already wired up in the graph. 791 * 792 * - A new interface is created, pointing at both entities. The sink 793 * entity will thus have two interfaces pointing to it. 794 */ 795 m2m->pad.flags = MEDIA_PAD_FL_SOURCE; 796 vdev->entity.name = "mxc_isi.output"; 797 vdev->entity.function = MEDIA_ENT_F_IO_V4L; 798 ret = media_entity_pads_init(&vdev->entity, 1, &m2m->pad); 799 if (ret) 800 goto err_video; 801 802 ret = media_device_register_entity(v4l2_dev->mdev, &vdev->entity); 803 if (ret) 804 goto err_entity_cleanup; 805 806 ret = media_create_pad_link(&vdev->entity, 0, 807 &m2m->isi->crossbar.sd.entity, 808 m2m->isi->crossbar.num_sinks - 1, 809 MEDIA_LNK_FL_IMMUTABLE | 810 MEDIA_LNK_FL_ENABLED); 811 if (ret) 812 goto err_entity_unreg; 813 814 m2m->intf = media_devnode_create(v4l2_dev->mdev, MEDIA_INTF_T_V4L_VIDEO, 815 0, VIDEO_MAJOR, vdev->minor); 816 if (!m2m->intf) { 817 ret = -ENOMEM; 818 goto err_entity_unreg; 819 } 820 821 link = media_create_intf_link(&vdev->entity, &m2m->intf->intf, 822 MEDIA_LNK_FL_IMMUTABLE | 823 MEDIA_LNK_FL_ENABLED); 824 if (!link) { 825 ret = -ENOMEM; 826 goto err_devnode; 827 } 828 829 link = media_create_intf_link(&m2m->pipe->video.vdev.entity, 830 &m2m->intf->intf, 831 MEDIA_LNK_FL_IMMUTABLE | 832 MEDIA_LNK_FL_ENABLED); 833 if (!link) { 834 ret = -ENOMEM; 835 goto err_devnode; 836 } 837 838 return 0; 839 840 err_devnode: 841 media_devnode_remove(m2m->intf); 842 err_entity_unreg: 843 media_device_unregister_entity(&vdev->entity); 844 err_entity_cleanup: 845 media_entity_cleanup(&vdev->entity); 846 err_video: 847 video_unregister_device(vdev); 848 err_m2m: 849 v4l2_m2m_release(m2m->m2m_dev); 850 err_mutex: 851 mutex_destroy(&m2m->lock); 852 return ret; 853 } 854 855 int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi) 856 { 857 struct mxc_isi_m2m *m2m = &isi->m2m; 858 struct video_device *vdev = &m2m->vdev; 859 860 video_unregister_device(vdev); 861 862 v4l2_m2m_release(m2m->m2m_dev); 863 media_devnode_remove(m2m->intf); 864 media_entity_cleanup(&vdev->entity); 865 mutex_destroy(&m2m->lock); 866 867 return 0; 868 } 869