linux/drivers/media/platform/rockchip/rga/rga.h
Sven Püschel 24a63d4c9d media: rockchip: rga: add rga3 support
Add support for the RGA3 unit contained in the RK3588.

Only a basic feature set consisting of scaling and color conversion is
implemented. Currently unimplemented features include:
- Advanced formats like 10bit YUV, FBCE mode and Tile8x8 mode
- Background color (V4L2_CID_BG_COLOR)
- Configurable alpha value (V4L2_CID_ALPHA_COMPONENT)
- Image flipping (V4L2_CID_HFLIP and V4L2_CID_VFLIP)
- Image rotation (V4L2_CID_ROTATE)
- Image cropping/composing (VIDIOC_S_SELECTION)
  - Only very basic output cropping for 1088 -> 1080 cases is implemented

The register address defines were copied from the
vendor Rockchip kernel sources and slightly adjusted to not start at 0
again for the cmd registers.

During testing it has been noted that the scaling of the hardware is
slightly incorrect. A test conversion of 128x128 RGBA to 256x256 RGBA
causes a slightly larger scaling. The scaling is suddle, as it seems
that the image is scaled to a 2px larger version and then cropped to
it's final size. Trying to use the RGA2 scaling factor calculation
didn't work. As the calculation matches the vendor kernel driver, no
further research has been utilized to check if there may be some kind of
better scaling factor calculation.

Furthermore comparing the RGA3 conversion with the GStreamer
videoconvertscale element, the chroma-site is different. A quick testing
didn't reveal a chroma-site that creates the same image with the
GStreamer Element. Also when converting from YUV to RGB the RGB values
differ by 1 or 2. This doesn't seem to be a colorspace conversion issue
but rather a slightly different precision on the calculation.

Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
2026-05-21 12:32:21 +02:00

175 lines
3.6 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
* Author: Jacob Chen <jacob-chen@iotwrt.com>
*/
#ifndef __RGA_H__
#define __RGA_H__
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <media/videobuf2-v4l2.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#define RGA_NAME "rockchip-rga"
#define DEFAULT_WIDTH 100
#define DEFAULT_HEIGHT 100
struct rga_frame {
/* Crop */
struct v4l2_rect crop;
/* Image format */
void *fmt;
struct v4l2_pix_format_mplane pix;
};
struct rga_dma_desc {
u32 addr;
};
struct rockchip_rga_version {
u32 major;
u32 minor;
};
struct rga_ctx {
struct v4l2_fh fh;
struct rockchip_rga *rga;
struct rga_frame in;
struct rga_frame out;
struct v4l2_ctrl_handler ctrl_handler;
void *cmdbuf_virt;
dma_addr_t cmdbuf_phy;
bool cmdbuf_dirty;
int osequence;
int csequence;
/* Control values */
u32 op;
u32 hflip;
u32 vflip;
u32 rotate;
u32 fill_color;
};
static inline struct rga_ctx *file_to_rga_ctx(struct file *filp)
{
return container_of(file_to_v4l2_fh(filp), struct rga_ctx, fh);
}
struct rga_hw;
struct rockchip_rga {
struct v4l2_device v4l2_dev;
struct v4l2_m2m_dev *m2m_dev;
struct video_device *vfd;
struct device *dev;
struct regmap *grf;
void __iomem *regs;
struct clk_bulk_data *clks;
int num_clks;
struct rockchip_rga_version version;
/* vfd lock */
struct mutex mutex;
/* ctrl parm lock */
spinlock_t ctrl_lock;
struct rga_ctx *curr;
const struct rga_hw *hw;
};
struct rga_addrs {
dma_addr_t y_addr;
dma_addr_t u_addr;
dma_addr_t v_addr;
};
struct rga_vb_buffer {
struct vb2_v4l2_buffer vb_buf;
struct list_head queue;
/* RGA MMU mapping for this buffer */
struct rga_dma_desc *dma_desc;
dma_addr_t dma_desc_pa;
size_t n_desc;
/* Plane DMA addresses after the MMU mapping of the buffer */
struct rga_addrs dma_addrs;
};
static inline struct rga_vb_buffer *vb_to_rga(struct vb2_v4l2_buffer *vb)
{
return container_of(vb, struct rga_vb_buffer, vb_buf);
}
struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type type);
int rga_check_scaling(const struct rga_hw *hw, const struct v4l2_rect *crop_in,
const struct v4l2_rect *crop_out, u32 rotate);
/* RGA Buffers Manage */
extern const struct vb2_ops rga_qops;
/* RGA Hardware */
static inline void rga_write(struct rockchip_rga *rga, u32 reg, u32 value)
{
writel(value, rga->regs + reg);
};
static inline u32 rga_read(struct rockchip_rga *rga, u32 reg)
{
return readl(rga->regs + reg);
};
static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
{
u32 temp = rga_read(rga, reg) & ~(mask);
temp |= val & mask;
rga_write(rga, reg, temp);
};
#define RGA_FEATURE_FLIP BIT(0)
#define RGA_FEATURE_ROTATE BIT(1)
#define RGA_FEATURE_BG_COLOR BIT(2)
struct rga_hw {
const char *card_type;
bool has_internal_iommu;
size_t cmdbuf_size;
u32 min_width, min_height;
u32 max_width, max_height;
u8 max_scaling_factor;
u8 stride_alignment;
u8 features;
void (*setup_cmdbuf)(struct rga_ctx *ctx);
void (*start)(struct rockchip_rga *rga,
struct rga_vb_buffer *src, struct rga_vb_buffer *dst);
bool (*handle_irq)(struct rockchip_rga *rga);
void (*get_version)(struct rockchip_rga *rga);
void *(*adjust_and_map_format)(struct rga_ctx *ctx,
struct v4l2_pix_format_mplane *format,
bool is_output);
int (*enum_format)(struct v4l2_fmtdesc *f);
};
static inline bool rga_has_internal_iommu(const struct rockchip_rga *rga)
{
return rga->hw->has_internal_iommu;
}
extern const struct rga_hw rga2_hw;
extern const struct rga_hw rga3_hw;
#endif