File Index
Files and directories
Sign in
FILE

rga-buf.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/rockchip/rga/rga-buf.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
  4 * Author: Jacob Chen <jacob-chen@iotwrt.com>
  5 */
  6
  7#include <linux/pm_runtime.h>
  8#include <linux/scatterlist.h>
  9
 10#include <media/v4l2-common.h>
 11#include <media/v4l2-device.h>
 12#include <media/v4l2-ioctl.h>
 13#include <media/v4l2-mem2mem.h>
 14#include <media/videobuf2-dma-sg.h>
 15#include <media/videobuf2-v4l2.h>
 16
 17#include "rga-hw.h"
 18#include "rga.h"
 19
 20static ssize_t fill_descriptors(struct rga_dma_desc *desc, size_t max_desc,
 21				struct sg_table *sgt)
 22{
 23	struct sg_dma_page_iter iter;
 24	struct rga_dma_desc *tmp = desc;
 25	size_t n_desc = 0;
 26	dma_addr_t addr;
 27
 28	for_each_sgtable_dma_page(sgt, &iter, 0) {
 29		if (n_desc > max_desc)
 30			return -EINVAL;
 31		addr = sg_page_iter_dma_address(&iter);
 32		tmp->addr = lower_32_bits(addr);
 33		tmp++;
 34		n_desc++;
 35	}
 36
 37	return n_desc;
 38}
 39
 40static int
 41rga_queue_setup(struct vb2_queue *vq,
 42		unsigned int *nbuffers, unsigned int *nplanes,
 43		unsigned int sizes[], struct device *alloc_devs[])
 44{
 45	struct rga_ctx *ctx = vb2_get_drv_priv(vq);
 46	struct rga_frame *f = rga_get_frame(ctx, vq->type);
 47	const struct v4l2_pix_format_mplane *pix_fmt;
 48	int i;
 49
 50	if (IS_ERR(f))
 51		return PTR_ERR(f);
 52
 53	pix_fmt = &f->pix;
 54
 55	if (*nplanes) {
 56		if (*nplanes != pix_fmt->num_planes)
 57			return -EINVAL;
 58
 59		for (i = 0; i < pix_fmt->num_planes; i++)
 60			if (sizes[i] < pix_fmt->plane_fmt[i].sizeimage)
 61				return -EINVAL;
 62
 63		return 0;
 64	}
 65
 66	*nplanes = pix_fmt->num_planes;
 67
 68	for (i = 0; i < pix_fmt->num_planes; i++)
 69		sizes[i] = pix_fmt->plane_fmt[i].sizeimage;
 70
 71	return 0;
 72}
 73
 74static int rga_buf_init(struct vb2_buffer *vb)
 75{
 76	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 77	struct rga_vb_buffer *rbuf = vb_to_rga(vbuf);
 78	struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 79	struct rockchip_rga *rga = ctx->rga;
 80	struct rga_frame *f = rga_get_frame(ctx, vb->vb2_queue->type);
 81	size_t n_desc = 0;
 82
 83	if (IS_ERR(f))
 84		return PTR_ERR(f);
 85
 86	n_desc = DIV_ROUND_UP(f->size, PAGE_SIZE);
 87
 88	rbuf->n_desc = n_desc;
 89	rbuf->dma_desc = dma_alloc_coherent(rga->dev,
 90					    rbuf->n_desc * sizeof(*rbuf->dma_desc),
 91					    &rbuf->dma_desc_pa, GFP_KERNEL);
 92	if (!rbuf->dma_desc)
 93		return -ENOMEM;
 94
 95	return 0;
 96}
 97
 98static int get_plane_offset(struct rga_frame *f, int plane)
 99{
100	if (plane == 0)
101		return 0;
102	if (plane == 1)
103		return f->width * f->height;
104	if (plane == 2)
105		return f->width * f->height + (f->width * f->height / f->fmt->uv_factor);
106
107	return -EINVAL;
108}
109
110static int rga_buf_prepare(struct vb2_buffer *vb)
111{
112	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
113	struct rga_vb_buffer *rbuf = vb_to_rga(vbuf);
114	struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
115	struct rga_frame *f = rga_get_frame(ctx, vb->vb2_queue->type);
116	ssize_t n_desc = 0;
117	size_t curr_desc = 0;
118	int i;
119	const struct v4l2_format_info *info;
120	unsigned int offsets[VIDEO_MAX_PLANES];
121
122	if (IS_ERR(f))
123		return PTR_ERR(f);
124
125	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
126		if (vbuf->field == V4L2_FIELD_ANY)
127			vbuf->field = V4L2_FIELD_NONE;
128		if (vbuf->field != V4L2_FIELD_NONE)
129			return -EINVAL;
130	}
131
132	for (i = 0; i < vb->num_planes; i++) {
133		vb2_set_plane_payload(vb, i, f->pix.plane_fmt[i].sizeimage);
134
135		/* Create local MMU table for RGA */
136		n_desc = fill_descriptors(&rbuf->dma_desc[curr_desc],
137					  rbuf->n_desc - curr_desc,
138					  vb2_dma_sg_plane_desc(vb, i));
139		if (n_desc < 0) {
140			v4l2_err(&ctx->rga->v4l2_dev,
141				 "Failed to map video buffer to RGA\n");
142			return n_desc;
143		}
144		offsets[i] = curr_desc << PAGE_SHIFT;
145		curr_desc += n_desc;
146	}
147
148	/* Fill the remaining planes */
149	info = v4l2_format_info(f->fmt->fourcc);
150	for (i = info->mem_planes; i < info->comp_planes; i++)
151		offsets[i] = get_plane_offset(f, i);
152
153	rbuf->offset.y_off = offsets[0];
154	rbuf->offset.u_off = offsets[1];
155	rbuf->offset.v_off = offsets[2];
156
157	return 0;
158}
159
160static void rga_buf_queue(struct vb2_buffer *vb)
161{
162	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
163	struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
164
165	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
166}
167
168static void rga_buf_cleanup(struct vb2_buffer *vb)
169{
170	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
171	struct rga_vb_buffer *rbuf = vb_to_rga(vbuf);
172	struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
173	struct rockchip_rga *rga = ctx->rga;
174
175	dma_free_coherent(rga->dev, rbuf->n_desc * sizeof(*rbuf->dma_desc),
176			  rbuf->dma_desc, rbuf->dma_desc_pa);
177}
178
179static void rga_buf_return_buffers(struct vb2_queue *q,
180				   enum vb2_buffer_state state)
181{
182	struct rga_ctx *ctx = vb2_get_drv_priv(q);
183	struct vb2_v4l2_buffer *vbuf;
184
185	for (;;) {
186		if (V4L2_TYPE_IS_OUTPUT(q->type))
187			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
188		else
189			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
190		if (!vbuf)
191			break;
192		v4l2_m2m_buf_done(vbuf, state);
193	}
194}
195
196static int rga_buf_start_streaming(struct vb2_queue *q, unsigned int count)
197{
198	struct rga_ctx *ctx = vb2_get_drv_priv(q);
199	struct rockchip_rga *rga = ctx->rga;
200	int ret;
201
202	ret = pm_runtime_resume_and_get(rga->dev);
203	if (ret < 0) {
204		rga_buf_return_buffers(q, VB2_BUF_STATE_QUEUED);
205		return ret;
206	}
207
208	if (V4L2_TYPE_IS_OUTPUT(q->type))
209		ctx->osequence = 0;
210	else
211		ctx->csequence = 0;
212
213	return 0;
214}
215
216static void rga_buf_stop_streaming(struct vb2_queue *q)
217{
218	struct rga_ctx *ctx = vb2_get_drv_priv(q);
219	struct rockchip_rga *rga = ctx->rga;
220
221	rga_buf_return_buffers(q, VB2_BUF_STATE_ERROR);
222	pm_runtime_put(rga->dev);
223}
224
225const struct vb2_ops rga_qops = {
226	.queue_setup = rga_queue_setup,
227	.buf_init = rga_buf_init,
228	.buf_prepare = rga_buf_prepare,
229	.buf_queue = rga_buf_queue,
230	.buf_cleanup = rga_buf_cleanup,
231	.start_streaming = rga_buf_start_streaming,
232	.stop_streaming = rga_buf_stop_streaming,
233};
~/ Read-only file preview.