cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}