Lines Matching +full:top +full:- +full:ctrl

1 // SPDX-License-Identifier: GPL-2.0-or-later
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-ioctl.h>
23 #include <media/v4l2-mem2mem.h>
24 #include <media/v4l2-ctrls.h>
25 #include <media/videobuf2-v4l2.h>
26 #include <media/videobuf2-dma-contig.h>
28 #include "ge2d-regs.h"
30 #define GE2D_NAME "meson-ge2d"
41 * - Scaling
42 * - Simple 1/2 vertical scaling
43 * - YUV input support
44 * - Source global alpha
45 * - Colorspace conversion
142 if (formats[i].fourcc == f->fmt.pix.pixelformat) in find_fmt()
160 return &ctx->in; in get_frame()
162 return &ctx->out; in get_frame()
165 dev_warn(ctx->ge2d->dev, "%s: invalid buffer type\n", __func__); in get_frame()
166 return &ctx->in; in get_frame()
172 struct ge2d_ctx *ctx = ge2d->curr; in ge2d_hw_start()
176 regmap_update_bits(ge2d->map, GE2D_GEN_CTRL1, in ge2d_hw_start()
178 regmap_update_bits(ge2d->map, GE2D_GEN_CTRL1, in ge2d_hw_start()
183 /* Implement CANVAS for non-AXG */ in ge2d_hw_start()
184 regmap_write(ge2d->map, GE2D_SRC1_BADDR_CTRL, in ge2d_hw_start()
185 (vb2_dma_contig_plane_dma_addr(&ctx->in.buf->vb2_buf, 0) + 7) >> 3); in ge2d_hw_start()
186 regmap_write(ge2d->map, GE2D_SRC1_STRIDE_CTRL, in ge2d_hw_start()
187 (ctx->in.pix_fmt.bytesperline + 7) >> 3); in ge2d_hw_start()
188 regmap_write(ge2d->map, GE2D_SRC2_BADDR_CTRL, in ge2d_hw_start()
189 (vb2_dma_contig_plane_dma_addr(&ctx->out.buf->vb2_buf, 0) + 7) >> 3); in ge2d_hw_start()
190 regmap_write(ge2d->map, GE2D_SRC2_STRIDE_CTRL, in ge2d_hw_start()
191 (ctx->out.pix_fmt.bytesperline + 7) >> 3); in ge2d_hw_start()
192 regmap_write(ge2d->map, GE2D_DST1_BADDR_CTRL, in ge2d_hw_start()
193 (vb2_dma_contig_plane_dma_addr(&ctx->out.buf->vb2_buf, 0) + 7) >> 3); in ge2d_hw_start()
194 regmap_write(ge2d->map, GE2D_DST1_STRIDE_CTRL, in ge2d_hw_start()
195 (ctx->out.pix_fmt.bytesperline + 7) >> 3); in ge2d_hw_start()
197 regmap_write(ge2d->map, GE2D_GEN_CTRL0, 0); in ge2d_hw_start()
198 regmap_write(ge2d->map, GE2D_GEN_CTRL1, in ge2d_hw_start()
203 regmap_write(ge2d->map, GE2D_GEN_CTRL2, in ge2d_hw_start()
207 FIELD_PREP(GE2D_DST1_COLOR_MAP, ctx->out.fmt->hw_map) | in ge2d_hw_start()
208 FIELD_PREP(GE2D_DST1_FORMAT, ctx->out.fmt->hw_fmt) | in ge2d_hw_start()
209 FIELD_PREP(GE2D_SRC2_COLOR_MAP, ctx->out.fmt->hw_map) | in ge2d_hw_start()
210 FIELD_PREP(GE2D_SRC2_FORMAT, ctx->out.fmt->hw_fmt) | in ge2d_hw_start()
211 FIELD_PREP(GE2D_SRC1_COLOR_MAP, ctx->in.fmt->hw_map) | in ge2d_hw_start()
212 FIELD_PREP(GE2D_SRC1_FORMAT, ctx->in.fmt->hw_fmt)); in ge2d_hw_start()
213 regmap_write(ge2d->map, GE2D_GEN_CTRL3, in ge2d_hw_start()
216 regmap_write(ge2d->map, GE2D_SRC1_CLIPY_START_END, in ge2d_hw_start()
217 FIELD_PREP(GE2D_START, ctx->in.crop.top) | in ge2d_hw_start()
218 FIELD_PREP(GE2D_END, ctx->in.crop.top + ctx->in.crop.height - 1)); in ge2d_hw_start()
219 regmap_write(ge2d->map, GE2D_SRC1_CLIPX_START_END, in ge2d_hw_start()
220 FIELD_PREP(GE2D_START, ctx->in.crop.left) | in ge2d_hw_start()
221 FIELD_PREP(GE2D_END, ctx->in.crop.left + ctx->in.crop.width - 1)); in ge2d_hw_start()
222 regmap_write(ge2d->map, GE2D_SRC2_CLIPY_START_END, in ge2d_hw_start()
223 FIELD_PREP(GE2D_START, ctx->out.crop.top) | in ge2d_hw_start()
224 FIELD_PREP(GE2D_END, ctx->out.crop.top + ctx->out.crop.height - 1)); in ge2d_hw_start()
225 regmap_write(ge2d->map, GE2D_SRC2_CLIPX_START_END, in ge2d_hw_start()
226 FIELD_PREP(GE2D_START, ctx->out.crop.left) | in ge2d_hw_start()
227 FIELD_PREP(GE2D_END, ctx->out.crop.left + ctx->out.crop.width - 1)); in ge2d_hw_start()
228 regmap_write(ge2d->map, GE2D_DST_CLIPY_START_END, in ge2d_hw_start()
229 FIELD_PREP(GE2D_START, ctx->out.crop.top) | in ge2d_hw_start()
230 FIELD_PREP(GE2D_END, ctx->out.crop.top + ctx->out.crop.height - 1)); in ge2d_hw_start()
231 regmap_write(ge2d->map, GE2D_DST_CLIPX_START_END, in ge2d_hw_start()
232 FIELD_PREP(GE2D_START, ctx->out.crop.left) | in ge2d_hw_start()
233 FIELD_PREP(GE2D_END, ctx->out.crop.left + ctx->out.crop.width - 1)); in ge2d_hw_start()
235 regmap_write(ge2d->map, GE2D_SRC1_Y_START_END, in ge2d_hw_start()
236 FIELD_PREP(GE2D_END, ctx->in.pix_fmt.height - 1)); in ge2d_hw_start()
237 regmap_write(ge2d->map, GE2D_SRC1_X_START_END, in ge2d_hw_start()
238 FIELD_PREP(GE2D_END, ctx->in.pix_fmt.width - 1)); in ge2d_hw_start()
239 regmap_write(ge2d->map, GE2D_SRC2_Y_START_END, in ge2d_hw_start()
240 FIELD_PREP(GE2D_END, ctx->out.pix_fmt.height - 1)); in ge2d_hw_start()
241 regmap_write(ge2d->map, GE2D_SRC2_X_START_END, in ge2d_hw_start()
242 FIELD_PREP(GE2D_END, ctx->out.pix_fmt.width - 1)); in ge2d_hw_start()
243 regmap_write(ge2d->map, GE2D_DST_Y_START_END, in ge2d_hw_start()
244 FIELD_PREP(GE2D_END, ctx->out.pix_fmt.height - 1)); in ge2d_hw_start()
245 regmap_write(ge2d->map, GE2D_DST_X_START_END, in ge2d_hw_start()
246 FIELD_PREP(GE2D_END, ctx->out.pix_fmt.width - 1)); in ge2d_hw_start()
252 if (ctx->in.fmt->alpha && ctx->out.fmt->alpha) in ge2d_hw_start()
256 else if (!ctx->out.fmt->alpha) in ge2d_hw_start()
265 regmap_write(ge2d->map, GE2D_ALU_OP_CTRL, reg); in ge2d_hw_start()
268 regmap_write(ge2d->map, GE2D_CMD_CTRL, in ge2d_hw_start()
269 (ctx->xy_swap ? GE2D_DST_XY_SWAP : 0) | in ge2d_hw_start()
270 (ctx->hflip ? GE2D_SRC1_Y_REV : 0) | in ge2d_hw_start()
271 (ctx->vflip ? GE2D_SRC1_X_REV : 0) | in ge2d_hw_start()
278 struct meson_ge2d *ge2d = ctx->ge2d; in device_run()
280 ge2d->curr = ctx; in device_run()
282 ctx->in.buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); in device_run()
283 ctx->out.buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); in device_run()
293 regmap_read(ge2d->map, GE2D_STATUS0, &intr); in ge2d_isr()
297 struct ge2d_ctx *ctx = ge2d->curr; in ge2d_isr()
299 ge2d->curr = NULL; in ge2d_isr()
301 src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); in ge2d_isr()
302 dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); in ge2d_isr()
304 src->sequence = ctx->sequence_out++; in ge2d_isr()
305 dst->sequence = ctx->sequence_cap++; in ge2d_isr()
307 dst->timecode = src->timecode; in ge2d_isr()
308 dst->vb2_buf.timestamp = src->vb2_buf.timestamp; in ge2d_isr()
309 dst->flags = src->flags; in ge2d_isr()
313 v4l2_m2m_job_finish(ge2d->m2m_dev, ctx->fh.m2m_ctx); in ge2d_isr()
328 struct ge2d_frame *f = get_frame(ctx, vq->type); in ge2d_queue_setup()
331 return sizes[0] < f->pix_fmt.sizeimage ? -EINVAL : 0; in ge2d_queue_setup()
333 sizes[0] = f->pix_fmt.sizeimage; in ge2d_queue_setup()
341 struct ge2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); in ge2d_buf_prepare()
343 struct ge2d_frame *f = get_frame(ctx, vb->vb2_queue->type); in ge2d_buf_prepare()
345 vbuf->field = V4L2_FIELD_NONE; in ge2d_buf_prepare()
347 vb2_set_plane_payload(vb, 0, f->pix_fmt.sizeimage); in ge2d_buf_prepare()
355 struct ge2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); in ge2d_buf_queue()
357 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); in ge2d_buf_queue()
364 if (V4L2_TYPE_IS_OUTPUT(vq->type)) in ge2d_start_streaming()
365 ctx->sequence_out = 0; in ge2d_start_streaming()
367 ctx->sequence_cap = 0; in ge2d_start_streaming()
378 if (V4L2_TYPE_IS_OUTPUT(vq->type)) in ge2d_stop_streaming()
379 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); in ge2d_stop_streaming()
381 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); in ge2d_stop_streaming()
404 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; in queue_init()
405 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; in queue_init()
406 src_vq->drv_priv = ctx; in queue_init()
407 src_vq->ops = &ge2d_qops; in queue_init()
408 src_vq->mem_ops = &vb2_dma_contig_memops; in queue_init()
409 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); in queue_init()
410 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; in queue_init()
411 src_vq->lock = &ctx->ge2d->mutex; in queue_init()
412 src_vq->dev = ctx->ge2d->v4l2_dev.dev; in queue_init()
418 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; in queue_init()
419 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; in queue_init()
420 dst_vq->drv_priv = ctx; in queue_init()
421 dst_vq->ops = &ge2d_qops; in queue_init()
422 dst_vq->mem_ops = &vb2_dma_contig_memops; in queue_init()
423 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); in queue_init()
424 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; in queue_init()
425 dst_vq->lock = &ctx->ge2d->mutex; in queue_init()
426 dst_vq->dev = ctx->ge2d->v4l2_dev.dev; in queue_init()
434 strscpy(cap->driver, GE2D_NAME, sizeof(cap->driver)); in vidioc_querycap()
435 strscpy(cap->card, GE2D_NAME, sizeof(cap->card)); in vidioc_querycap()
436 strscpy(cap->bus_info, "platform:" GE2D_NAME, sizeof(cap->bus_info)); in vidioc_querycap()
445 if (f->index >= NUM_FORMATS) in vidioc_enum_fmt()
446 return -EINVAL; in vidioc_enum_fmt()
448 fmt = &formats[f->index]; in vidioc_enum_fmt()
449 f->pixelformat = fmt->fourcc; in vidioc_enum_fmt()
461 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && in vidioc_g_selection()
462 s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) in vidioc_g_selection()
463 return -EINVAL; in vidioc_g_selection()
465 f = get_frame(ctx, s->type); in vidioc_g_selection()
467 switch (s->target) { in vidioc_g_selection()
470 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) in vidioc_g_selection()
471 return -EINVAL; in vidioc_g_selection()
475 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) in vidioc_g_selection()
476 return -EINVAL; in vidioc_g_selection()
479 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) in vidioc_g_selection()
480 return -EINVAL; in vidioc_g_selection()
484 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) in vidioc_g_selection()
485 return -EINVAL; in vidioc_g_selection()
489 return -EINVAL; in vidioc_g_selection()
493 s->r = f->crop; in vidioc_g_selection()
495 s->r.left = 0; in vidioc_g_selection()
496 s->r.top = 0; in vidioc_g_selection()
497 s->r.width = f->pix_fmt.width; in vidioc_g_selection()
498 s->r.height = f->pix_fmt.height; in vidioc_g_selection()
508 struct meson_ge2d *ge2d = ctx->ge2d; in vidioc_s_selection()
512 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && in vidioc_s_selection()
513 s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) in vidioc_s_selection()
514 return -EINVAL; in vidioc_s_selection()
516 f = get_frame(ctx, s->type); in vidioc_s_selection()
518 switch (s->target) { in vidioc_s_selection()
524 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) in vidioc_s_selection()
525 return -EINVAL; in vidioc_s_selection()
532 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) in vidioc_s_selection()
533 return -EINVAL; in vidioc_s_selection()
540 return -EINVAL; in vidioc_s_selection()
543 if (s->r.top < 0 || s->r.left < 0) { in vidioc_s_selection()
544 v4l2_err(&ge2d->v4l2_dev, in vidioc_s_selection()
545 "doesn't support negative values for top & left.\n"); in vidioc_s_selection()
546 return -EINVAL; in vidioc_s_selection()
549 if (s->r.left + s->r.width > f->pix_fmt.width || in vidioc_s_selection()
550 s->r.top + s->r.height > f->pix_fmt.height) { in vidioc_s_selection()
551 v4l2_err(&ge2d->v4l2_dev, "unsupported rectangle value.\n"); in vidioc_s_selection()
552 return -EINVAL; in vidioc_s_selection()
555 f->crop = s->r; in vidioc_s_selection()
564 *f = frm_out->pix_fmt; in vidioc_setup_cap_fmt()
566 if (ctx->xy_swap) { in vidioc_setup_cap_fmt()
567 f->width = frm_out->pix_fmt.height; in vidioc_setup_cap_fmt()
568 f->height = frm_out->pix_fmt.width; in vidioc_setup_cap_fmt()
580 fmt_cap.pixelformat = fmt->fourcc; in vidioc_try_fmt_cap()
582 fmt_cap.bytesperline = max(f->fmt.pix.bytesperline, in vidioc_try_fmt_cap()
583 ALIGN((fmt_cap.width * fmt->depth) >> 3, 8)); in vidioc_try_fmt_cap()
585 fmt_cap.sizeimage = max(f->fmt.pix.sizeimage, in vidioc_try_fmt_cap()
588 f->fmt.pix = fmt_cap; in vidioc_try_fmt_cap()
596 struct meson_ge2d *ge2d = ctx->ge2d; in vidioc_s_fmt_cap()
608 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); in vidioc_s_fmt_cap()
610 v4l2_err(&ge2d->v4l2_dev, "queue (%d) bust\n", f->type); in vidioc_s_fmt_cap()
611 return -EBUSY; in vidioc_s_fmt_cap()
616 frm->pix_fmt = f->fmt.pix; in vidioc_s_fmt_cap()
617 frm->fmt = find_fmt(f); in vidioc_s_fmt_cap()
618 f->fmt.pix.pixelformat = frm->fmt->fourcc; in vidioc_s_fmt_cap()
621 frm->crop.left = 0; in vidioc_s_fmt_cap()
622 frm->crop.top = 0; in vidioc_s_fmt_cap()
623 frm->crop.width = frm->pix_fmt.width; in vidioc_s_fmt_cap()
624 frm->crop.height = frm->pix_fmt.height; in vidioc_s_fmt_cap()
635 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); in vidioc_g_fmt()
637 return -EINVAL; in vidioc_g_fmt()
639 frm = get_frame(ctx, f->type); in vidioc_g_fmt()
641 f->fmt.pix = frm->pix_fmt; in vidioc_g_fmt()
642 f->fmt.pix.pixelformat = frm->fmt->fourcc; in vidioc_g_fmt()
651 f->fmt.pix.field = V4L2_FIELD_NONE; in vidioc_try_fmt_out()
652 f->fmt.pix.pixelformat = fmt->fourcc; in vidioc_try_fmt_out()
654 if (f->fmt.pix.width > MAX_WIDTH) in vidioc_try_fmt_out()
655 f->fmt.pix.width = MAX_WIDTH; in vidioc_try_fmt_out()
656 if (f->fmt.pix.height > MAX_HEIGHT) in vidioc_try_fmt_out()
657 f->fmt.pix.height = MAX_HEIGHT; in vidioc_try_fmt_out()
659 f->fmt.pix.bytesperline = max(f->fmt.pix.bytesperline, in vidioc_try_fmt_out()
660 ALIGN((f->fmt.pix.width * fmt->depth) >> 3, 8)); in vidioc_try_fmt_out()
662 f->fmt.pix.sizeimage = max(f->fmt.pix.sizeimage, in vidioc_try_fmt_out()
663 f->fmt.pix.height * f->fmt.pix.bytesperline); in vidioc_try_fmt_out()
671 struct meson_ge2d *ge2d = ctx->ge2d; in vidioc_s_fmt_out()
683 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); in vidioc_s_fmt_out()
685 v4l2_err(&ge2d->v4l2_dev, "queue (%d) bust\n", f->type); in vidioc_s_fmt_out()
686 return -EBUSY; in vidioc_s_fmt_out()
692 frm->pix_fmt = f->fmt.pix; in vidioc_s_fmt_out()
693 frm->fmt = find_fmt(f); in vidioc_s_fmt_out()
694 f->fmt.pix.pixelformat = frm->fmt->fourcc; in vidioc_s_fmt_out()
697 frm->crop.left = 0; in vidioc_s_fmt_out()
698 frm->crop.top = 0; in vidioc_s_fmt_out()
699 frm->crop.width = frm->pix_fmt.width; in vidioc_s_fmt_out()
700 frm->crop.height = frm->pix_fmt.height; in vidioc_s_fmt_out()
703 vidioc_setup_cap_fmt(ctx, &frm_cap->pix_fmt); in vidioc_s_fmt_out()
739 static int ge2d_s_ctrl(struct v4l2_ctrl *ctrl) in ge2d_s_ctrl() argument
741 struct ge2d_ctx *ctx = container_of(ctrl->handler, struct ge2d_ctx, in ge2d_s_ctrl()
746 switch (ctrl->id) { in ge2d_s_ctrl()
748 ctx->hflip = ctrl->val; in ge2d_s_ctrl()
751 ctx->vflip = ctrl->val; in ge2d_s_ctrl()
754 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); in ge2d_s_ctrl()
756 return -EBUSY; in ge2d_s_ctrl()
758 if (ctrl->val == 90) { in ge2d_s_ctrl()
759 ctx->hflip = 0; in ge2d_s_ctrl()
760 ctx->vflip = 1; in ge2d_s_ctrl()
761 ctx->xy_swap = 1; in ge2d_s_ctrl()
762 } else if (ctrl->val == 180) { in ge2d_s_ctrl()
763 ctx->hflip = 1; in ge2d_s_ctrl()
764 ctx->vflip = 1; in ge2d_s_ctrl()
765 ctx->xy_swap = 0; in ge2d_s_ctrl()
766 } else if (ctrl->val == 270) { in ge2d_s_ctrl()
767 ctx->hflip = 1; in ge2d_s_ctrl()
768 ctx->vflip = 0; in ge2d_s_ctrl()
769 ctx->xy_swap = 1; in ge2d_s_ctrl()
771 ctx->hflip = 0; in ge2d_s_ctrl()
772 ctx->vflip = 0; in ge2d_s_ctrl()
773 ctx->xy_swap = 0; in ge2d_s_ctrl()
782 ctx->out.pix_fmt = fmt; in ge2d_s_ctrl()
796 struct meson_ge2d *ge2d = ctx->ge2d; in ge2d_setup_ctrls()
798 v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4); in ge2d_setup_ctrls()
800 v4l2_ctrl_new_std(&ctx->ctrl_handler, &ge2d_ctrl_ops, in ge2d_setup_ctrls()
803 v4l2_ctrl_new_std(&ctx->ctrl_handler, &ge2d_ctrl_ops, in ge2d_setup_ctrls()
806 v4l2_ctrl_new_std(&ctx->ctrl_handler, &ge2d_ctrl_ops, in ge2d_setup_ctrls()
809 if (ctx->ctrl_handler.error) { in ge2d_setup_ctrls()
810 int err = ctx->ctrl_handler.error; in ge2d_setup_ctrls()
812 v4l2_err(&ge2d->v4l2_dev, "%s failed\n", __func__); in ge2d_setup_ctrls()
813 v4l2_ctrl_handler_free(&ctx->ctrl_handler); in ge2d_setup_ctrls()
841 return -ENOMEM; in ge2d_open()
842 ctx->ge2d = ge2d; in ge2d_open()
845 ctx->in = def_frame; in ge2d_open()
846 ctx->out = def_frame; in ge2d_open()
848 if (mutex_lock_interruptible(&ge2d->mutex)) { in ge2d_open()
850 return -ERESTARTSYS; in ge2d_open()
852 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(ge2d->m2m_dev, ctx, &queue_init); in ge2d_open()
853 if (IS_ERR(ctx->fh.m2m_ctx)) { in ge2d_open()
854 ret = PTR_ERR(ctx->fh.m2m_ctx); in ge2d_open()
855 mutex_unlock(&ge2d->mutex); in ge2d_open()
859 v4l2_fh_init(&ctx->fh, video_devdata(file)); in ge2d_open()
860 file->private_data = &ctx->fh; in ge2d_open()
861 v4l2_fh_add(&ctx->fh); in ge2d_open()
866 v4l2_ctrl_handler_setup(&ctx->ctrl_handler); in ge2d_open()
868 ctx->fh.ctrl_handler = &ctx->ctrl_handler; in ge2d_open()
869 mutex_unlock(&ge2d->mutex); in ge2d_open()
877 container_of(file->private_data, struct ge2d_ctx, fh); in ge2d_release()
878 struct meson_ge2d *ge2d = ctx->ge2d; in ge2d_release()
880 mutex_lock(&ge2d->mutex); in ge2d_release()
882 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); in ge2d_release()
884 v4l2_ctrl_handler_free(&ctx->ctrl_handler); in ge2d_release()
885 v4l2_fh_del(&ctx->fh); in ge2d_release()
886 v4l2_fh_exit(&ctx->fh); in ge2d_release()
889 mutex_unlock(&ge2d->mutex); in ge2d_release()
904 .name = "meson-ge2d",
907 .minor = -1,
929 if (!pdev->dev.of_node) in ge2d_probe()
930 return -ENODEV; in ge2d_probe()
932 ge2d = devm_kzalloc(&pdev->dev, sizeof(*ge2d), GFP_KERNEL); in ge2d_probe()
934 return -ENOMEM; in ge2d_probe()
936 ge2d->dev = &pdev->dev; in ge2d_probe()
937 mutex_init(&ge2d->mutex); in ge2d_probe()
943 ge2d->map = devm_regmap_init_mmio(ge2d->dev, regs, in ge2d_probe()
945 if (IS_ERR(ge2d->map)) in ge2d_probe()
946 return PTR_ERR(ge2d->map); in ge2d_probe()
949 ret = devm_request_irq(ge2d->dev, irq, ge2d_isr, 0, in ge2d_probe()
950 dev_name(ge2d->dev), ge2d); in ge2d_probe()
952 dev_err(ge2d->dev, "failed to request irq\n"); in ge2d_probe()
956 rst = devm_reset_control_get(ge2d->dev, NULL); in ge2d_probe()
958 dev_err(ge2d->dev, "failed to get core reset controller\n"); in ge2d_probe()
962 ge2d->clk = devm_clk_get(ge2d->dev, NULL); in ge2d_probe()
963 if (IS_ERR(ge2d->clk)) { in ge2d_probe()
964 dev_err(ge2d->dev, "failed to get clock\n"); in ge2d_probe()
965 return PTR_ERR(ge2d->clk); in ge2d_probe()
972 ret = clk_prepare_enable(ge2d->clk); in ge2d_probe()
974 dev_err(ge2d->dev, "Cannot enable ge2d sclk: %d\n", ret); in ge2d_probe()
978 ret = v4l2_device_register(&pdev->dev, &ge2d->v4l2_dev); in ge2d_probe()
984 v4l2_err(&ge2d->v4l2_dev, "Failed to allocate video device\n"); in ge2d_probe()
985 ret = -ENOMEM; in ge2d_probe()
990 vfd->lock = &ge2d->mutex; in ge2d_probe()
991 vfd->v4l2_dev = &ge2d->v4l2_dev; in ge2d_probe()
994 ge2d->vfd = vfd; in ge2d_probe()
997 ge2d->m2m_dev = v4l2_m2m_init(&ge2d_m2m_ops); in ge2d_probe()
998 if (IS_ERR(ge2d->m2m_dev)) { in ge2d_probe()
999 v4l2_err(&ge2d->v4l2_dev, "Failed to init mem2mem device\n"); in ge2d_probe()
1000 ret = PTR_ERR(ge2d->m2m_dev); in ge2d_probe()
1004 ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); in ge2d_probe()
1006 v4l2_err(&ge2d->v4l2_dev, "Failed to register video device\n"); in ge2d_probe()
1010 v4l2_info(&ge2d->v4l2_dev, "Registered %s as /dev/%s\n", in ge2d_probe()
1011 vfd->name, video_device_node_name(vfd)); in ge2d_probe()
1016 v4l2_m2m_release(ge2d->m2m_dev); in ge2d_probe()
1018 video_device_release(ge2d->vfd); in ge2d_probe()
1020 v4l2_device_unregister(&ge2d->v4l2_dev); in ge2d_probe()
1022 clk_disable_unprepare(ge2d->clk); in ge2d_probe()
1031 video_unregister_device(ge2d->vfd); in ge2d_remove()
1032 v4l2_m2m_release(ge2d->m2m_dev); in ge2d_remove()
1033 v4l2_device_unregister(&ge2d->v4l2_dev); in ge2d_remove()
1034 clk_disable_unprepare(ge2d->clk); in ge2d_remove()
1041 .compatible = "amlogic,axg-ge2d",
1052 .name = "meson-ge2d",