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 .buf_prepare = mdp_m2m_buf_prepare, 270 .start_streaming = mdp_m2m_start_streaming, 271 .stop_streaming = mdp_m2m_stop_streaming, 272 .buf_queue = mdp_m2m_buf_queue, 273 .buf_out_validate = mdp_m2m_buf_out_validate, 274 }; 275 276 static int mdp_m2m_querycap(struct file *file, void *fh, 277 struct v4l2_capability *cap) 278 { 279 strscpy(cap->driver, MDP_MODULE_NAME, sizeof(cap->driver)); 280 strscpy(cap->card, MDP_DEVICE_NAME, sizeof(cap->card)); 281 282 return 0; 283 } 284 285 static int mdp_m2m_enum_fmt_mplane(struct file *file, void *fh, 286 struct v4l2_fmtdesc *f) 287 { 288 struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); 289 290 return mdp_enum_fmt_mplane(ctx->mdp_dev, f); 291 } 292 293 static int mdp_m2m_g_fmt_mplane(struct file *file, void *fh, 294 struct v4l2_format *f) 295 { 296 struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); 297 struct mdp_frame *frame; 298 struct v4l2_pix_format_mplane *pix_mp; 299 300 frame = ctx_get_frame(ctx, f->type); 301 *f = frame->format; 302 pix_mp = &f->fmt.pix_mp; 303 pix_mp->colorspace = ctx->curr_param.colorspace; 304 pix_mp->xfer_func = ctx->curr_param.xfer_func; 305 pix_mp->ycbcr_enc = ctx->curr_param.ycbcr_enc; 306 pix_mp->quantization = ctx->curr_param.quant; 307 308 return 0; 309 } 310 311 static int mdp_m2m_s_fmt_mplane(struct file *file, void *fh, 312 struct v4l2_format *f) 313 { 314 struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); 315 struct mdp_frame *frame = ctx_get_frame(ctx, f->type); 316 struct mdp_frame *capture; 317 const struct mdp_format *fmt; 318 struct vb2_queue *vq; 319 320 fmt = mdp_try_fmt_mplane(ctx->mdp_dev, f, &ctx->curr_param, ctx->id); 321 if (!fmt) 322 return -EINVAL; 323 324 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); 325 if (vb2_is_busy(vq)) 326 return -EBUSY; 327 328 frame->format = *f; 329 frame->mdp_fmt = fmt; 330 frame->ycbcr_prof = mdp_map_ycbcr_prof_mplane(f, fmt->mdp_color); 331 frame->usage = V4L2_TYPE_IS_OUTPUT(f->type) ? 332 MDP_BUFFER_USAGE_HW_READ : MDP_BUFFER_USAGE_MDP; 333 334 capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 335 if (V4L2_TYPE_IS_OUTPUT(f->type)) { 336 capture->crop.c.left = 0; 337 capture->crop.c.top = 0; 338 capture->crop.c.width = f->fmt.pix_mp.width; 339 capture->crop.c.height = f->fmt.pix_mp.height; 340 ctx->curr_param.colorspace = f->fmt.pix_mp.colorspace; 341 ctx->curr_param.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; 342 ctx->curr_param.quant = f->fmt.pix_mp.quantization; 343 ctx->curr_param.xfer_func = f->fmt.pix_mp.xfer_func; 344 } else { 345 capture->compose.left = 0; 346 capture->compose.top = 0; 347 capture->compose.width = f->fmt.pix_mp.width; 348 capture->compose.height = f->fmt.pix_mp.height; 349 } 350 351 return 0; 352 } 353 354 static int mdp_m2m_try_fmt_mplane(struct file *file, void *fh, 355 struct v4l2_format *f) 356 { 357 struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); 358 359 if (!mdp_try_fmt_mplane(ctx->mdp_dev, f, &ctx->curr_param, ctx->id)) 360 return -EINVAL; 361 362 return 0; 363 } 364 365 static int mdp_m2m_g_selection(struct file *file, void *fh, 366 struct v4l2_selection *s) 367 { 368 struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); 369 struct mdp_frame *frame; 370 bool valid = false; 371 372 if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 373 valid = mdp_target_is_crop(s->target); 374 else if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 375 valid = mdp_target_is_compose(s->target); 376 377 if (!valid) 378 return -EINVAL; 379 380 switch (s->target) { 381 case V4L2_SEL_TGT_CROP: 382 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 383 return -EINVAL; 384 frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 385 s->r = frame->crop.c; 386 return 0; 387 case V4L2_SEL_TGT_COMPOSE: 388 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 389 return -EINVAL; 390 frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 391 s->r = frame->compose; 392 return 0; 393 case V4L2_SEL_TGT_CROP_DEFAULT: 394 case V4L2_SEL_TGT_CROP_BOUNDS: 395 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 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 case V4L2_SEL_TGT_COMPOSE_DEFAULT: 404 case V4L2_SEL_TGT_COMPOSE_BOUNDS: 405 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 406 return -EINVAL; 407 frame = ctx_get_frame(ctx, s->type); 408 s->r.left = 0; 409 s->r.top = 0; 410 s->r.width = frame->format.fmt.pix_mp.width; 411 s->r.height = frame->format.fmt.pix_mp.height; 412 return 0; 413 } 414 return -EINVAL; 415 } 416 417 static int mdp_m2m_s_selection(struct file *file, void *fh, 418 struct v4l2_selection *s) 419 { 420 struct mdp_m2m_ctx *ctx = fh_to_ctx(fh); 421 struct mdp_frame *frame = ctx_get_frame(ctx, s->type); 422 struct mdp_frame *capture; 423 struct v4l2_rect r; 424 struct device *dev = &ctx->mdp_dev->pdev->dev; 425 bool valid = false; 426 int ret; 427 428 if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 429 valid = (s->target == V4L2_SEL_TGT_CROP); 430 else if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 431 valid = (s->target == V4L2_SEL_TGT_COMPOSE); 432 433 if (!valid) { 434 dev_dbg(dev, "[%s:%d] invalid type:%u target:%u", __func__, 435 ctx->id, s->type, s->target); 436 return -EINVAL; 437 } 438 439 ret = mdp_try_crop(ctx, &r, s, frame); 440 if (ret) 441 return ret; 442 capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 443 444 if (mdp_target_is_crop(s->target)) 445 capture->crop.c = r; 446 else 447 capture->compose = r; 448 449 s->r = r; 450 451 return 0; 452 } 453 454 static const struct v4l2_ioctl_ops mdp_m2m_ioctl_ops = { 455 .vidioc_querycap = mdp_m2m_querycap, 456 .vidioc_enum_fmt_vid_cap = mdp_m2m_enum_fmt_mplane, 457 .vidioc_enum_fmt_vid_out = mdp_m2m_enum_fmt_mplane, 458 .vidioc_g_fmt_vid_cap_mplane = mdp_m2m_g_fmt_mplane, 459 .vidioc_g_fmt_vid_out_mplane = mdp_m2m_g_fmt_mplane, 460 .vidioc_s_fmt_vid_cap_mplane = mdp_m2m_s_fmt_mplane, 461 .vidioc_s_fmt_vid_out_mplane = mdp_m2m_s_fmt_mplane, 462 .vidioc_try_fmt_vid_cap_mplane = mdp_m2m_try_fmt_mplane, 463 .vidioc_try_fmt_vid_out_mplane = mdp_m2m_try_fmt_mplane, 464 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 465 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 466 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 467 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 468 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 469 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 470 .vidioc_streamon = v4l2_m2m_ioctl_streamon, 471 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 472 .vidioc_g_selection = mdp_m2m_g_selection, 473 .vidioc_s_selection = mdp_m2m_s_selection, 474 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 475 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 476 }; 477 478 static int mdp_m2m_queue_init(void *priv, 479 struct vb2_queue *src_vq, 480 struct vb2_queue *dst_vq) 481 { 482 struct mdp_m2m_ctx *ctx = priv; 483 int ret; 484 485 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 486 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 487 src_vq->ops = &mdp_m2m_qops; 488 src_vq->mem_ops = &vb2_dma_contig_memops; 489 src_vq->drv_priv = ctx; 490 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 491 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 492 src_vq->dev = &ctx->mdp_dev->pdev->dev; 493 src_vq->lock = &ctx->ctx_lock; 494 495 ret = vb2_queue_init(src_vq); 496 if (ret) 497 return ret; 498 499 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 500 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 501 dst_vq->ops = &mdp_m2m_qops; 502 dst_vq->mem_ops = &vb2_dma_contig_memops; 503 dst_vq->drv_priv = ctx; 504 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 505 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 506 dst_vq->dev = &ctx->mdp_dev->pdev->dev; 507 dst_vq->lock = &ctx->ctx_lock; 508 509 return vb2_queue_init(dst_vq); 510 } 511 512 static int mdp_m2m_s_ctrl(struct v4l2_ctrl *ctrl) 513 { 514 struct mdp_m2m_ctx *ctx = ctrl_to_ctx(ctrl); 515 struct mdp_frame *capture; 516 517 capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 518 switch (ctrl->id) { 519 case V4L2_CID_HFLIP: 520 capture->hflip = ctrl->val; 521 break; 522 case V4L2_CID_VFLIP: 523 capture->vflip = ctrl->val; 524 break; 525 case V4L2_CID_ROTATE: 526 capture->rotation = ctrl->val; 527 break; 528 } 529 530 return 0; 531 } 532 533 static const struct v4l2_ctrl_ops mdp_m2m_ctrl_ops = { 534 .s_ctrl = mdp_m2m_s_ctrl, 535 }; 536 537 static int mdp_m2m_ctrls_create(struct mdp_m2m_ctx *ctx) 538 { 539 v4l2_ctrl_handler_init(&ctx->ctrl_handler, MDP_MAX_CTRLS); 540 ctx->ctrls.hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, 541 &mdp_m2m_ctrl_ops, V4L2_CID_HFLIP, 542 0, 1, 1, 0); 543 ctx->ctrls.vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, 544 &mdp_m2m_ctrl_ops, V4L2_CID_VFLIP, 545 0, 1, 1, 0); 546 ctx->ctrls.rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, 547 &mdp_m2m_ctrl_ops, 548 V4L2_CID_ROTATE, 0, 270, 90, 0); 549 550 if (ctx->ctrl_handler.error) { 551 int err = ctx->ctrl_handler.error; 552 553 v4l2_ctrl_handler_free(&ctx->ctrl_handler); 554 dev_err(&ctx->mdp_dev->pdev->dev, 555 "Failed to register controls\n"); 556 return err; 557 } 558 return 0; 559 } 560 561 static int mdp_m2m_open(struct file *file) 562 { 563 struct video_device *vdev = video_devdata(file); 564 struct mdp_dev *mdp = video_get_drvdata(vdev); 565 struct mdp_m2m_ctx *ctx; 566 struct device *dev = &mdp->pdev->dev; 567 int ret; 568 struct v4l2_format default_format = {}; 569 const struct mdp_limit *limit = mdp->mdp_data->def_limit; 570 571 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 572 if (!ctx) 573 return -ENOMEM; 574 575 if (mutex_lock_interruptible(&mdp->m2m_lock)) { 576 ret = -ERESTARTSYS; 577 goto err_free_ctx; 578 } 579 580 ret = ida_alloc(&mdp->mdp_ida, GFP_KERNEL); 581 if (ret < 0) 582 goto err_unlock_mutex; 583 ctx->id = ret; 584 585 ctx->mdp_dev = mdp; 586 587 v4l2_fh_init(&ctx->fh, vdev); 588 file->private_data = &ctx->fh; 589 ret = mdp_m2m_ctrls_create(ctx); 590 if (ret) 591 goto err_exit_fh; 592 593 /* Use separate control handler per file handle */ 594 ctx->fh.ctrl_handler = &ctx->ctrl_handler; 595 v4l2_fh_add(&ctx->fh); 596 597 mutex_init(&ctx->ctx_lock); 598 ctx->m2m_ctx = v4l2_m2m_ctx_init(mdp->m2m_dev, ctx, mdp_m2m_queue_init); 599 if (IS_ERR(ctx->m2m_ctx)) { 600 dev_err(dev, "Failed to initialize m2m context\n"); 601 ret = PTR_ERR(ctx->m2m_ctx); 602 goto err_release_handler; 603 } 604 ctx->fh.m2m_ctx = ctx->m2m_ctx; 605 606 ctx->curr_param.ctx = ctx; 607 ret = mdp_frameparam_init(mdp, &ctx->curr_param); 608 if (ret) { 609 dev_err(dev, "Failed to initialize mdp parameter\n"); 610 goto err_release_m2m_ctx; 611 } 612 613 mutex_unlock(&mdp->m2m_lock); 614 615 /* Default format */ 616 default_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 617 default_format.fmt.pix_mp.width = limit->out_limit.wmin; 618 default_format.fmt.pix_mp.height = limit->out_limit.hmin; 619 default_format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M; 620 mdp_m2m_s_fmt_mplane(file, &ctx->fh, &default_format); 621 default_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 622 mdp_m2m_s_fmt_mplane(file, &ctx->fh, &default_format); 623 624 dev_dbg(dev, "%s:[%d]", __func__, ctx->id); 625 626 return 0; 627 628 err_release_m2m_ctx: 629 v4l2_m2m_ctx_release(ctx->m2m_ctx); 630 err_release_handler: 631 v4l2_ctrl_handler_free(&ctx->ctrl_handler); 632 v4l2_fh_del(&ctx->fh); 633 err_exit_fh: 634 v4l2_fh_exit(&ctx->fh); 635 ida_free(&mdp->mdp_ida, ctx->id); 636 err_unlock_mutex: 637 mutex_unlock(&mdp->m2m_lock); 638 err_free_ctx: 639 kfree(ctx); 640 641 return ret; 642 } 643 644 static int mdp_m2m_release(struct file *file) 645 { 646 struct mdp_m2m_ctx *ctx = fh_to_ctx(file->private_data); 647 struct mdp_dev *mdp = video_drvdata(file); 648 struct device *dev = &mdp->pdev->dev; 649 650 mutex_lock(&mdp->m2m_lock); 651 v4l2_m2m_ctx_release(ctx->m2m_ctx); 652 if (mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT)) 653 mdp_vpu_put_locked(mdp); 654 655 v4l2_ctrl_handler_free(&ctx->ctrl_handler); 656 v4l2_fh_del(&ctx->fh); 657 v4l2_fh_exit(&ctx->fh); 658 ida_free(&mdp->mdp_ida, ctx->id); 659 mutex_unlock(&mdp->m2m_lock); 660 661 dev_dbg(dev, "%s:[%d]", __func__, ctx->id); 662 kfree(ctx); 663 664 return 0; 665 } 666 667 static const struct v4l2_file_operations mdp_m2m_fops = { 668 .owner = THIS_MODULE, 669 .poll = v4l2_m2m_fop_poll, 670 .unlocked_ioctl = video_ioctl2, 671 .mmap = v4l2_m2m_fop_mmap, 672 .open = mdp_m2m_open, 673 .release = mdp_m2m_release, 674 }; 675 676 static const struct v4l2_m2m_ops mdp_m2m_ops = { 677 .device_run = mdp_m2m_device_run, 678 }; 679 680 int mdp_m2m_device_register(struct mdp_dev *mdp) 681 { 682 struct device *dev = &mdp->pdev->dev; 683 int ret = 0; 684 685 mdp->m2m_vdev = video_device_alloc(); 686 if (!mdp->m2m_vdev) { 687 dev_err(dev, "Failed to allocate video device\n"); 688 ret = -ENOMEM; 689 goto err_video_alloc; 690 } 691 mdp->m2m_vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | 692 V4L2_CAP_STREAMING; 693 mdp->m2m_vdev->fops = &mdp_m2m_fops; 694 mdp->m2m_vdev->ioctl_ops = &mdp_m2m_ioctl_ops; 695 mdp->m2m_vdev->release = mdp_video_device_release; 696 mdp->m2m_vdev->lock = &mdp->m2m_lock; 697 mdp->m2m_vdev->vfl_dir = VFL_DIR_M2M; 698 mdp->m2m_vdev->v4l2_dev = &mdp->v4l2_dev; 699 snprintf(mdp->m2m_vdev->name, sizeof(mdp->m2m_vdev->name), "%s:m2m", 700 MDP_MODULE_NAME); 701 video_set_drvdata(mdp->m2m_vdev, mdp); 702 703 mdp->m2m_dev = v4l2_m2m_init(&mdp_m2m_ops); 704 if (IS_ERR(mdp->m2m_dev)) { 705 dev_err(dev, "Failed to initialize v4l2-m2m device\n"); 706 ret = PTR_ERR(mdp->m2m_dev); 707 goto err_m2m_init; 708 } 709 710 ret = video_register_device(mdp->m2m_vdev, VFL_TYPE_VIDEO, -1); 711 if (ret) { 712 dev_err(dev, "Failed to register video device\n"); 713 goto err_video_register; 714 } 715 716 v4l2_info(&mdp->v4l2_dev, "Driver registered as /dev/video%d", 717 mdp->m2m_vdev->num); 718 return 0; 719 720 err_video_register: 721 v4l2_m2m_release(mdp->m2m_dev); 722 err_m2m_init: 723 video_device_release(mdp->m2m_vdev); 724 err_video_alloc: 725 726 return ret; 727 } 728 729 void mdp_m2m_device_unregister(struct mdp_dev *mdp) 730 { 731 video_unregister_device(mdp->m2m_vdev); 732 } 733 734 void mdp_m2m_job_finish(struct mdp_m2m_ctx *ctx) 735 { 736 enum vb2_buffer_state vb_state = VB2_BUF_STATE_DONE; 737 738 mdp_m2m_process_done(ctx, vb_state); 739 } 740