rga-buf.c (3478B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2017 Fuzhou Rockchip Electronics Co.Ltd 4 * Author: Jacob Chen <jacob-chen@iotwrt.com> 5 */ 6 7#include <linux/pm_runtime.h> 8 9#include <media/v4l2-device.h> 10#include <media/v4l2-ioctl.h> 11#include <media/v4l2-mem2mem.h> 12#include <media/videobuf2-dma-sg.h> 13#include <media/videobuf2-v4l2.h> 14 15#include "rga-hw.h" 16#include "rga.h" 17 18static int 19rga_queue_setup(struct vb2_queue *vq, 20 unsigned int *nbuffers, unsigned int *nplanes, 21 unsigned int sizes[], struct device *alloc_devs[]) 22{ 23 struct rga_ctx *ctx = vb2_get_drv_priv(vq); 24 struct rga_frame *f = rga_get_frame(ctx, vq->type); 25 26 if (IS_ERR(f)) 27 return PTR_ERR(f); 28 29 if (*nplanes) 30 return sizes[0] < f->size ? -EINVAL : 0; 31 32 sizes[0] = f->size; 33 *nplanes = 1; 34 35 return 0; 36} 37 38static int rga_buf_prepare(struct vb2_buffer *vb) 39{ 40 struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 41 struct rga_frame *f = rga_get_frame(ctx, vb->vb2_queue->type); 42 43 if (IS_ERR(f)) 44 return PTR_ERR(f); 45 46 vb2_set_plane_payload(vb, 0, f->size); 47 48 return 0; 49} 50 51static void rga_buf_queue(struct vb2_buffer *vb) 52{ 53 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 54 struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 55 56 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); 57} 58 59static void rga_buf_return_buffers(struct vb2_queue *q, 60 enum vb2_buffer_state state) 61{ 62 struct rga_ctx *ctx = vb2_get_drv_priv(q); 63 struct vb2_v4l2_buffer *vbuf; 64 65 for (;;) { 66 if (V4L2_TYPE_IS_OUTPUT(q->type)) 67 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 68 else 69 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 70 if (!vbuf) 71 break; 72 v4l2_m2m_buf_done(vbuf, state); 73 } 74} 75 76static int rga_buf_start_streaming(struct vb2_queue *q, unsigned int count) 77{ 78 struct rga_ctx *ctx = vb2_get_drv_priv(q); 79 struct rockchip_rga *rga = ctx->rga; 80 int ret; 81 82 ret = pm_runtime_resume_and_get(rga->dev); 83 if (ret < 0) { 84 rga_buf_return_buffers(q, VB2_BUF_STATE_QUEUED); 85 return ret; 86 } 87 88 return 0; 89} 90 91static void rga_buf_stop_streaming(struct vb2_queue *q) 92{ 93 struct rga_ctx *ctx = vb2_get_drv_priv(q); 94 struct rockchip_rga *rga = ctx->rga; 95 96 rga_buf_return_buffers(q, VB2_BUF_STATE_ERROR); 97 pm_runtime_put(rga->dev); 98} 99 100const struct vb2_ops rga_qops = { 101 .queue_setup = rga_queue_setup, 102 .buf_prepare = rga_buf_prepare, 103 .buf_queue = rga_buf_queue, 104 .wait_prepare = vb2_ops_wait_prepare, 105 .wait_finish = vb2_ops_wait_finish, 106 .start_streaming = rga_buf_start_streaming, 107 .stop_streaming = rga_buf_stop_streaming, 108}; 109 110/* RGA MMU is a 1-Level MMU, so it can't be used through the IOMMU API. 111 * We use it more like a scatter-gather list. 112 */ 113void rga_buf_map(struct vb2_buffer *vb) 114{ 115 struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 116 struct rockchip_rga *rga = ctx->rga; 117 struct sg_table *sgt; 118 struct scatterlist *sgl; 119 unsigned int *pages; 120 unsigned int address, len, i, p; 121 unsigned int mapped_size = 0; 122 123 if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 124 pages = rga->src_mmu_pages; 125 else 126 pages = rga->dst_mmu_pages; 127 128 /* Create local MMU table for RGA */ 129 sgt = vb2_plane_cookie(vb, 0); 130 131 for_each_sg(sgt->sgl, sgl, sgt->nents, i) { 132 len = sg_dma_len(sgl) >> PAGE_SHIFT; 133 address = sg_phys(sgl); 134 135 for (p = 0; p < len; p++) { 136 dma_addr_t phys = address + 137 ((dma_addr_t)p << PAGE_SHIFT); 138 139 pages[mapped_size + p] = phys; 140 } 141 142 mapped_size += len; 143 } 144 145 /* sync local MMU table for RGA */ 146 dma_sync_single_for_device(rga->dev, virt_to_phys(pages), 147 8 * PAGE_SIZE, DMA_BIDIRECTIONAL); 148}