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