1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022 MediaTek Inc. 4 * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com> 5 */ 6 7 #include <linux/platform_device.h> 8 #include <media/v4l2-ioctl.h> 9 #include <media/v4l2-event.h> 10 #include <media/videobuf2-dma-contig.h> 11 #include "mtk-mdp3-m2m.h" 12 13 static inline struct mdp_m2m_ctx *fh_to_ctx(struct v4l2_fh *fh) 14 { 15 return container_of(fh, struct mdp_m2m_ctx, fh); 16 } 17 18 static inline struct mdp_m2m_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) 19 { 20 return container_of(ctrl->handler, struct mdp_m2m_ctx, ctrl_handler); 21 } 22 23 static inline struct mdp_frame *ctx_get_frame(struct mdp_m2m_ctx *ctx, 24 enum v4l2_buf_type type) 25 { 26 if (V4L2_TYPE_IS_OUTPUT(type)) 27 return &ctx->curr_param.output; 28 else 29 return &ctx->curr_param.captures[0]; 30 } 31 32 static inline void mdp_m2m_ctx_set_state(struct mdp_m2m_ctx *ctx, u32 state) 33 { 34 atomic_or(state, &ctx->curr_param.state); 35 } 36 37 static inline bool mdp_m2m_ctx_is_state_set(struct mdp_m2m_ctx *ctx, u32 mask) 38 { 39 return ((atomic_read(&ctx->curr_param.state) & mask) == mask); 40 } 41 42 static void mdp_m2m_process_done(void *priv, int vb_state) 43 { 44 struct mdp_m2m_ctx *ctx = priv; 45 struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf; 46 47 src_vbuf = (struct vb2_v4l2_buffer *) 48 v4l2_m2m_src_buf_remove(ctx->m2m_ctx); 49 dst_vbuf = (struct vb2_v4l2_buffer *) 50 v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); 51 ctx->curr_param.frame_no = ctx->frame_count[MDP_M2M_SRC]; 52 src_vbuf->sequence = ctx->frame_count[MDP_M2M_SRC]++; 53 dst_vbuf->sequence = ctx->frame_count[MDP_M2M_DST]++; 54 v4l2_m2m_buf_copy_metadata(src_vbuf, dst_vbuf, true); 55 56 v4l2_m2m_buf_done(src_vbuf, vb_state); 57 v4l2_m2m_buf_done(dst_vbuf, vb_state); 58 v4l2_m2m_job_finish(ctx->mdp_dev->m2m_dev, ctx->m2m_ctx); 59 } 60 61 static void mdp_m2m_device_run(void *priv) 62 { 63 struct mdp_m2m_ctx *ctx = priv; 64 struct mdp_frame *frame; 65 struct vb2_v4l2_buffer *src_vb, *dst_vb; 66 struct img_ipi_frameparam param = {}; 67 struct mdp_cmdq_param task = {}; 68 enum vb2_buffer_state vb_state = VB2_BUF_STATE_ERROR; 69 int ret; 70 71 if (mdp_m2m_ctx_is_state_set(ctx, MDP_M2M_CTX_ERROR)) { 72 dev_err(&ctx->mdp_dev->pdev->dev, 73 "mdp_m2m_ctx is in error state\n"); 74 goto worker_end; 75 } 76 77 param.frame_no = ctx->curr_param.frame_no; 78 param.type = ctx->curr_param.type; 79 param.num_inputs = 1; 80 param.num_outputs = 1; 81 82 frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 83 src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); 84 mdp_set_src_config(¶m.inputs[0], frame, &src_vb->vb2_buf); 85 86 frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 87 dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); 88 mdp_set_dst_config(¶m.outputs[0], frame, &dst_vb->vb2_buf); 89 90 ret = mdp_vpu_process(&ctx->vpu, ¶m); 91 if (ret) { 92 dev_err(&ctx->mdp_dev->pdev->dev, 93 "VPU MDP process failed: %d\n", ret); 94 goto worker_end; 95 } 96 97 task.config = ctx->vpu.config; 98 task.param = ¶m; 99 task.composes[0] = &frame->compose; 100 task.cmdq_cb = NULL; 101 task.cb_data = NULL; 102 task.mdp_ctx = ctx; 103 104 ret = mdp_cmdq_send(ctx->mdp_dev, &task); 105 if (ret) { 106 dev_err(&ctx->mdp_dev->pdev->dev, 107 "CMDQ sendtask failed: %d\n", ret); 108 goto worker_end; 109 } 110 111 return; 112 113 worker_end: 114 mdp_m2m_process_done(ctx, vb_state); 115 } 116 117 static int mdp_m2m_start_streaming(struct vb2_queue *q, unsigned int count) 118 { 119 struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(q); 120 struct mdp_frame *capture; 121 struct vb2_queue *vq; 122 int ret; 123 bool out_streaming, cap_streaming; 124 125 if (V4L2_TYPE_IS_OUTPUT(q->type)) 126 ctx->frame_count[MDP_M2M_SRC] = 0; 127 128 if (V4L2_TYPE_IS_CAPTURE(q->type)) 129 ctx->frame_count[MDP_M2M_DST] = 0; 130 131 capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 132 vq = v4l2_m2m_get_src_vq(ctx->m2m_ctx); 133 out_streaming = vb2_is_streaming(vq); 134 vq = v4l2_m2m_get_dst_vq(ctx->m2m_ctx); 135 cap_streaming = vb2_is_streaming(vq); 136 137 /* Check to see if scaling ratio is within supported range */ 138 if ((V4L2_TYPE_IS_OUTPUT(q->type) && cap_streaming) || 139 (V4L2_TYPE_IS_CAPTURE(q->type) && out_streaming)) { 140 ret = mdp_check_scaling_ratio(&capture->crop.c, 141 &capture->compose, 142 capture->rotation, 143 ctx->curr_param.limit); 144 if (ret) { 145 dev_err(&ctx->mdp_dev->pdev->dev, 146 "Out of scaling range\n"); 147 return ret; 148 } 149 } 150 151 if (!mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT)) { 152 ret = mdp_vpu_get_locked(ctx->mdp_dev); 153 if (ret) 154 return ret; 155 156 ret = mdp_vpu_ctx_init(&ctx->vpu, &ctx->mdp_dev->vpu, 157 MDP_DEV_M2M); 158 if (ret) { 159 dev_err(&ctx->mdp_dev->pdev->dev, 160 "VPU init failed %d\n", ret); 161 return -EINVAL; 162 } 163 mdp_m2m_ctx_set_state(ctx, MDP_VPU_INIT); 164 } 165 166 return 0; 167 } 168 169 static struct vb2_v4l2_buffer *mdp_m2m_buf_remove(struct mdp_m2m_ctx *ctx, 170 unsigned int type) 171 { 172 if (V4L2_TYPE_IS_OUTPUT(type)) 173 return (struct vb2_v4l2_buffer *) 174 v4l2_m2m_src_buf_remove(ctx->m2m_ctx); 175 else 176 return (struct vb2_v4l2_buffer *) 177 v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); 178 } 179 180 static void mdp_m2m_stop_streaming(struct vb2_queue *q) 181 { 182 struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(q); 183 struct vb2_v4l2_buffer *vb; 184 185 vb = mdp_m2m_buf_remove(ctx, q->type); 186 while (vb) { 187 v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR); 188 vb = mdp_m2m_buf_remove(ctx, q->type); 189 } 190 } 191 192 static int mdp_m2m_queue_setup(struct vb2_queue *q, 193 unsigned int *num_buffers, 194 unsigned int *num_planes, unsigned int sizes[], 195 struct device *alloc_devs[]) 196 { 197 struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(q); 198 struct v4l2_pix_format_mplane *pix_mp; 199 u32 i; 200 201 pix_mp = &ctx_get_frame(ctx, q->type)->format.fmt.pix_mp; 202 203 /* from VIDIOC_CREATE_BUFS */ 204 if (*num_planes) { 205 if (*num_planes != pix_mp->num_planes) 206 return -EINVAL; 207 for (i = 0; i < pix_mp->num_planes; ++i) 208 if (sizes[i] < pix_mp->plane_fmt[i].sizeimage) 209 return -EINVAL; 210 } else {/* from VIDIOC_REQBUFS */ 211 *num_planes = pix_mp->num_planes; 212 for (i = 0; i < pix_mp->num_planes; ++i) 213 sizes[i] = pix_mp->plane_fmt[i].sizeimage; 214 } 215 216 return 0; 217 } 218 219 static int mdp_m2m_buf_prepare(struct vb2_buffer *vb) 220 { 221 struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 222 struct v4l2_pix_format_mplane *pix_mp; 223 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); 224 u32 i; 225 226 v4l2_buf->field = V4L2_FIELD_NONE; 227 228 if (V4L2_TYPE_IS_CAPTURE(vb->type)) { 229 pix_mp = &ctx_get_frame(ctx, vb->type)->format.fmt.pix_mp; 230 for (i = 0; i < pix_mp->num_planes; ++i) { 231 vb2_set_plane_payload(vb, i, 232 pix_mp->plane_fmt[i].sizeimage); 233 } 234 } 235 return 0; 236 } 237 238 static int mdp_m2m_buf_out_validate(struct vb2_buffer *vb) 239 { 240 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); 241 242 v4l2_buf->field = V4L2_FIELD_NONE; 243 244 return 0; 245 } 246 247 static void mdp_m2m_buf_queue(struct vb2_buffer *vb) 248 { 249 struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 250 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); 251 252 v4l2_buf->field = V4L2_FIELD_NONE; 253 254 v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb)); 255 } 256 257 static const struct vb2_ops mdp_m2m_qops = { 258 .queue_setup = mdp_m2m_queue_setup, 259 .wait_prepare = vb2_ops_wait_prepare, 260 .wait_finish = vb2_ops_wait_finish, 261 .buf_prepare = mdp_m2m_buf_prepare, 262 .start_streaming = mdp_m2m_start_streaming, 263 .stop_streaming = mdp_m2m_stop_streaming, 264 .buf_queue = mdp_m2m_buf_queue, 265 .buf_out_validate = mdp_m2m_buf_out_validate, 266 }; 267 268 static int mdp_m2m_querycap(struct file *file, void *fh, 269 struct v4l2_capability *cap) 270 { 271 strscpy(cap->driver, MDP_MODULE_NAME, sizeof(cap->driver)); 272 strscpy(cap->card, MDP_DEVICE_NAME, sizeof(cap->card)); 273 274 return 0; 275 } 276 277 static int mdp_m2m_enum_fmt_mplane(struct file *file, void *fh, 278 struct v4l2_fmtdesc *f) 279 { 280 return mdp_enum_fmt_mplane(f); 281 } 282 283 static int mdp_m2m_g_fmt_mplane(struct file *file, void *fh, 284 struct v4l2_format *f) 285 { 286 struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); 287 struct mdp_frame *frame; 288 struct v4l2_pix_format_mplane *pix_mp; 289 290 frame = ctx_get_frame(ctx, f->type); 291 *f = frame->format; 292 pix_mp = &f->fmt.pix_mp; 293 pix_mp->colorspace = ctx->curr_param.colorspace; 294 pix_mp->xfer_func = ctx->curr_param.xfer_func; 295 pix_mp->ycbcr_enc = ctx->curr_param.ycbcr_enc; 296 pix_mp->quantization = ctx->curr_param.quant; 297 298 return 0; 299 } 300 301 static int mdp_m2m_s_fmt_mplane(struct file *file, void *fh, 302 struct v4l2_format *f) 303 { 304 struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); 305 struct mdp_frame *frame = ctx_get_frame(ctx, f->type); 306 struct mdp_frame *capture; 307 const struct mdp_format *fmt; 308 struct vb2_queue *vq; 309 310 fmt = mdp_try_fmt_mplane(f, &ctx->curr_param, ctx->id); 311 if (!fmt) 312 return -EINVAL; 313 314 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); 315 if (vb2_is_busy(vq)) 316 return -EBUSY; 317 318 frame->format = *f; 319 frame->mdp_fmt = fmt; 320 frame->ycbcr_prof = mdp_map_ycbcr_prof_mplane(f, fmt->mdp_color); 321 frame->usage = V4L2_TYPE_IS_OUTPUT(f->type) ? 322 MDP_BUFFER_USAGE_HW_READ : MDP_BUFFER_USAGE_MDP; 323 324 capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 325 if (V4L2_TYPE_IS_OUTPUT(f->type)) { 326 capture->crop.c.left = 0; 327 capture->crop.c.top = 0; 328 capture->crop.c.width = f->fmt.pix_mp.width; 329 capture->crop.c.height = f->fmt.pix_mp.height; 330 ctx->curr_param.colorspace = f->fmt.pix_mp.colorspace; 331 ctx->curr_param.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; 332 ctx->curr_param.quant = f->fmt.pix_mp.quantization; 333 ctx->curr_param.xfer_func = f->fmt.pix_mp.xfer_func; 334 } else { 335 capture->compose.left = 0; 336 capture->compose.top = 0; 337 capture->compose.width = f->fmt.pix_mp.width; 338 capture->compose.height = f->fmt.pix_mp.height; 339 } 340 341 return 0; 342 } 343 344 static int mdp_m2m_try_fmt_mplane(struct file *file, void *fh, 345 struct v4l2_format *f) 346 { 347 struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); 348 349 if (!mdp_try_fmt_mplane(f, &ctx->curr_param, ctx->id)) 350 return -EINVAL; 351 352 return 0; 353 } 354 355 static int mdp_m2m_g_selection(struct file *file, void *fh, 356 struct v4l2_selection *s) 357 { 358 struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); 359 struct mdp_frame *frame; 360 bool valid = false; 361 362 if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 363 valid = mdp_target_is_crop(s->target); 364 else if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 365 valid = mdp_target_is_compose(s->target); 366 367 if (!valid) 368 return -EINVAL; 369 370 switch (s->target) { 371 case V4L2_SEL_TGT_CROP: 372 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 373 return -EINVAL; 374 frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 375 s->r = frame->crop.c; 376 return 0; 377 case V4L2_SEL_TGT_COMPOSE: 378 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 379 return -EINVAL; 380 frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 381 s->r = frame->compose; 382 return 0; 383 case V4L2_SEL_TGT_CROP_DEFAULT: 384 case V4L2_SEL_TGT_CROP_BOUNDS: 385 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 386 return -EINVAL; 387 frame = ctx_get_frame(ctx, s->type); 388 s->r.left = 0; 389 s->r.top = 0; 390 s->r.width = frame->format.fmt.pix_mp.width; 391 s->r.height = frame->format.fmt.pix_mp.height; 392 return 0; 393 case V4L2_SEL_TGT_COMPOSE_DEFAULT: 394 case V4L2_SEL_TGT_COMPOSE_BOUNDS: 395 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 396 return -EINVAL; 397 frame = ctx_get_frame(ctx, s->type); 398 s->r.left = 0; 399 s->r.top = 0; 400 s->r.width = frame->format.fmt.pix_mp.width; 401 s->r.height = frame->format.fmt.pix_mp.height; 402 return 0; 403 } 404 return -EINVAL; 405 } 406 407 static int mdp_m2m_s_selection(struct file *file, void *fh, 408 struct v4l2_selection *s) 409 { 410 struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); 411 struct mdp_frame *frame = ctx_get_frame(ctx, s->type); 412 struct mdp_frame *capture; 413 struct v4l2_rect r; 414 struct device *dev = &ctx->mdp_dev->pdev->dev; 415 bool valid = false; 416 int ret; 417 418 if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 419 valid = (s->target == V4L2_SEL_TGT_CROP); 420 else if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 421 valid = (s->target == V4L2_SEL_TGT_COMPOSE); 422 423 if (!valid) { 424 dev_dbg(dev, "[%s:%d] invalid type:%u target:%u", __func__, 425 ctx->id, s->type, s->target); 426 return -EINVAL; 427 } 428 429 ret = mdp_try_crop(ctx, &r, s, frame); 430 if (ret) 431 return ret; 432 capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 433 434 if (mdp_target_is_crop(s->target)) 435 capture->crop.c = r; 436 else 437 capture->compose = r; 438 439 s->r = r; 440 441 return 0; 442 } 443 444 static const struct v4l2_ioctl_ops mdp_m2m_ioctl_ops = { 445 .vidioc_querycap = mdp_m2m_querycap, 446 .vidioc_enum_fmt_vid_cap = mdp_m2m_enum_fmt_mplane, 447 .vidioc_enum_fmt_vid_out = mdp_m2m_enum_fmt_mplane, 448 .vidioc_g_fmt_vid_cap_mplane = mdp_m2m_g_fmt_mplane, 449 .vidioc_g_fmt_vid_out_mplane = mdp_m2m_g_fmt_mplane, 450 .vidioc_s_fmt_vid_cap_mplane = mdp_m2m_s_fmt_mplane, 451 .vidioc_s_fmt_vid_out_mplane = mdp_m2m_s_fmt_mplane, 452 .vidioc_try_fmt_vid_cap_mplane = mdp_m2m_try_fmt_mplane, 453 .vidioc_try_fmt_vid_out_mplane = mdp_m2m_try_fmt_mplane, 454 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 455 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 456 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 457 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 458 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 459 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 460 .vidioc_streamon = v4l2_m2m_ioctl_streamon, 461 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 462 .vidioc_g_selection = mdp_m2m_g_selection, 463 .vidioc_s_selection = mdp_m2m_s_selection, 464 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 465 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 466 }; 467 468 static int mdp_m2m_queue_init(void *priv, 469 struct vb2_queue *src_vq, 470 struct vb2_queue *dst_vq) 471 { 472 struct mdp_m2m_ctx *ctx = priv; 473 int ret; 474 475 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 476 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 477 src_vq->ops = &mdp_m2m_qops; 478 src_vq->mem_ops = &vb2_dma_contig_memops; 479 src_vq->drv_priv = ctx; 480 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 481 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 482 src_vq->dev = &ctx->mdp_dev->pdev->dev; 483 src_vq->lock = &ctx->ctx_lock; 484 485 ret = vb2_queue_init(src_vq); 486 if (ret) 487 return ret; 488 489 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 490 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 491 dst_vq->ops = &mdp_m2m_qops; 492 dst_vq->mem_ops = &vb2_dma_contig_memops; 493 dst_vq->drv_priv = ctx; 494 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 495 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 496 dst_vq->dev = &ctx->mdp_dev->pdev->dev; 497 dst_vq->lock = &ctx->ctx_lock; 498 499 return vb2_queue_init(dst_vq); 500 } 501 502 static int mdp_m2m_s_ctrl(struct v4l2_ctrl *ctrl) 503 { 504 struct mdp_m2m_ctx *ctx = ctrl_to_ctx(ctrl); 505 struct mdp_frame *capture; 506 507 capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 508 switch (ctrl->id) { 509 case V4L2_CID_HFLIP: 510 capture->hflip = ctrl->val; 511 break; 512 case V4L2_CID_VFLIP: 513 capture->vflip = ctrl->val; 514 break; 515 case V4L2_CID_ROTATE: 516 capture->rotation = ctrl->val; 517 break; 518 } 519 520 return 0; 521 } 522 523 static const struct v4l2_ctrl_ops mdp_m2m_ctrl_ops = { 524 .s_ctrl = mdp_m2m_s_ctrl, 525 }; 526 527 static int mdp_m2m_ctrls_create(struct mdp_m2m_ctx *ctx) 528 { 529 v4l2_ctrl_handler_init(&ctx->ctrl_handler, MDP_MAX_CTRLS); 530 ctx->ctrls.hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, 531 &mdp_m2m_ctrl_ops, V4L2_CID_HFLIP, 532 0, 1, 1, 0); 533 ctx->ctrls.vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, 534 &mdp_m2m_ctrl_ops, V4L2_CID_VFLIP, 535 0, 1, 1, 0); 536 ctx->ctrls.rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, 537 &mdp_m2m_ctrl_ops, 538 V4L2_CID_ROTATE, 0, 270, 90, 0); 539 540 if (ctx->ctrl_handler.error) { 541 int err = ctx->ctrl_handler.error; 542 543 v4l2_ctrl_handler_free(&ctx->ctrl_handler); 544 dev_err(&ctx->mdp_dev->pdev->dev, 545 "Failed to register controls\n"); 546 return err; 547 } 548 return 0; 549 } 550 551 static int mdp_m2m_open(struct file *file) 552 { 553 struct video_device *vdev = video_devdata(file); 554 struct mdp_dev *mdp = video_get_drvdata(vdev); 555 struct mdp_m2m_ctx *ctx; 556 struct device *dev = &mdp->pdev->dev; 557 int ret; 558 struct v4l2_format default_format = {}; 559 560 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 561 if (!ctx) 562 return -ENOMEM; 563 564 if (mutex_lock_interruptible(&mdp->m2m_lock)) { 565 ret = -ERESTARTSYS; 566 goto err_free_ctx; 567 } 568 569 ctx->id = ida_alloc(&mdp->mdp_ida, GFP_KERNEL); 570 ctx->mdp_dev = mdp; 571 572 v4l2_fh_init(&ctx->fh, vdev); 573 file->private_data = &ctx->fh; 574 ret = mdp_m2m_ctrls_create(ctx); 575 if (ret) 576 goto err_exit_fh; 577 578 /* Use separate control handler per file handle */ 579 ctx->fh.ctrl_handler = &ctx->ctrl_handler; 580 v4l2_fh_add(&ctx->fh); 581 582 mutex_init(&ctx->ctx_lock); 583 ctx->m2m_ctx = v4l2_m2m_ctx_init(mdp->m2m_dev, ctx, mdp_m2m_queue_init); 584 if (IS_ERR(ctx->m2m_ctx)) { 585 dev_err(dev, "Failed to initialize m2m context\n"); 586 ret = PTR_ERR(ctx->m2m_ctx); 587 goto err_release_handler; 588 } 589 ctx->fh.m2m_ctx = ctx->m2m_ctx; 590 591 ctx->curr_param.ctx = ctx; 592 ret = mdp_frameparam_init(&ctx->curr_param); 593 if (ret) { 594 dev_err(dev, "Failed to initialize mdp parameter\n"); 595 goto err_release_m2m_ctx; 596 } 597 598 mutex_unlock(&mdp->m2m_lock); 599 600 /* Default format */ 601 default_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 602 default_format.fmt.pix_mp.width = 32; 603 default_format.fmt.pix_mp.height = 32; 604 default_format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M; 605 mdp_m2m_s_fmt_mplane(file, &ctx->fh, &default_format); 606 default_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 607 mdp_m2m_s_fmt_mplane(file, &ctx->fh, &default_format); 608 609 dev_dbg(dev, "%s:[%d]", __func__, ctx->id); 610 611 return 0; 612 613 err_release_m2m_ctx: 614 v4l2_m2m_ctx_release(ctx->m2m_ctx); 615 err_release_handler: 616 v4l2_ctrl_handler_free(&ctx->ctrl_handler); 617 v4l2_fh_del(&ctx->fh); 618 err_exit_fh: 619 v4l2_fh_exit(&ctx->fh); 620 mutex_unlock(&mdp->m2m_lock); 621 err_free_ctx: 622 kfree(ctx); 623 624 return ret; 625 } 626 627 static int mdp_m2m_release(struct file *file) 628 { 629 struct mdp_m2m_ctx *ctx = fh_to_ctx(file->private_data); 630 struct mdp_dev *mdp = video_drvdata(file); 631 struct device *dev = &mdp->pdev->dev; 632 633 mutex_lock(&mdp->m2m_lock); 634 v4l2_m2m_ctx_release(ctx->m2m_ctx); 635 if (mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT)) { 636 mdp_vpu_ctx_deinit(&ctx->vpu); 637 mdp_vpu_put_locked(mdp); 638 } 639 640 v4l2_ctrl_handler_free(&ctx->ctrl_handler); 641 v4l2_fh_del(&ctx->fh); 642 v4l2_fh_exit(&ctx->fh); 643 ida_free(&mdp->mdp_ida, ctx->id); 644 mutex_unlock(&mdp->m2m_lock); 645 646 dev_dbg(dev, "%s:[%d]", __func__, ctx->id); 647 kfree(ctx); 648 649 return 0; 650 } 651 652 static const struct v4l2_file_operations mdp_m2m_fops = { 653 .owner = THIS_MODULE, 654 .poll = v4l2_m2m_fop_poll, 655 .unlocked_ioctl = video_ioctl2, 656 .mmap = v4l2_m2m_fop_mmap, 657 .open = mdp_m2m_open, 658 .release = mdp_m2m_release, 659 }; 660 661 static const struct v4l2_m2m_ops mdp_m2m_ops = { 662 .device_run = mdp_m2m_device_run, 663 }; 664 665 int mdp_m2m_device_register(struct mdp_dev *mdp) 666 { 667 struct device *dev = &mdp->pdev->dev; 668 int ret = 0; 669 670 mdp->m2m_vdev = video_device_alloc(); 671 if (!mdp->m2m_vdev) { 672 dev_err(dev, "Failed to allocate video device\n"); 673 ret = -ENOMEM; 674 goto err_video_alloc; 675 } 676 mdp->m2m_vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | 677 V4L2_CAP_STREAMING; 678 mdp->m2m_vdev->fops = &mdp_m2m_fops; 679 mdp->m2m_vdev->ioctl_ops = &mdp_m2m_ioctl_ops; 680 mdp->m2m_vdev->release = mdp_video_device_release; 681 mdp->m2m_vdev->lock = &mdp->m2m_lock; 682 mdp->m2m_vdev->vfl_dir = VFL_DIR_M2M; 683 mdp->m2m_vdev->v4l2_dev = &mdp->v4l2_dev; 684 snprintf(mdp->m2m_vdev->name, sizeof(mdp->m2m_vdev->name), "%s:m2m", 685 MDP_MODULE_NAME); 686 video_set_drvdata(mdp->m2m_vdev, mdp); 687 688 mdp->m2m_dev = v4l2_m2m_init(&mdp_m2m_ops); 689 if (IS_ERR(mdp->m2m_dev)) { 690 dev_err(dev, "Failed to initialize v4l2-m2m device\n"); 691 ret = PTR_ERR(mdp->m2m_dev); 692 goto err_m2m_init; 693 } 694 695 ret = video_register_device(mdp->m2m_vdev, VFL_TYPE_VIDEO, -1); 696 if (ret) { 697 dev_err(dev, "Failed to register video device\n"); 698 goto err_video_register; 699 } 700 701 v4l2_info(&mdp->v4l2_dev, "Driver registered as /dev/video%d", 702 mdp->m2m_vdev->num); 703 return 0; 704 705 err_video_register: 706 v4l2_m2m_release(mdp->m2m_dev); 707 err_m2m_init: 708 video_device_release(mdp->m2m_vdev); 709 err_video_alloc: 710 711 return ret; 712 } 713 714 void mdp_m2m_device_unregister(struct mdp_dev *mdp) 715 { 716 video_unregister_device(mdp->m2m_vdev); 717 } 718 719 void mdp_m2m_job_finish(struct mdp_m2m_ctx *ctx) 720 { 721 enum vb2_buffer_state vb_state = VB2_BUF_STATE_DONE; 722 723 mdp_m2m_process_done(ctx, vb_state); 724 } 725