video: rockchip: rga3: Init multi rga

Signed-off-by: Li Huang <putin.li@rock-chips.com>
Change-Id: Ib19d2d141e6b0eefa9d67b062e564559f58fb0b4
This commit is contained in:
Li Huang
2022-01-25 15:19:16 +08:00
committed by Tao Huang
parent 80eac8dcf1
commit 9f95b5fc62
28 changed files with 13825 additions and 0 deletions

View File

@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
source "drivers/video/rockchip/rga/Kconfig"
source "drivers/video/rockchip/rga2/Kconfig"
source "drivers/video/rockchip/rga3/Kconfig"
source "drivers/video/rockchip/iep/Kconfig"
source "drivers/video/rockchip/mpp/Kconfig"

View File

@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_ROCKCHIP_RGA) += rga/
obj-$(CONFIG_ROCKCHIP_RGA2) += rga2/
obj-$(CONFIG_ROCKCHIP_MULTI_RGA) += rga3/
obj-$(CONFIG_IEP) += iep/
obj-$(CONFIG_ROCKCHIP_MPP_SERVICE) += mpp/

View File

@@ -0,0 +1,30 @@
# SPDX-License-Identifier: GPL-2.0
menuconfig ROCKCHIP_MULTI_RGA
tristate "MULTI_RGA"
depends on ARCH_ROCKCHIP
help
multi_rga module.
if ROCKCHIP_MULTI_RGA
config ROCKCHIP_RGA_PROC_FS
bool "Enable RGA procfs"
select ROCKCHIP_RGA_DEBUGGER
depends on PROC_FS
help
Enable procfs to debug multi RGA driver.
config ROCKCHIP_RGA_DEBUG_FS
bool "Enable RGA debugfs"
select ROCKCHIP_RGA_DEBUGGER
depends on DEBUG_FS
default y
help
Enable debugfs to debug multi RGA driver.
config ROCKCHIP_RGA_DEBUGGER
bool
help
Enabling the debugger of multi RGA, you can use procfs and debugfs for debugging.
endif

View File

@@ -0,0 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
ccflags-y += -I$(srctree)/$(src)/include
rga3-y := rga_drv.o rga_common.o rga3_reg_info.o rga_dma_buf.o rga_fence.o rga_job.o rga_hw_config.o rga2_reg_info.o rga2_mmu_info.o rga_policy.o rga_mm.o
rga3-$(CONFIG_ROCKCHIP_RGA_DEBUGGER) += rga_debugger.o
obj-$(CONFIG_ROCKCHIP_MULTI_RGA) += rga3.o

View File

@@ -0,0 +1,673 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _RGA_DRIVER_H_
#define _RGA_DRIVER_H_
#include <linux/mutex.h>
#include <linux/scatterlist.h>
/* Use 'r' as magic number */
#define RGA_IOC_MAGIC 'r'
#define RGA_IOW(nr, type) _IOW(RGA_IOC_MAGIC, nr, type)
#define RGA_IOR(nr, type) _IOR(RGA_IOC_MAGIC, nr, type)
#define RGA_IOWR(nr, type) _IOWR(RGA_IOC_MAGIC, nr, type)
#define RGA_IOC_GET_DRVIER_VERSION RGA_IOR(0x1, struct rga_version_t)
#define RGA_IOC_GET_HW_VERSION RGA_IOR(0x2, struct rga_hw_versions_t)
#define RGA_IOC_IMPORT_BUFFER RGA_IOWR(0x3, struct rga_buffer_pool)
#define RGA_IOC_RELEASE_BUFFER RGA_IOW(0x4, struct rga_buffer_pool)
#define RGA_BLIT_SYNC 0x5017
#define RGA_BLIT_ASYNC 0x5018
#define RGA_FLUSH 0x5019
#define RGA_GET_RESULT 0x501a
#define RGA_GET_VERSION 0x501b
#define RGA_CACHE_FLUSH 0x501c
#define RGA2_GET_VERSION 0x601b
#define RGA_IMPORT_DMA 0x601d
#define RGA_RELEASE_DMA 0x601e
#define RGA_OUT_OF_RESOURCES -10
#define RGA_MALLOC_ERROR -11
#define SCALE_DOWN_LARGE 1
#define SCALE_UP_LARGE 1
#define RGA_BUFFER_POOL_SIZE_MAX 40
#define RGA3_MAJOR_VERSION_MASK (0xF0000000)
#define RGA3_MINOR_VERSION_MASK (0x0FF00000)
#define RGA3_SVN_VERSION_MASK (0x000FFFFF)
#define RGA2_MAJOR_VERSION_MASK (0xFF000000)
#define RGA2_MINOR_VERSION_MASK (0x00F00000)
#define RGA2_SVN_VERSION_MASK (0x000FFFFF)
#define RGA_MODE_ROTATE_0 (1<<0)
#define RGA_MODE_ROTATE_90 (1<<1)
#define RGA_MODE_ROTATE_180 (1<<2)
#define RGA_MODE_ROTATE_270 (1<<3)
#define RGA_MODE_X_MIRROR (1<<4)
#define RGA_MODE_Y_MIRROR (1<<5)
#define RGA_MODE_CSC_BT601L (1<<0)
#define RGA_MODE_CSC_BT601F (1<<1)
#define RGA_MODE_CSC_BT709 (1<<2)
#define RGA_MODE_CSC_BT2020 (1<<3)
#define RGA_MODE_ROTATE_MASK (\
RGA_MODE_ROTATE_0 | \
RGA_MODE_ROTATE_90 | \
RGA_MODE_ROTATE_180 | \
RGA_MODE_ROTATE_270 | \
RGA_MODE_X_MIRROR | \
RGA_MODE_Y_MIRROR)
enum rga_memory_type {
RGA_DMA_BUFFER = 0,
RGA_VIRTUAL_ADDRESS,
RGA_PHYSICAL_ADDRESS
};
enum rga_scale_up_mode {
RGA_SCALE_UP_NONE = 0x0,
RGA_SCALE_UP_BIC = 0x1,
};
enum rga_scale_down_mode {
RGA_SCALE_DOWN_NONE = 0x0,
RGA_SCALE_DOWN_AVG = 0x1,
};
/* RGA process mode enum */
enum {
BITBLT_MODE = 0x0,
COLOR_PALETTE_MODE = 0x1,
COLOR_FILL_MODE = 0x2,
/* used by rga2 */
UPDATE_PALETTE_TABLE_MODE = 0x6,
UPDATE_PATTEN_BUF_MODE = 0x7,
}; /*render mode*/
/* RGA rd_mode */
enum {
RGA_RASTER_MODE = 0x1 << 0,
RGA_FBC_MODE = 0x1 << 1,
RGA_TILE_MODE = 0x1 << 2,
};
/* RGA feature */
enum {
RGA_COLOR_FILL = 0x1 << 0,
RGA_COLOR_PALETTE = 0x1 << 1,
RGA_COLOR_KEY = 0x1 << 2,
RGA_ROP_CALCULATE = 0x1 << 3,
RGA_NN_QUANTIZE = 0x1 << 4,
RGA_OSD_BLEND = 0x1 << 5,
RGA_DITHER = 0x1 << 6,
};
enum {
RGA2_FORMAT_RGBA_8888 = 0x0,
RGA2_FORMAT_RGBX_8888 = 0x1,
RGA2_FORMAT_RGB_888 = 0x2,
RGA2_FORMAT_BGRA_8888 = 0x3,
RGA2_FORMAT_BGRX_8888 = 0x4,
RGA2_FORMAT_BGR_888 = 0x5,
RGA2_FORMAT_RGB_565 = 0x6,
RGA2_FORMAT_RGBA_5551 = 0x7,
RGA2_FORMAT_RGBA_4444 = 0x8,
RGA2_FORMAT_BGR_565 = 0x9,
RGA2_FORMAT_BGRA_5551 = 0xa,
RGA2_FORMAT_BGRA_4444 = 0xb,
RGA2_FORMAT_Y4 = 0xe,
RGA2_FORMAT_YCbCr_400 = 0xf,
RGA2_FORMAT_YCbCr_422_SP = 0x10,
RGA2_FORMAT_YCbCr_422_P = 0x11,
RGA2_FORMAT_YCbCr_420_SP = 0x12,
RGA2_FORMAT_YCbCr_420_P = 0x13,
RGA2_FORMAT_YCrCb_422_SP = 0x14,
RGA2_FORMAT_YCrCb_422_P = 0x15,
RGA2_FORMAT_YCrCb_420_SP = 0x16,
RGA2_FORMAT_YCrCb_420_P = 0x17,
RGA2_FORMAT_YVYU_422 = 0x18,
RGA2_FORMAT_YVYU_420 = 0x19,
RGA2_FORMAT_VYUY_422 = 0x1a,
RGA2_FORMAT_VYUY_420 = 0x1b,
RGA2_FORMAT_YUYV_422 = 0x1c,
RGA2_FORMAT_YUYV_420 = 0x1d,
RGA2_FORMAT_UYVY_422 = 0x1e,
RGA2_FORMAT_UYVY_420 = 0x1f,
RGA2_FORMAT_YCbCr_420_SP_10B = 0x20,
RGA2_FORMAT_YCrCb_420_SP_10B = 0x21,
RGA2_FORMAT_YCbCr_422_SP_10B = 0x22,
RGA2_FORMAT_YCrCb_422_SP_10B = 0x23,
RGA2_FORMAT_BPP_1 = 0x24,
RGA2_FORMAT_BPP_2 = 0x25,
RGA2_FORMAT_BPP_4 = 0x26,
RGA2_FORMAT_BPP_8 = 0x27,
RGA2_FORMAT_ARGB_8888 = 0x28,
RGA2_FORMAT_XRGB_8888 = 0x29,
RGA2_FORMAT_ARGB_5551 = 0x2a,
RGA2_FORMAT_ARGB_4444 = 0x2b,
RGA2_FORMAT_ABGR_8888 = 0x2c,
RGA2_FORMAT_XBGR_8888 = 0x2d,
RGA2_FORMAT_ABGR_5551 = 0x2e,
RGA2_FORMAT_ABGR_4444 = 0x2f,
};
#define RGA_SCHED_PRIORITY_DEFAULT 0
#define RGA_SCHED_PRIORITY_MAX 6
#define RGA_VERSION_SIZE 16
#define RGA_HW_SIZE 5
struct rga_version_t {
uint32_t major;
uint32_t minor;
uint32_t revision;
uint8_t str[RGA_VERSION_SIZE];
};
struct rga_hw_versions_t {
struct rga_version_t version[RGA_HW_SIZE];
uint32_t size;
};
struct rga_memory_parm {
uint32_t width;
uint32_t height;
uint32_t format;
};
struct rga_external_buffer {
uint64_t memory;
uint32_t type;
uint32_t handle;
struct rga_memory_parm memory_parm;
uint8_t reserve[256];
};
struct rga_buffer_pool {
struct rga_external_buffer __user *buffers;
uint32_t size;
};
struct rga_mmu_info_t {
unsigned long src0_base_addr;
unsigned long src1_base_addr;
unsigned long dst_base_addr;
unsigned long els_base_addr;
/* [0] mmu enable [1] flush [2] prefetch_en [3] prefetch dir */
u8 src0_mmu_flag;
u8 src1_mmu_flag;
u8 dst_mmu_flag;
u8 els_mmu_flag;
};
struct rga_color_fill_t {
int16_t gr_x_a;
int16_t gr_y_a;
int16_t gr_x_b;
int16_t gr_y_b;
int16_t gr_x_g;
int16_t gr_y_g;
int16_t gr_x_r;
int16_t gr_y_r;
};
/***************************************/
/* porting from rga.h for msg convert */
/***************************************/
struct rga_fading_t {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t res;
};
struct rga_mmu_t {
uint8_t mmu_en;
uint64_t base_addr;
/*
* [0] mmu enable [1] src_flush [2] dst_flush
* [3] CMD_flush [4~5] page size
*/
uint32_t mmu_flag;
};
struct rga_rect_t {
uint16_t xmin;
/* width - 1 */
uint16_t xmax;
uint16_t ymin;
/* height - 1 */
uint16_t ymax;
};
struct rga_point_t {
uint16_t x;
uint16_t y;
};
struct rga_line_draw_t {
/* LineDraw_start_point */
struct rga_point_t start_point;
/* LineDraw_end_point */
struct rga_point_t end_point;
/* LineDraw_color */
uint32_t color;
/* (enum) LineDrawing mode sel */
uint32_t flag;
/* range 1~16 */
uint32_t line_width;
};
/* color space convert coefficient. */
struct rga_csc_coe_t {
int16_t r_v;
int16_t g_y;
int16_t b_u;
int32_t off;
};
struct rga_full_csc_t {
uint8_t flag;
struct rga_csc_coe_t coe_y;
struct rga_csc_coe_t coe_u;
struct rga_csc_coe_t coe_v;
};
struct rga_win_info_t {
/* yrgb mem addr */
unsigned long yrgb_addr;
/* cb/cr mem addr */
unsigned long uv_addr;
/* cr mem addr */
unsigned long v_addr;
/* definition by RK_FORMAT */
unsigned int format;
unsigned short src_act_w;
unsigned short src_act_h;
unsigned short dst_act_w;
unsigned short dst_act_h;
unsigned short x_offset;
unsigned short y_offset;
unsigned short vir_w;
unsigned short vir_h;
unsigned short y2r_mode;
unsigned short r2y_mode;
unsigned short rotate_mode;
/* RASTER or FBCD or TILE */
unsigned short rd_mode;
unsigned short is_10b_compact;
unsigned short is_10b_endian;
unsigned short enable;
};
struct rga_img_info_t {
/* yrgb mem addr */
uint64_t yrgb_addr;
/* cb/cr mem addr */
uint64_t uv_addr;
/* cr mem addr */
uint64_t v_addr;
/* definition by RK_FORMAT */
uint32_t format;
uint16_t act_w;
uint16_t act_h;
uint16_t x_offset;
uint16_t y_offset;
uint16_t vir_w;
uint16_t vir_h;
uint16_t endian_mode;
/* useless */
uint16_t alpha_swap;
/* used by RGA3 */
uint16_t rotate_mode;
uint16_t rd_mode;
uint16_t is_10b_compact;
uint16_t is_10b_endian;
uint16_t enable;
};
struct rga_req {
/* (enum) process mode sel */
uint8_t render_mode;
struct rga_img_info_t src;
struct rga_img_info_t dst;
struct rga_img_info_t pat;
/* rop4 mask addr */
uint64_t rop_mask_addr;
/* LUT addr */
uint64_t LUT_addr;
/* dst clip window default value is dst_vir */
/* value from [0, w-1] / [0, h-1]*/
struct rga_rect_t clip;
/* dst angle default value 0 16.16 scan from table */
int32_t sina;
/* dst angle default value 0 16.16 scan from table */
int32_t cosa;
/* alpha rop process flag */
/* ([0] = 1 alpha_rop_enable) */
/* ([1] = 1 rop enable) */
/* ([2] = 1 fading_enable) */
/* ([3] = 1 PD_enable) */
/* ([4] = 1 alpha cal_mode_sel) */
/* ([5] = 1 dither_enable) */
/* ([6] = 1 gradient fill mode sel) */
/* ([7] = 1 AA_enable) */
uint16_t alpha_rop_flag;
/* 0 nearst / 1 bilnear / 2 bicubic */
uint8_t scale_mode;
/* color key max */
uint32_t color_key_max;
/* color key min */
uint32_t color_key_min;
/* foreground color */
uint32_t fg_color;
/* background color */
uint32_t bg_color;
/* color fill use gradient */
struct rga_color_fill_t gr_color;
struct rga_line_draw_t line_draw_info;
struct rga_fading_t fading;
/* porter duff alpha mode sel */
uint8_t PD_mode;
/* global alpha value */
uint8_t alpha_global_value;
/* rop2/3/4 code scan from rop code table*/
uint16_t rop_code;
/* [2] 0 blur 1 sharp / [1:0] filter_type*/
uint8_t bsfilter_flag;
/* (enum) color palette 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/
uint8_t palette_mode;
/* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */
uint8_t yuv2rgb_mode;
/* 0/big endian 1/little endian*/
uint8_t endian_mode;
/* (enum) rotate mode */
/* 0x0, no rotate */
/* 0x1, rotate */
/* 0x2, x_mirror */
/* 0x3, y_mirror */
uint8_t rotate_mode;
/* 0 solid color / 1 pattern color */
uint8_t color_fill_mode;
/* mmu information */
struct rga_mmu_t mmu_info;
/* ([0~1] alpha mode) */
/* ([2~3] rop mode) */
/* ([4] zero mode en) */
/* ([5] dst alpha mode) */
/* ([6] alpha output mode sel) 0 src / 1 dst*/
uint8_t alpha_rop_mode;
uint8_t src_trans_mode;
uint8_t dither_mode;
/* full color space convert */
struct rga_full_csc_t full_csc;
int32_t in_fence_fd;
uint8_t core;
uint8_t priority;
int32_t out_fence_fd;
uint8_t handle_flag;
uint8_t reservr[127];
};
struct rga2_req {
/* (enum) process mode sel */
u8 render_mode;
/* active window */
struct rga_img_info_t src;
struct rga_img_info_t src1;
struct rga_img_info_t dst;
struct rga_img_info_t pat;
/* rop4 mask addr */
unsigned long rop_mask_addr;
/* LUT addr */
unsigned long LUT_addr;
u32 rop_mask_stride;
/* 0: SRC + DST => DST */
/* 1: SRC + SRC1 => DST */
u8 bitblt_mode;
/* [1:0] */
/* 0 degree 0x0 */
/* 90 degree 0x1 */
/* 180 degree 0x2 */
/* 270 degree 0x3 */
/* [5:4] */
/* none 0x0 */
/* x_mirror 0x1 */
/* y_mirror 0x2 */
/* x_mirror + y_mirror 0x3 */
u8 rotate_mode;
/* alpha rop process flag */
/* ([0] = 1 alpha_rop_enable) */
/* ([1] = 1 rop enable) */
/* ([2] = 1 fading_enable) */
/* ([3] = 1 alpha cal_mode_sel) */
/* ([4] = 1 src_dither_up_enable) */
/* ([5] = 1 dst_dither_up_enable) */
/* ([6] = 1 dither_down_enable) */
/* ([7] = 1 gradient fill mode sel) */
u16 alpha_rop_flag;
/* [0] SrcAlphaMode0 */
/* [2:1] SrcGlobalAlphaMode0 */
/* [3] SrcAlphaSelectMode0 */
/* [6:4] SrcFactorMode0 */
/* [7] SrcColorMode */
/* [8] DstAlphaMode0 */
/* [10:9] DstGlobalAlphaMode0 */
/* [11] DstAlphaSelectMode0 */
/* [14:12] DstFactorMode0 */
/* [15] DstColorMode0 */
u16 alpha_mode_0;
/* [0] SrcAlphaMode1 */
/* [2:1] SrcGlobalAlphaMode1 */
/* [3] SrcAlphaSelectMode1 */
/* [6:4] SrcFactorMode1 */
/* [8] DstAlphaMode1 */
/* [10:9] DstGlobalAlphaMode1 */
/* [11] DstAlphaSelectMode1 */
/* [14:12] DstFactorMode1 */
u16 alpha_mode_1;
/* 0 1 2 3 */
u8 scale_bicu_mode;
u32 color_key_max;
u32 color_key_min;
/* foreground color */
u32 fg_color;
/* background color */
u32 bg_color;
u8 color_fill_mode;
/* color fill use gradient */
struct rga_color_fill_t gr_color;
/* Fading value */
u8 fading_alpha_value;
u8 fading_r_value;
u8 fading_g_value;
u8 fading_b_value;
/* src global alpha value */
u8 src_a_global_val;
/* dst global alpha value */
u8 dst_a_global_val;
/* rop mode select 0 : rop2 1 : rop3 2 : rop4 */
u8 rop_mode;
/* rop2/3/4 code */
u16 rop_code;
/* (enum) color palette 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/
u8 palette_mode;
/* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */
u8 yuv2rgb_mode;
/* [1:0] src0 csc mode */
/* [3:2] dst csc mode */
/* [4] dst csc clip enable */
/* [6:5] src1 csc mdoe */
/* [7] src1 csc clip enable */
/* full color space convert */
struct rga_full_csc_t full_csc;
/* 0/little endian 1/big endian */
u8 endian_mode;
u8 CMD_fin_int_enable;
/* mmu information */
struct rga_mmu_info_t mmu_info;
u8 alpha_zero_key;
u8 src_trans_mode;
/* useless */
u8 alpha_swp;
u8 dither_mode;
u8 rgb2yuv_mode;
};
struct rga3_req {
/* (enum) process mode sel */
u8 render_mode;
struct rga_win_info_t win0;
struct rga_win_info_t wr;
struct rga_win_info_t win1;
/* rop4 mask addr */
unsigned long rop_mask_addr;
unsigned long LUT_addr;
u32 rop_mask_stride;
u8 bitblt_mode;
u8 rotate_mode;
u16 alpha_rop_flag;
u16 alpha_mode_0;
u16 alpha_mode_1;
u8 scale_bicu_mode;
u32 color_key_max;
u32 color_key_min;
u32 fg_color;
u32 bg_color;
u8 color_fill_mode;
struct rga_color_fill_t gr_color;
u8 fading_alpha_value;
u8 fading_r_value;
u8 fading_g_value;
u8 fading_b_value;
/* win0 global alpha value */
u8 win0_a_global_val;
/* win1 global alpha value */
u8 win1_a_global_val;
u8 rop_mode;
u16 rop_code;
u8 palette_mode;
u8 yuv2rgb_mode;
u8 endian_mode;
u8 CMD_fin_int_enable;
struct rga_mmu_info_t mmu_info;
u8 alpha_zero_key;
u8 src_trans_mode;
u8 alpha_swp;
u8 dither_mode;
u8 rgb2yuv_mode;
};
struct rga_mpi_job_t {
struct dma_buf *dma_buf_src0;
struct dma_buf *dma_buf_src1;
struct dma_buf *dma_buf_dst;
};
int rga_mpi_commit(struct rga_req *cmd, struct rga_mpi_job_t *mpi_job);
#endif /*_RGA_DRIVER_H_*/

View File

@@ -0,0 +1,45 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __RGA_MMU_INFO_H__
#define __RGA_MMU_INFO_H__
#include "rga_drv.h"
/*
* The maximum input is 8192*8192, the maximum output is 4096*4096
* The size of physical pages requested is:
* (( maximum_input_value *
* maximum_input_value * format_bpp ) / 4K_page_size) + 1
*/
#define RGA2_PHY_PAGE_SIZE (((8192 * 8192 * 4) / 4096) + 1)
enum {
MMU_MAP_CLEAN = 1 << 0,
MMU_MAP_INVALID = 1 << 1,
MMU_MAP_MASK = 0x03,
MMU_UNMAP_CLEAN = 1 << 2,
MMU_UNMAP_INVALID = 1 << 3,
MMU_UNMAP_MASK = 0x0c,
};
struct rga2_mmu_info_t {
int32_t front;
int32_t back;
int32_t size;
int32_t curr;
unsigned int *buf;
unsigned int *buf_virtual;
struct page **pages;
u8 buf_order;
u8 pages_order;
};
void rga2_dma_flush_cache_for_virtual_address(struct rga2_mmu_other_t *reg,
struct rga_scheduler_t *scheduler);
int rga2_set_mmu_reg_info(struct rga2_mmu_other_t *reg,
struct rga2_req *req, struct rga_job *job);
#endif

View File

@@ -0,0 +1,332 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __REG2_INFO_H__
#define __REG2_INFO_H__
#include "rga_drv.h"
/* General Registers */
#define RGA2_SYS_CTRL 0x000
#define RGA2_CMD_CTRL 0x004
#define RGA2_CMD_BASE 0x008
#define RGA2_STATUS 0x00c
#define RGA2_INT 0x010
#define RGA2_MMU_CTRL0 0x018
#define RGA2_MMU_CMD_BASE 0x01c
#define RGA2_VERSION_NUM 0x028
/* Full Csc Coefficient */
#define RGA2_CSC_COE_BASE 0x60
#define rRGA_SYS_CTRL \
(*(volatile u32 *)(RGA2_BASE + RGA2_SYS_CTRL_OFFSET))
#define rRGA_CMD_CTRL \
(*(volatile u32 *)(RGA2_BASE + RGA2_CMD_CTRL_OFFSET))
#define rRGA_CMD_BASE \
(*(volatile u32 *)(RGA2_BASE + RGA2_CMD_BASE_OFFSET))
#define rRGA_STATUS \
(*(volatile u32 *)(RGA2_BASE + RGA2_STATUS_OFFSET))
#define rRGA_INT \
(*(volatile u32 *)(RGA2_BASE + RGA2_INT_OFFSET))
#define rRGA_MMU_CTRL0 \
(*(volatile u32 *)(RGA2_BASE + RGA2_MMU_CTRL0_OFFSET))
#define rRGA_MMU_CMD_BASE \
(*(volatile u32 *)(RGA2_BASE + RGA2_MMU_CMD_BASE_OFFSET))
#define rRGA_CMD_ADDR \
(*(volatile u32 *)(RGA2_BASE + RGA2_CMD_ADDR))
/* RGA_INT */
#define m_RGA2_INT_ALL_CMD_DONE_INT_EN (1<<10)
#define m_RGA2_INT_MMU_INT_EN (1<<9)
#define m_RGA2_INT_ERROR_INT_EN (1<<8)
#define m_RGA2_INT_NOW_CMD_DONE_INT_CLEAR (1<<7)
#define m_RGA2_INT_ALL_CMD_DONE_INT_CLEAR (1<<6)
#define m_RGA2_INT_MMU_INT_CLEAR (1<<5)
#define m_RGA2_INT_ERROR_INT_CLEAR (1<<4)
#define m_RGA2_INT_CUR_CMD_DONE_INT_FLAG (1<<3)
#define m_RGA2_INT_ALL_CMD_DONE_INT_FLAG (1<<2)
#define m_RGA2_INT_MMU_INT_FLAG (1<<1)
#define m_RGA2_INT_ERROR_INT_FLAG (1<<0)
#define s_RGA2_INT_ALL_CMD_DONE_INT_EN(x) ((x&0x1)<<10)
#define s_RGA2_INT_MMU_INT_EN(x) ((x&0x1)<<9)
#define s_RGA2_INT_ERROR_INT_EN(x) ((x&0x1)<<8)
#define s_RGA2_INT_NOW_CMD_DONE_INT_CLEAR(x) ((x&0x1)<<7)
#define s_RGA2_INT_ALL_CMD_DONE_INT_CLEAR(x) ((x&0x1)<<6)
#define s_RGA2_INT_MMU_INT_CLEAR(x) ((x&0x1)<<5)
#define s_RGA2_INT_ERROR_INT_CLEAR(x) ((x&0x1)<<4)
/* RGA_MODE_CTRL */
#define m_RGA2_MODE_CTRL_SW_RENDER_MODE (0x7<<0)
#define m_RGA2_MODE_CTRL_SW_BITBLT_MODE (0x1<<3)
#define m_RGA2_MODE_CTRL_SW_CF_ROP4_PAT (0x1<<4)
#define m_RGA2_MODE_CTRL_SW_ALPHA_ZERO_KET (0x1<<5)
#define m_RGA2_MODE_CTRL_SW_GRADIENT_SAT (0x1<<6)
#define m_RGA2_MODE_CTRL_SW_INTR_CF_E (0x1<<7)
#define s_RGA2_MODE_CTRL_SW_RENDER_MODE(x) ((x&0x7)<<0)
#define s_RGA2_MODE_CTRL_SW_BITBLT_MODE(x) ((x&0x1)<<3)
#define s_RGA2_MODE_CTRL_SW_CF_ROP4_PAT(x) ((x&0x1)<<4)
#define s_RGA2_MODE_CTRL_SW_ALPHA_ZERO_KET(x) ((x&0x1)<<5)
#define s_RGA2_MODE_CTRL_SW_GRADIENT_SAT(x) ((x&0x1)<<6)
#define s_RGA2_MODE_CTRL_SW_INTR_CF_E(x) ((x&0x1)<<7)
/* RGA_SRC_INFO */
#define m_RGA2_SRC_INFO_SW_SRC_FMT (0xf<<0)
#define m_RGA2_SRC_INFO_SW_SW_SRC_RB_SWAP (0x1<<4)
#define m_RGA2_SRC_INFO_SW_SW_SRC_ALPHA_SWAP (0x1<<5)
#define m_RGA2_SRC_INFO_SW_SW_SRC_UV_SWAP (0x1<<6)
#define m_RGA2_SRC_INFO_SW_SW_CP_ENDAIN (0x1<<7)
#define m_RGA2_SRC_INFO_SW_SW_SRC_CSC_MODE (0x3<<8)
#define m_RGA2_SRC_INFO_SW_SW_SRC_ROT_MODE (0x3<<10)
#define m_RGA2_SRC_INFO_SW_SW_SRC_MIR_MODE (0x3<<12)
#define m_RGA2_SRC_INFO_SW_SW_SRC_HSCL_MODE (0x3<<14)
#define m_RGA2_SRC_INFO_SW_SW_SRC_VSCL_MODE (0x3<<16)
#define m_RGA2_SRC_INFO_SW_SW_SRC_TRANS_MODE (0x1<<18)
#define m_RGA2_SRC_INFO_SW_SW_SRC_TRANS_E (0xf<<19)
#define m_RGA2_SRC_INFO_SW_SW_SRC_DITHER_UP_E (0x1<<23)
#define m_RGA2_SRC_INFO_SW_SW_SRC_SCL_FILTER (0x3<<24)
#define m_RGA2_SRC_INFO_SW_SW_VSP_MODE_SEL (0x1<<26)
#define m_RGA2_SRC_INFO_SW_SW_YUV10_E (0x1<<27)
#define m_RGA2_SRC_INFO_SW_SW_YUV10_ROUND_E (0x1<<28)
#define s_RGA2_SRC_INFO_SW_SRC_FMT(x) ((x&0xf)<<0)
#define s_RGA2_SRC_INFO_SW_SW_SRC_RB_SWAP(x) ((x&0x1)<<4)
#define s_RGA2_SRC_INFO_SW_SW_SRC_ALPHA_SWAP(x) ((x&0x1)<<5)
#define s_RGA2_SRC_INFO_SW_SW_SRC_UV_SWAP(x) ((x&0x1)<<6)
#define s_RGA2_SRC_INFO_SW_SW_CP_ENDAIN(x) ((x&0x1)<<7)
#define s_RGA2_SRC_INFO_SW_SW_SRC_CSC_MODE(x) ((x&0x3)<<8)
#define s_RGA2_SRC_INFO_SW_SW_SRC_ROT_MODE(x) ((x&0x3)<<10)
#define s_RGA2_SRC_INFO_SW_SW_SRC_MIR_MODE(x) ((x&0x3)<<12)
#define s_RGA2_SRC_INFO_SW_SW_SRC_HSCL_MODE(x) ((x&0x3)<<14)
#define s_RGA2_SRC_INFO_SW_SW_SRC_VSCL_MODE(x) ((x&0x3)<<16)
#define s_RGA2_SRC_INFO_SW_SW_SRC_TRANS_MODE(x) ((x&0x1)<<18)
#define s_RGA2_SRC_INFO_SW_SW_SRC_TRANS_E(x) ((x&0xf)<<19)
#define s_RGA2_SRC_INFO_SW_SW_SRC_DITHER_UP_E(x) ((x&0x1)<<23)
#define s_RGA2_SRC_INFO_SW_SW_SRC_SCL_FILTER(x) ((x&0x3)<<24)
#define s_RGA2_SRC_INFO_SW_SW_VSP_MODE_SEL(x) ((x&0x1)<<26)
#define s_RGA2_SRC_INFO_SW_SW_YUV10_E(x) ((x&0x1)<<27)
#define s_RGA2_SRC_INFO_SW_SW_YUV10_ROUND_E(x) ((x&0x1)<<28)
/* RGA_SRC_VIR_INFO */
#define m_RGA2_SRC_VIR_INFO_SW_SRC_VIR_STRIDE (0x7fff<<0)
#define m_RGA2_SRC_VIR_INFO_SW_MASK_VIR_STRIDE (0x3ff<<16)
#define s_RGA2_SRC_VIR_INFO_SW_SRC_VIR_STRIDE(x) ((x&0x7fff)<<0)
#define s_RGA2_SRC_VIR_INFO_SW_MASK_VIR_STRIDE(x) ((x&0x3ff)<<16)
/* RGA_SRC_ACT_INFO */
#define m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH (0x1fff<<0)
#define m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT (0x1fff<<16)
#define s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH(x) ((x&0x1fff)<<0)
#define s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT(x) ((x&0x1fff)<<16)
/* RGA_DST_INFO */
#define m_RGA2_DST_INFO_SW_DST_FMT (0xf<<0)
#define m_RGA2_DST_INFO_SW_DST_RB_SWAP (0x1<<4)
#define m_RGA2_DST_INFO_SW_ALPHA_SWAP (0x1<<5)
#define m_RGA2_DST_INFO_SW_DST_UV_SWAP (0x1<<6)
#define m_RGA2_DST_INFO_SW_SRC1_FMT (0x7<<7)
#define m_RGA2_DST_INFO_SW_SRC1_RB_SWP (0x1<<10)
#define m_RGA2_DST_INFO_SW_SRC1_ALPHA_SWP (0x1<<11)
#define m_RGA2_DST_INFO_SW_DITHER_UP_E (0x1<<12)
#define m_RGA2_DST_INFO_SW_DITHER_DOWN_E (0x1<<13)
#define m_RGA2_DST_INFO_SW_DITHER_MODE (0x3<<14)
#define m_RGA2_DST_INFO_SW_DST_CSC_MODE (0x3<<16)
#define m_RGA2_DST_INFO_SW_CSC_CLIP_MODE (0x1<<18)
#define m_RGA2_DST_INFO_SW_DST_CSC_MODE_2 (0x1<<19)
#define m_RGA2_DST_INFO_SW_DST_FMT_YUV400_EN (0x1<<24)
#define m_RGA2_DST_INFO_SW_DST_FMT_Y4_EN (0x1<<25)
#define m_RGA2_DST_INFO_SW_DST_NN_QUANTIZE_EN (0x1<<26)
#define m_RGA2_DST_INFO_SW_SRC1_CSC_MODE (0x3<<20)
#define m_RGA2_DST_INFO_SW_SRC1_CSC_CLIP_MODE (0x1<<22)
#define s_RGA2_DST_INFO_SW_DST_FMT(x) ((x&0xf)<<0)
#define s_RGA2_DST_INFO_SW_DST_RB_SWAP(x) ((x&0x1)<<4)
#define s_RGA2_DST_INFO_SW_ALPHA_SWAP(x) ((x&0x1)<<5)
#define s_RGA2_DST_INFO_SW_DST_UV_SWAP(x) ((x&0x1)<<6)
#define s_RGA2_DST_INFO_SW_SRC1_FMT(x) ((x&0x7)<<7)
#define s_RGA2_DST_INFO_SW_SRC1_RB_SWP(x) ((x&0x1)<<10)
#define s_RGA2_DST_INFO_SW_SRC1_ALPHA_SWP(x) ((x&0x1)<<11)
#define s_RGA2_DST_INFO_SW_DITHER_UP_E(x) ((x&0x1)<<12)
#define s_RGA2_DST_INFO_SW_DITHER_DOWN_E(x) ((x&0x1)<<13)
#define s_RGA2_DST_INFO_SW_DITHER_MODE(x) ((x&0x3)<<14)
#define s_RGA2_DST_INFO_SW_DST_CSC_MODE(x) ((x&0x3)<<16)
#define s_RGA2_DST_INFO_SW_CSC_CLIP_MODE(x) ((x&0x1)<<18)
#define s_RGA2_DST_INFO_SW_DST_CSC_MODE_2(x) ((x&0x1)<<19)
#define s_RGA2_DST_INFO_SW_DST_FMT_YUV400_EN(x) ((x&0x1)<<24)
#define s_RGA2_DST_INFO_SW_DST_FMT_Y4_EN(x) ((x&0x1)<<25)
#define s_RGA2_DST_INFO_SW_DST_NN_QUANTIZE_EN(x) ((x&0x1)<<26)
#define s_RGA2_DST_INFO_SW_SRC1_CSC_MODE(x) ((x&0x3)<<20)
#define s_RGA2_DST_INFO_SW_SRC1_CSC_CLIP_MODE(x) ((x&0x1)<<22)
/* RGA_ALPHA_CTRL0 */
#define m_RGA2_ALPHA_CTRL0_SW_ALPHA_ROP_0 (0x1<<0)
#define m_RGA2_ALPHA_CTRL0_SW_ALPHA_ROP_SEL (0x1<<1)
#define m_RGA2_ALPHA_CTRL0_SW_ROP_MODE (0x3<<2)
#define m_RGA2_ALPHA_CTRL0_SW_SRC_GLOBAL_ALPHA (0xff<<4)
#define m_RGA2_ALPHA_CTRL0_SW_DST_GLOBAL_ALPHA (0xff<<12)
#define m_RGA2_ALPHA_CTRLO_SW_MASK_ENDIAN (0x1<<20)
#define s_RGA2_ALPHA_CTRL0_SW_ALPHA_ROP_0(x) ((x&0x1)<<0)
#define s_RGA2_ALPHA_CTRL0_SW_ALPHA_ROP_SEL(x) ((x&0x1)<<1)
#define s_RGA2_ALPHA_CTRL0_SW_ROP_MODE(x) ((x&0x3)<<2)
#define s_RGA2_ALPHA_CTRL0_SW_SRC_GLOBAL_ALPHA(x) ((x&0xff)<<4)
#define s_RGA2_ALPHA_CTRL0_SW_DST_GLOBAL_ALPHA(x) ((x&0xff)<<12)
#define s_RGA2_ALPHA_CTRLO_SW_MASK_ENDIAN(x) ((x&0x1)<<20)
/* RGA_ALPHA_CTRL1 */
#define m_RGA2_ALPHA_CTRL1_SW_DST_COLOR_M0 (0x1<<0)
#define m_RGA2_ALPHA_CTRL1_SW_SRC_COLOR_M0 (0x1<<1)
#define m_RGA2_ALPHA_CTRL1_SW_DST_FACTOR_M0 (0x7<<2)
#define m_RGA2_ALPHA_CTRL1_SW_SRC_FACTOR_M0 (0x7<<5)
#define m_RGA2_ALPHA_CTRL1_SW_DST_ALPHA_CAL_M0 (0x1<<8)
#define m_RGA2_ALPHA_CTRL1_SW_SRC_ALPHA_CAL_M0 (0x1<<9)
#define m_RGA2_ALPHA_CTRL1_SW_DST_BLEND_M0 (0x3<<10)
#define m_RGA2_ALPHA_CTRL1_SW_SRC_BLEND_M0 (0x3<<12)
#define m_RGA2_ALPHA_CTRL1_SW_DST_ALPHA_M0 (0x1<<14)
#define m_RGA2_ALPHA_CTRL1_SW_SRC_ALPHA_M0 (0x1<<15)
#define m_RGA2_ALPHA_CTRL1_SW_DST_FACTOR_M1 (0x7<<16)
#define m_RGA2_ALPHA_CTRL1_SW_SRC_FACTOR_M1 (0x7<<19)
#define m_RGA2_ALPHA_CTRL1_SW_DST_ALPHA_CAL_M1 (0x1<<22)
#define m_RGA2_ALPHA_CTRL1_SW_SRC_ALPHA_CAL_M1 (0x1<<23)
#define m_RGA2_ALPHA_CTRL1_SW_DST_BLEND_M1 (0x3<<24)
#define m_RGA2_ALPHA_CTRL1_SW_SRC_BLEND_M1 (0x3<<26)
#define m_RGA2_ALPHA_CTRL1_SW_DST_ALPHA_M1 (0x1<<28)
#define m_RGA2_ALPHA_CTRL1_SW_SRC_ALPHA_M1 (0x1<<29)
#define s_RGA2_ALPHA_CTRL1_SW_DST_COLOR_M0(x) ((x&0x1)<<0)
#define s_RGA2_ALPHA_CTRL1_SW_SRC_COLOR_M0(x) ((x&0x1)<<1)
#define s_RGA2_ALPHA_CTRL1_SW_DST_FACTOR_M0(x) ((x&0x7)<<2)
#define s_RGA2_ALPHA_CTRL1_SW_SRC_FACTOR_M0(x) ((x&0x7)<<5)
#define s_RGA2_ALPHA_CTRL1_SW_DST_ALPHA_CAL_M0(x) ((x&0x1)<<8)
#define s_RGA2_ALPHA_CTRL1_SW_SRC_ALPHA_CAL_M0(x) ((x&0x1)<<9)
#define s_RGA2_ALPHA_CTRL1_SW_DST_BLEND_M0(x) ((x&0x3)<<10)
#define s_RGA2_ALPHA_CTRL1_SW_SRC_BLEND_M0(x) ((x&0x3)<<12)
#define s_RGA2_ALPHA_CTRL1_SW_DST_ALPHA_M0(x) ((x&0x1)<<14)
#define s_RGA2_ALPHA_CTRL1_SW_SRC_ALPHA_M0(x) ((x&0x1)<<15)
#define s_RGA2_ALPHA_CTRL1_SW_DST_FACTOR_M1(x) ((x&0x7)<<16)
#define s_RGA2_ALPHA_CTRL1_SW_SRC_FACTOR_M1(x) ((x&0x7)<<19)
#define s_RGA2_ALPHA_CTRL1_SW_DST_ALPHA_CAL_M1(x) ((x&0x1)<<22)
#define s_RGA2_ALPHA_CTRL1_SW_SRC_ALPHA_CAL_M1(x) ((x&0x1)<<23)
#define s_RGA2_ALPHA_CTRL1_SW_DST_BLEND_M1(x) ((x&0x3)<<24)
#define s_RGA2_ALPHA_CTRL1_SW_SRC_BLEND_M1(x) ((x&0x3)<<26)
#define s_RGA2_ALPHA_CTRL1_SW_DST_ALPHA_M1(x) ((x&0x1)<<28)
#define s_RGA2_ALPHA_CTRL1_SW_SRC_ALPHA_M1(x) ((x&0x1)<<29)
/* RGA_MMU_CTRL1 */
#define m_RGA2_MMU_CTRL1_SW_SRC_MMU_EN (0x1<<0)
#define m_RGA2_MMU_CTRL1_SW_SRC_MMU_FLUSH (0x1<<1)
#define m_RGA2_MMU_CTRL1_SW_SRC_MMU_PREFETCH_EN (0x1<<2)
#define m_RGA2_MMU_CTRL1_SW_SRC_MMU_PREFETCH_DIR (0x1<<3)
#define m_RGA2_MMU_CTRL1_SW_SRC1_MMU_EN (0x1<<4)
#define m_RGA2_MMU_CTRL1_SW_SRC1_MMU_FLUSH (0x1<<5)
#define m_RGA2_MMU_CTRL1_SW_SRC1_MMU_PREFETCH_EN (0x1<<6)
#define m_RGA2_MMU_CTRL1_SW_SRC1_MMU_PREFETCH_DIR (0x1<<7)
#define m_RGA2_MMU_CTRL1_SW_DST_MMU_EN (0x1<<8)
#define m_RGA2_MMU_CTRL1_SW_DST_MMU_FLUSH (0x1<<9)
#define m_RGA2_MMU_CTRL1_SW_DST_MMU_PREFETCH_EN (0x1<<10)
#define m_RGA2_MMU_CTRL1_SW_DST_MMU_PREFETCH_DIR (0x1<<11)
#define m_RGA2_MMU_CTRL1_SW_ELS_MMU_EN (0x1<<12)
#define m_RGA2_MMU_CTRL1_SW_ELS_MMU_FLUSH (0x1<<13)
#define s_RGA2_MMU_CTRL1_SW_SRC_MMU_EN(x) ((x&0x1)<<0)
#define s_RGA2_MMU_CTRL1_SW_SRC_MMU_FLUSH(x) ((x&0x1)<<1)
#define s_RGA2_MMU_CTRL1_SW_SRC_MMU_PREFETCH_EN(x) ((x&0x1)<<2)
#define s_RGA2_MMU_CTRL1_SW_SRC_MMU_PREFETCH_DIR(x) ((x&0x1)<<3)
#define s_RGA2_MMU_CTRL1_SW_SRC1_MMU_EN(x) ((x&0x1)<<4)
#define s_RGA2_MMU_CTRL1_SW_SRC1_MMU_FLUSH(x) ((x&0x1)<<5)
#define s_RGA2_MMU_CTRL1_SW_SRC1_MMU_PREFETCH_EN(x) ((x&0x1)<<6)
#define s_RGA2_MMU_CTRL1_SW_SRC1_MMU_PREFETCH_DIR(x) ((x&0x1)<<7)
#define s_RGA2_MMU_CTRL1_SW_DST_MMU_EN(x) ((x&0x1)<<8)
#define s_RGA2_MMU_CTRL1_SW_DST_MMU_FLUSH(x) ((x&0x1)<<9)
#define s_RGA2_MMU_CTRL1_SW_DST_MMU_PREFETCH_EN(x) ((x&0x1)<<10)
#define s_RGA2_MMU_CTRL1_SW_DST_MMU_PREFETCH_DIR(x) ((x&0x1)<<11)
#define s_RGA2_MMU_CTRL1_SW_ELS_MMU_EN(x) ((x&0x1)<<12)
#define s_RGA2_MMU_CTRL1_SW_ELS_MMU_FLUSH(x) ((x&0x1)<<13)
#define RGA2_SYS_CTRL_OFFSET 0x0
#define RGA2_CMD_CTRL_OFFSET 0x4
#define RGA2_CMD_BASE_OFFSET 0x8
#define RGA2_STATUS_OFFSET 0xc
#define RGA2_INT_OFFSET 0x10
#define RGA2_MMU_CTRL0_OFFSET 0x14
#define RGA2_MMU_CMD_BASE_OFFSET 0x18
/* dst full csc */
#define RGA2_DST_CSC_00_OFFSET 0x0
#define RGA2_DST_CSC_01_OFFSET 0x4
#define RGA2_DST_CSC_02_OFFSET 0x8
#define RGA2_DST_CSC_OFF0_OFFSET 0xc
#define RGA2_DST_CSC_10_OFFSET 0x10
#define RGA2_DST_CSC_11_OFFSET 0x14
#define RGA2_DST_CSC_12_OFFSET 0x18
#define RGA2_DST_CSC_OFF1_OFFSET 0x1c
#define RGA2_DST_CSC_20_OFFSET 0x20
#define RGA2_DST_CSC_21_OFFSET 0x24
#define RGA2_DST_CSC_22_OFFSET 0x28
#define RGA2_DST_CSC_OFF2_OFFSET 0x2c
#define RGA2_MODE_CTRL_OFFSET 0x00
#define RGA2_SRC_INFO_OFFSET 0x04
#define RGA2_SRC_BASE0_OFFSET 0x08
#define RGA2_SRC_BASE1_OFFSET 0x0c
#define RGA2_SRC_BASE2_OFFSET 0x10
#define RGA2_SRC_BASE3_OFFSET 0x14
#define RGA2_SRC_VIR_INFO_OFFSET 0x18
#define RGA2_SRC_ACT_INFO_OFFSET 0x1c
#define RGA2_SRC_X_FACTOR_OFFSET 0x20
#define RGA2_SRC_Y_FACTOR_OFFSET 0x24
#define RGA2_SRC_BG_COLOR_OFFSET 0x28
#define RGA2_SRC_FG_COLOR_OFFSET 0x2c
#define RGA2_SRC_TR_COLOR0_OFFSET 0x30
#define RGA2_CF_GR_A_OFFSET 0x30 // repeat
#define RGA2_SRC_TR_COLOR1_OFFSET 0x34
#define RGA2_CF_GR_B_OFFSET 0x34 // repeat
#define RGA2_DST_INFO_OFFSET 0x38
#define RGA2_DST_BASE0_OFFSET 0x3c
#define RGA2_DST_BASE1_OFFSET 0x40
#define RGA2_DST_BASE2_OFFSET 0x44
#define RGA2_DST_VIR_INFO_OFFSET 0x48
#define RGA2_DST_ACT_INFO_OFFSET 0x4c
#define RGA2_ALPHA_CTRL0_OFFSET 0x50
#define RGA2_ALPHA_CTRL1_OFFSET 0x54
#define RGA2_FADING_CTRL_OFFSET 0x58
#define RGA2_PAT_CON_OFFSET 0x5c
#define RGA2_ROP_CTRL0_OFFSET 0x60
#define RGA2_CF_GR_G_OFFSET 0x60 // repeat
#define RGA2_DST_Y4MAP_LUT0_OFFSET 0x60 // repeat
#define RGA2_DST_QUANTIZE_SCALE_OFFSET 0x60 // repeat
#define RGA2_ROP_CTRL1_OFFSET 0x64
#define RGA2_CF_GR_R_OFFSET 0x64 // repeat
#define RGA2_DST_Y4MAP_LUT1_OFFSET 0x64 // repeat
#define RGA2_DST_QUANTIZE_OFFSET_OFFSET 0x64 // repeat
#define RGA2_MASK_BASE_OFFSET 0x68
#define RGA2_MMU_CTRL1_OFFSET 0x6c
#define RGA2_MMU_SRC_BASE_OFFSET 0x70
#define RGA2_MMU_SRC1_BASE_OFFSET 0x74
#define RGA2_MMU_DST_BASE_OFFSET 0x78
#define RGA2_MMU_ELS_BASE_OFFSET 0x7c
int rga2_gen_reg_info(unsigned char *base,
unsigned char *csc_base, struct rga2_req *msg);
void rga_cmd_to_rga2_cmd(struct rga_req *req_rga, struct rga2_req *req);
void rga2_soft_reset(struct rga_scheduler_t *scheduler);
int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler);
int rga2_init_reg(struct rga_job *job);
int rga2_get_version(struct rga_scheduler_t *scheduler);
#endif

View File

@@ -0,0 +1,450 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __REG3_INFO_H__
#define __REG3_INFO_H__
#include "rga_drv.h"
//General Registers
/* yqw: status和int寄存器尚不明了无法进行修改。 */
//#define RGA2_STATUS 0x00c
//#define RGA2_INT 0x010
#define RGA3_SYS_CTRL 0x000
#define RGA3_CMD_CTRL 0x004
#define RGA3_CMD_ADDR 0x008
#define RGA3_MI_GROUP_CTRL 0x00c
#define RGA3_ARQOS_CTRL 0x010
#define RGA3_VERSION_NUM 0x018
#define RGA3_VERSION_TIM 0x01c
#define RGA3_INT_EN 0x020
#define RGA3_INT_RAW 0x024
#define RGA3_INT_MSK 0x028
#define RGA3_INT_CLR 0x02c
#define RGA3_RO_SRST 0x030
#define RGA3_STATUS0 0x034
#define RGA3_SCAN_CNT 0x038
#define RGA3_STATUS1 0x03c
#define RGA3_CMD_STATE 0x040
/* TODO: RGA_INT */
/* RGA3_WIN0_RD_CTRL */
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_ENABLE (0x1 << 0)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_RD_MODE (0x3 << 1)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_PIC_FORMAT (0xf << 4)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_RD_FORMAT (0x3 << 8)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_YUV10B_COMPACT (0x1 << 10)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_ENDIAN_MODE (0x1 << 11)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_PIX_SWAP (0x1 << 12)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_YC_SWAP (0x1 << 13)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_ROT (0x1 << 16)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_XMIRROR (0x1 << 17)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_YMIRROR (0x1 << 18)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_HOR_BY (0x1 << 20)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_HOR_UP (0x1 << 21)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_VER_BY (0x1 << 22)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_VER_UP (0x1 << 23)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_Y2R_EN (0x1 << 24)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_R2Y_EN (0x1 << 25)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_CSC_MODE (0x3 << 26)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_PERF_OPT_DIS (0x1 << 29)
#define m_RGA3_WIN0_RD_CTRL_SW_WIN0_RD_ALIGN_DIS (0x1 << 30)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_ENABLE(x) ((x & 0x1) << 0)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_RD_MODE(x) ((x & 0x3) << 1)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_PIC_FORMAT(x) ((x & 0xf) << 4)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_RD_FORMAT(x) ((x & 0x3) << 8)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_YUV10B_COMPACT(x) ((x & 0x1) << 10)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_ENDIAN_MODE(x) ((x & 0x1) << 11)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_PIX_SWAP(x) ((x & 0x1) << 12)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_YC_SWAP(x) ((x & 0x1) << 13)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_ROT(x) ((x & 0x1) << 16)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_XMIRROR(x) ((x & 0x1) << 17)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_YMIRROR(x) ((x & 0x1) << 18)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_HOR_BY(x) ((x & 0x1) << 20)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_HOR_UP(x) ((x & 0x1) << 21)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_VER_BY(x) ((x & 0x1) << 22)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_VER_UP(x) ((x & 0x1) << 23)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_Y2R_EN(x) ((x & 0x1) << 24)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_R2Y_EN(x) ((x & 0x1) << 25)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_CSC_MODE(x) ((x & 0x3) << 26)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_PERF_OPT_DIS(x) ((x & 0x1) << 29)
#define s_RGA3_WIN0_RD_CTRL_SW_WIN0_RD_ALIGN_DIS(x) ((x & 0x1) << 30)
/* RGA3_WIN0_FBC_OFF */
#define m_RGA3_WIN0_FBC_OFF_SW_WIN0_FBC_XOFF (0x1fff << 0)
#define m_RGA3_WIN0_FBC_OFF_SW_WIN0_FBC_YOFF (0x1fff << 16)
#define s_RGA3_WIN0_FBC_OFF_SW_WIN0_FBC_XOFF(x) ((x & 0x1fff) << 0)
#define s_RGA3_WIN0_FBC_OFF_SW_WIN0_FBC_YOFF(x) ((x & 0x1fff) << 16)
/* RGA3_WIN0_SRC_SIZE */
#define m_RGA3_WIN0_SRC_SIZE_SW_WIN0_SRC_WIDTH (0x1fff << 0)
#define m_RGA3_WIN0_SRC_SIZE_SW_WIN0_SRC_HEIGHT (0x1fff << 16)
#define s_RGA3_WIN0_SRC_OFF_SW_WIN0_SRC_WIDTH(x) ((x & 0x1fff) << 0)
#define s_RGA3_WIN0_SRC_OFF_SW_WIN0_SRC_HEIGHT(x) ((x & 0x1fff) << 16)
/* RGA3_WIN0_ACT_OFF */
#define m_RGA3_WIN0_ACT_OFF_SW_WIN0_ACT_XOFF (0x1fff << 0)
#define m_RGA3_WIN0_ACT_OFF_SW_WIN0_ACT_YOFF (0x1fff << 16)
#define s_RGA3_WIN0_ACT_OFF_SW_WIN0_ACT_XOFF(x) ((x & 0x1fff) << 0)
#define s_RGA3_WIN0_ACT_OFF_SW_WIN0_ACT_YOFF(x) ((x & 0x1fff) << 16)
/* RGA3_WIN0_ACT_SIZE */
#define m_RGA3_WIN0_ACT_SIZE_SW_WIN0_ACT_WIDTH (0x1fff << 0)
#define m_RGA3_WIN0_ACT_SIZE_SW_WIN0_ACT_HEIGHT (0x1fff << 16)
#define s_RGA3_WIN0_ACT_SIZE_SW_WIN0_ACT_WIDTH(x) ((x & 0x1fff) << 0)
#define s_RGA3_WIN0_ACT_SIZE_SW_WIN0_ACT_HEIGHT(x) ((x & 0x1fff) << 16)
/* RGA3_WIN0_DST_SIZE */
#define m_RGA3_WIN0_DST_SIZE_SW_WIN0_DST_WIDTH (0x1fff << 0)
#define m_RGA3_WIN0_DST_SIZE_SW_WIN0_DST_HEIGHT (0x1fff << 16)
#define s_RGA3_WIN0_DST_SIZE_SW_WIN0_DST_WIDTH(x) ((x & 0x1fff) << 0)
#define s_RGA3_WIN0_DST_SIZE_SW_WIN0_DST_HEIGHT(x) ((x & 0x1fff) << 16)
/* RGA3_WIN0_SCL_FAC */
#define m_RGA3_WIN0_SCL_FAC_SW_WIN0_VER_FAC (0xffff << 0)
#define m_RGA3_WIN0_SCL_FAC_SW_WIN0_HOR_FAC (0xffff << 16)
#define s_RGA3_WIN0_SCL_FAC_SW_WIN0_VER_FAC(x) ((x & 0xffff) << 0)
#define s_RGA3_WIN0_SCL_FAC_SW_WIN0_HOR_FAC(x) ((x & 0xffff) << 16)
/* RGA3_WIN1_RD_CTRL */
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_ENABLE (0x1 << 0)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_RD_MODE (0x3 << 1)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_PIC_FORMAT (0xf << 4)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_RD_FORMAT (0x3 << 8)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_YUV10B_COMPACT (0x1 << 10)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_ENDIAN_MODE (0x1 << 11)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_PIX_SWAP (0x1 << 12)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_YC_SWAP (0x1 << 13)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_ROT (0x1 << 16)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_XMIRROR (0x1 << 17)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_YMIRROR (0x1 << 18)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_HOR_BY (0x1 << 20)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_HOR_UP (0x1 << 21)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_VER_BY (0x1 << 22)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_VER_UP (0x1 << 23)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_Y2R_EN (0x1 << 24)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_R2Y_EN (0x1 << 25)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_CSC_MODE (0x3 << 26)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_PERF_OPT_DIS (0x1 << 29)
#define m_RGA3_WIN1_RD_CTRL_SW_WIN1_RD_ALIGN_DIS (0x1 << 30)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_ENABLE(x) ((x & 0x1) << 0)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_RD_MODE(x) ((x & 0x3) << 1)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_PIC_FORMAT(x) ((x & 0xf) << 4)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_RD_FORMAT(x) ((x & 0x3) << 8)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_YUV10B_COMPACT(x) ((x & 0x1) << 10)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_ENDIAN_MODE(x) ((x & 0x1) << 11)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_PIX_SWAP(x) ((x & 0x1) << 12)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_YC_SWAP(x) ((x & 0x1) << 13)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_ROT(x) ((x & 0x1) << 16)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_XMIRROR(x) ((x & 0x1) << 17)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_YMIRROR(x) ((x & 0x1) << 18)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_HOR_BY(x) ((x & 0x1) << 20)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_HOR_UP(x) ((x & 0x1) << 21)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_VER_BY(x) ((x & 0x1) << 22)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_VER_UP(x) ((x & 0x1) << 23)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_Y2R_EN(x) ((x & 0x1) << 24)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_R2Y_EN(x) ((x & 0x1) << 25)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_CSC_MODE(x) ((x & 0x3) << 26)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_PERF_OPT_DIS(x) ((x & 0x1) << 29)
#define s_RGA3_WIN1_RD_CTRL_SW_WIN1_RD_ALIGN_DIS(x) ((x & 0x1) << 30)
/* RGA3_WIN1_FBC_OFF */
#define m_RGA3_WIN1_FBC_OFF_SW_WIN1_FBC_XOFF (0x1fff << 0)
#define m_RGA3_WIN1_FBC_OFF_SW_WIN1_FBC_YOFF (0x1fff << 16)
#define s_RGA3_WIN1_FBC_OFF_SW_WIN1_FBC_XOFF(x) ((x & 0x1fff) << 0)
#define s_RGA3_WIN1_FBC_OFF_SW_WIN1_FBC_YOFF(x) ((x & 0x1fff) << 16)
/* RGA3_WIN1_SRC_SIZE */
#define m_RGA3_WIN1_SRC_SIZE_SW_WIN1_SRC_WIDTH (0x1fff << 0)
#define m_RGA3_WIN1_SRC_SIZE_SW_WIN1_SRC_HEIGHT (0x1fff << 16)
#define s_RGA3_WIN1_SRC_OFF_SW_WIN1_SRC_WIDTH(x) ((x & 0x1fff) << 0)
#define s_RGA3_WIN1_SRC_OFF_SW_WIN1_SRC_HEIGHT(x) ((x & 0x1fff) << 16)
/* RGA3_WIN1_ACT_OFF */
#define m_RGA3_WIN1_ACT_OFF_SW_WIN1_ACT_XOFF (0x1fff << 0)
#define m_RGA3_WIN1_ACT_OFF_SW_WIN1_ACT_YOFF (0x1fff << 16)
#define s_RGA3_WIN1_ACT_OFF_SW_WIN1_ACT_XOFF(x) ((x & 0x1fff) << 0)
#define s_RGA3_WIN1_ACT_OFF_SW_WIN1_ACT_YOFF(x) ((x & 0x1fff) << 16)
/* RGA3_WIN1_ACT_SIZE */
#define m_RGA3_WIN1_ACT_SIZE_SW_WIN1_ACT_WIDTH (0x1fff << 0)
#define m_RGA3_WIN1_ACT_SIZE_SW_WIN1_ACT_HEIGHT (0x1fff << 16)
#define s_RGA3_WIN1_ACT_SIZE_SW_WIN1_ACT_WIDTH(x) ((x & 0x1fff) << 0)
#define s_RGA3_WIN1_ACT_SIZE_SW_WIN1_ACT_HEIGHT(x) ((x & 0x1fff) << 16)
/* RGA3_WIN1_DST_SIZE */
#define m_RGA3_WIN1_DST_SIZE_SW_WIN1_DST_WIDTH (0x1fff << 0)
#define m_RGA3_WIN1_DST_SIZE_SW_WIN1_DST_HEIGHT (0x1fff << 16)
#define s_RGA3_WIN1_DST_SIZE_SW_WIN1_DST_WIDTH(x) ((x & 0x1fff) << 0)
#define s_RGA3_WIN1_DST_SIZE_SW_WIN1_DST_HEIGHT(x) ((x & 0x1fff) << 16)
/* RGA3_WIN1_SCL_FAC */
#define m_RGA3_WIN1_SCL_FAC_SW_WIN1_VER_FAC (0xffff << 0)
#define m_RGA3_WIN1_SCL_FAC_SW_WIN1_HOR_FAC (0xffff << 16)
#define s_RGA3_WIN1_SCL_FAC_SW_WIN1_VER_FAC(x) ((x & 0xffff) << 0)
#define s_RGA3_WIN1_SCL_FAC_SW_WIN1_HOR_FAC(x) ((x & 0xffff) << 16)
/* RGA3_OVLP_CTRL */
#define m_RGA3_OVLP_CTRL_SW_OVLP_MODE (0x3 << 0)
#define m_RGA3_OVLP_CTRL_SW_OVLP_FIELD (0x1 << 2)
#define m_RGA3_OVLP_CTRL_SW_TOP_SWAP (0x1 << 3)
#define m_RGA3_OVLP_CTRL_SW_TOP_ALPHA_EN (0x1 << 4)
#define m_RGA3_OVLP_CTRL_SW_TOP_KEY_EN (0x7FFF << 5)
#define m_RGA3_OVLP_CTRL_SW_OVLP_Y2R_EN (0x1 << 20)
#define m_RGA3_OVLP_CTRL_SW_OVLP_R2Y_EN (0x1 << 21)
#define m_RGA3_OVLP_CTRL_SW_OVLP_CSC_MODE (0x3 << 22)
#define s_RGA3_OVLP_CTRL_SW_OVLP_MODE(x) ((x & 0x3) << 0)
#define s_RGA3_OVLP_CTRL_SW_OVLP_FIELD(x) ((x & 0x1) << 2)
#define s_RGA3_OVLP_CTRL_SW_TOP_SWAP(x) ((x & 0x1) << 3)
#define s_RGA3_OVLP_CTRL_SW_TOP_ALPHA_EN(x) ((x & 0x1) << 4)
#define s_RGA3_OVLP_CTRL_SW_TOP_KEY_EN(x) ((x & 0x7FFF) << 5)
#define s_RGA3_OVLP_CTRL_SW_OVLP_Y2R_EN(x) ((x & 0x1) << 20)
#define s_RGA3_OVLP_CTRL_SW_OVLP_R2Y_EN(x) ((x & 0x1) << 21)
#define s_RGA3_OVLP_CTRL_SW_OVLP_CSC_MODE(x) ((x & 0x3) << 22)
/* RGA3_OVLP_OFF */
#define m_RGA3_OVLP_OFF_SW_OVLP_XOFF (0x1fff << 0)
#define m_RGA3_OVLP_OFF_SW_OVLP_YOFF (0x1fff << 16)
#define s_RGA3_OVLP_OFF_SW_OVLP_XOFF(x) ((x & 0x1fff) << 0)
#define s_RGA3_OVLP_OFF_SW_OVLP_YOFF(x) ((x & 0x1fff) << 16)
/* RGA3_OVLP_TOP_KEY_MIN */
#define m_RGA3_OVLP_TOP_KEY_MIN_SW_TOP_KEY_YG_MIN (0x3ff << 0)
#define m_RGA3_OVLP_TOP_KEY_MIN_SW_TOP_KEY_UB_MIN (0x3ff << 10)
#define m_RGA3_OVLP_TOP_KEY_MIN_SW_TOP_KEY_VR_MIN (0x3ff << 20)
#define s_RGA3_OVLP_TOP_KEY_MIN_SW_TOP_KEY_YG_MIN(x) ((x & 0x3f)f << 0)
#define s_RGA3_OVLP_TOP_KEY_MIN_SW_TOP_KEY_UB_MIN(x) ((x & 0x3ff) << 10)
#define s_RGA3_OVLP_TOP_KEY_MIN_SW_TOP_KEY_VR_MIN(x) ((x & 0x3ff) << 20)
/* RGA3_OVLP_TOP_KEY_MAX */
#define m_RGA3_OVLP_TOP_KEY_MAX_SW_TOP_KEY_YG_MAX (0x3ff << 0)
#define m_RGA3_OVLP_TOP_KEY_MAX_SW_TOP_KEY_UB_MAX (0x3ff << 10)
#define m_RGA3_OVLP_TOP_KEY_MAX_SW_TOP_KEY_VR_MAX (0x3ff << 20)
#define s_RGA3_OVLP_TOP_KEY_MAX_SW_TOP_KEY_YG_MAX(x) ((x & 0x3ff) << 0)
#define s_RGA3_OVLP_TOP_KEY_MAX_SW_TOP_KEY_UB_MAX(x) ((x & 0x3ff) << 10)
#define s_RGA3_OVLP_TOP_KEY_MAX_SW_TOP_KEY_VR_MAX(x) ((x & 0x3ff) << 20)
/* RGA3_OVLP_TOP_CTRL */
#define m_RGA3_OVLP_TOP_CTRL_SW_TOP_COLOR_M0 (0x1 << 0)
#define m_RGA3_OVLP_TOP_CTRL_SW_TOP_ALPHA_M0 (0x1 << 1)
#define m_RGA3_OVLP_TOP_CTRL_SW_TOP_BLEND_M0 (0x3 << 2)
#define m_RGA3_OVLP_TOP_CTRL_SW_TOP_ALPHA_CAL_M0 (0x1 << 4)
#define m_RGA3_OVLP_TOP_CTRL_SW_TOP_FACTOR_M0 (0x7 << 5)
#define m_RGA3_OVLP_TOP_CTRL_SW_TOP_GLOBAL_ALPHA (0xff << 16)
#define s_RGA3_OVLP_TOP_CTRL_SW_TOP_COLOR_M0(x) ((x & 0x1) << 0)
#define s_RGA3_OVLP_TOP_CTRL_SW_TOP_ALPHA_M0(x) ((x & 0x1) << 1)
#define s_RGA3_OVLP_TOP_CTRL_SW_TOP_BLEND_M0(x) ((x & 0x3) << 2)
#define s_RGA3_OVLP_TOP_CTRL_SW_TOP_ALPHA_CAL_M0(x) ((x & 0x1) << 4)
#define s_RGA3_OVLP_TOP_CTRL_SW_TOP_FACTOR_M0(x) ((x & 0x7) << 5)
#define s_RGA3_OVLP_TOP_CTRL_SW_TOP_GLOBAL_ALPHA(x) ((x & 0xff) << 16)
/* RGA3_OVLP_BOT_CTRL */
#define m_RGA3_OVLP_BOT_CTRL_SW_BOT_COLOR_M0 (0x1 << 0)
#define m_RGA3_OVLP_BOT_CTRL_SW_BOT_ALPHA_M0 (0x1 << 1)
#define m_RGA3_OVLP_BOT_CTRL_SW_BOT_BLEND_M0 (0x3 << 2)
#define m_RGA3_OVLP_BOT_CTRL_SW_BOT_ALPHA_CAL_M0 (0x1 << 4)
#define m_RGA3_OVLP_BOT_CTRL_SW_BOT_FACTOR_M0 (0x7 << 5)
#define m_RGA3_OVLP_BOT_CTRL_SW_BOT_GLOBAL_ALPHA (0xff << 16)
#define s_RGA3_OVLP_BOT_CTRL_SW_BOT_COLOR_M0(x) ((x & 0x1) << 0)
#define s_RGA3_OVLP_BOT_CTRL_SW_BOT_ALPHA_M0(x) ((x & 0x1) << 1)
#define s_RGA3_OVLP_BOT_CTRL_SW_BOT_BLEND_M0(x) ((x & 0x3) << 2)
#define s_RGA3_OVLP_BOT_CTRL_SW_BOT_ALPHA_CAL_M0(x) ((x & 0x1) << 4)
#define s_RGA3_OVLP_BOT_CTRL_SW_BOT_FACTOR_M0(x) ((x & 0x7) << 5)
#define s_RGA3_OVLP_BOT_CTRL_SW_BOT_GLOBAL_ALPHA(x) ((x & 0xff) << 16)
/* RGA3_OVLP_TOP_ALPHA */
#define m_RGA3_OVLP_TOP_ALPHA_SW_TOP_ALPHA_M1 (0x1 << 1)
#define m_RGA3_OVLP_TOP_ALPHA_SW_TOP_BLEND_M1 (0x3 << 2)
#define m_RGA3_OVLP_TOP_ALPHA_SW_TOP_ALPHA_CAL_M1 (0x1 << 4)
#define m_RGA3_OVLP_TOP_ALPHA_SW_TOP_FACTOR_M1 (0x7 << 5)
#define s_RGA3_OVLP_TOP_ALPHA_SW_TOP_ALPHA_M1(x) ((x & 0x1) << 1)
#define s_RGA3_OVLP_TOP_ALPHA_SW_TOP_BLEND_M1(x) ((x & 0x3) << 2)
#define s_RGA3_OVLP_TOP_ALPHA_SW_TOP_ALPHA_CAL_M1(x) ((x & 0x1) << 4)
#define s_RGA3_OVLP_TOP_ALPHA_SW_TOP_FACTOR_M1(x) ((x & 0x7) << 5)
/* RGA3_OVLP_BOT_ALPHA */
#define m_RGA3_OVLP_BOT_ALPHA_SW_BOT_ALPHA_M1 (0x1 << 1)
#define m_RGA3_OVLP_BOT_ALPHA_SW_BOT_BLEND_M1 (0x3 << 2)
#define m_RGA3_OVLP_BOT_ALPHA_SW_BOT_ALPHA_CAL_M1 (0x1 << 4)
#define m_RGA3_OVLP_BOT_ALPHA_SW_BOT_FACTOR_M1 (0x7 << 5)
#define s_RGA3_OVLP_BOT_ALPHA_SW_BOT_ALPHA_M1(x) ((x & 0x1) << 1)
#define s_RGA3_OVLP_BOT_ALPHA_SW_BOT_BLEND_M1(x) ((x & 0x3) << 2)
#define s_RGA3_OVLP_BOT_ALPHA_SW_BOT_ALPHA_CAL_M1(x) ((x & 0x1) << 4)
#define s_RGA3_OVLP_BOT_ALPHA_SW_BOT_FACTOR_M1(x) ((x & 0x7) << 5)
/* RGA3_WR_CTRL */
#define m_RGA3_WR_CTRL_SW_WR_MODE (0x3 << 0)
#define m_RGA3_WR_CTRL_SW_WR_FBCE_SPARSE_EN (0x1 << 2)
#define m_RGA3_WR_CTRL_SW_WR_PIC_FORMAT (0xf << 4)
#define m_RGA3_WR_CTRL_SW_WR_FORMAT (0x3 << 8)
#define m_RGA3_WR_CTRL_SW_WR_YUV10B_COMPACT (0x1 << 10)
#define m_RGA3_WR_CTRL_SW_WR_ENDIAN_MODE (0x1 << 11)
#define m_RGA3_WR_CTRL_SW_WR_PIX_SWAP (0x1 << 12)
#define m_RGA3_WR_CTRL_SW_OUTSTANDING_MAX (0x3f << 13)
#define m_RGA3_WR_CTRL_SW_WR_YC_SWAP (0x1 << 20)
#define s_RGA3_WR_CTRL_SW_WR_MODE(x) ((x & 0x3) << 0)
#define s_RGA3_WR_CTRL_SW_WR_FBCE_SPARSE_EN(x) ((x & 0x1) << 2)
#define s_RGA3_WR_CTRL_SW_WR_PIC_FORMAT(x) ((x & 0xf) << 4)
#define s_RGA3_WR_CTRL_SW_WR_FORMAT(x) ((x & 0x3) << 8)
#define s_RGA3_WR_CTRL_SW_WR_YUV10B_COMPACT(x) ((x & 0x1) << 10)
#define s_RGA3_WR_CTRL_SW_WR_ENDIAN_MODE(x) ((x & 0x1) << 11)
#define s_RGA3_WR_CTRL_SW_WR_PIX_SWAP(x) ((x & 0x1) << 12)
#define s_RGA3_WR_CTRL_SW_OUTSTANDING_MAX(x) ((x & 0x3f) << 13)
#define s_RGA3_WR_CTRL_SW_WR_YC_SWAP(x) ((x & 0x1) << 20)
/* RGA3_WR_FBCE_CTRL */
#define m_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_BLKBD_OPT_DIS (0x1 << 0)
#define m_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_HOFF_DISS (0x1 << 1)
#define m_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_PL_FIFO0_WATERMARK (0x3f << 2)
#define m_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_PL_FIFO1_WATERMARK (0x3f << 8)
#define m_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_SIZE_ALIGN_DIS (0x1 << 31)
#define s_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_BLKBD_OPT_DIS(x) ((x & 0x1) << 0)
#define s_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_HOFF_DISS(x) ((x & 0x1) << 1)
#define s_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_PL_FIFO0_WATERMARK(x) ((x & 0x3f) << 2)
#define s_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_PL_FIFO1_WATERMARK(x) ((x & 0x3f) << 8)
#define s_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_SIZE_ALIGN_DIS(x) ((x & 0x1) << 31)
/* RGA3_MMU_STATUS read_only */
#define m_RGA3_MMU_STATUS_PAGING_ENABLED (0x1 << 0)
#define m_RGA3_MMU_STATUS_PAGE_FAULT_ACTIVE (0x1 << 1)
#define m_RGA3_MMU_STATUS_STAIL_ACTIVE (0x1 << 2)
#define m_RGA3_MMU_STATUS_MMU_IDLE (0x1 << 3)
#define m_RGA3_MMU_STATUS_REPLAY_BUFFER_EMPTY (0x1 << 4)
#define m_RGA3_MMU_STATUS_PAGE_FAULT_IS_WRITE (0x1 << 5)
#define m_RGA3_MMU_STATUS_PAGE_FAULT_BUS_ID (0x1f << 6)
/* RGA3_MMU_INT_RAWSTAT read_only */
#define m_RGA3_MMU_INT_RAWSTAT_READ_BUS_ERROR (0x1 << 0)
#define m_RGA3_MMU_INT_RAWSTAT_PAGE_FAULT (0x1 << 1)
/* RGA3_MMU_INT_CLEAR write_only */
#define m_RGA3_MMU_INT_CLEAR_READ_BUS_ERROR (0x1 << 0)
#define m_RGA3_MMU_INT_CLEAR_PAGE_FAULT (0x1 << 1)
#define s_RGA3_MMU_INT_CLEAR_READ_BUS_ERROR(x) ((x & 0x1) << 0)
#define s_RGA3_MMU_INT_CLEAR_PAGE_FAULT(x) ((x & 0x1) << 1)
/* RGA3_MMU_INT_MASK */
#define m_RGA3_MMU_INT_MASK_READ_BUS_ERROR (0x1 << 0)
#define m_RGA3_MMU_INT_MASK_PAGE_FAULT (0x1 << 1)
#define s_RGA3_MMU_INT_MASK_READ_BUS_ERROR(x) ((x & 0x1) << 0)
#define s_RGA3_MMU_INT_MASK_PAGE_FAULT(x) ((x & 0x1) << 1)
/* RGA3_MMU_INT_STATUS read_only */
#define m_RGA3_MMU_INT_STATUS_READ_BUS_ERROR (0x1 << 0)
#define m_RGA3_MMU_INT_STATUS_PAGE_FAULT (0x1 << 1)
/* RGA3_MMU_AUTO_GATING */
#define m_RGA3_MMU_AUTO_GATING_MMU_AUTO_GATING (0x1 << 1)
#define m_RGA3_MMU_AUTO_GATING_MMU_CFG_MODE (0x1 << 1)
#define m_RGA3_MMU_AUTO_GATING_MMU_BUG_FIXED_DISABLE (0x1 << 31)
#define s_RGA3_MMU_AUTO_GATING_MMU_AUTO_GATING(x) ((x & 0x1) << 1)
#define s_RGA3_MMU_AUTO_GATING_MMU_BUG_FIXED_DISABLE(x) ((x & 0x1) << 31)
/* sys_reg */
#define RGA3_SYS_CTRL_OFFSET 0x000
#define RGA3_CMD_CTRL_OFFSET 0x004
#define RGA3_CMD_ADDR_OFFSET 0x008
#define RGA3_MI_GROUP_CTRL_OFFSET 0x00c
#define RGA3_ARQOS_CTRL_OFFSET 0x010
#define RGA3_VERSION_NUM_OFFSET 0x018
#define RGA3_VERSION_TIM_OFFSET 0x01c
#define RGA3_INT_EN_OFFSET 0x020
#define RGA3_INT_RAW_OFFSET 0x024
#define RGA3_INT_MSK_OFFSET 0x028
#define RGA3_INT_CLR_OFFSET 0x02c
#define RGA3_RO_SRST_OFFSET 0x030
#define RGA3_STATUS0_OFFSET 0x034
#define RGA3_SCAN_CNT_OFFSET 0x038
#define RGA3_STATUS1_OFFSET 0x03c
#define RGA3_CMD_STATE_OFFSET 0x040
/* op_reg */
#define RGA3_WIN0_RD_CTRL_OFFSET 0x000
#define RGA3_WIN0_Y_BASE_OFFSET 0x010
#define RGA3_WIN0_U_BASE_OFFSET 0x014
#define RGA3_WIN0_V_BASE_OFFSET 0x018
#define RGA3_WIN0_VIR_STRIDE_OFFSET 0x01c
#define RGA3_WIN0_FBC_OFF_OFFSET 0x020
#define RGA3_WIN0_SRC_SIZE_OFFSET 0x024
#define RGA3_WIN0_ACT_OFF_OFFSET 0x028
#define RGA3_WIN0_ACT_SIZE_OFFSET 0x02c
#define RGA3_WIN0_DST_SIZE_OFFSET 0x030
#define RGA3_WIN0_SCL_FAC_OFFSET 0x034
#define RGA3_WIN0_UV_VIR_STRIDE_OFFSET 0x038
#define RGA3_WIN1_RD_CTRL_OFFSET 0x040
#define RGA3_WIN1_Y_BASE_OFFSET 0x050
#define RGA3_WIN1_U_BASE_OFFSET 0x054
#define RGA3_WIN1_V_BASE_OFFSET 0x058
#define RGA3_WIN1_VIR_STRIDE_OFFSET 0x05c
#define RGA3_WIN1_FBC_OFF_OFFSET 0x060
#define RGA3_WIN1_SRC_SIZE_OFFSET 0x064
#define RGA3_WIN1_ACT_OFF_OFFSET 0x068
#define RGA3_WIN1_ACT_SIZE_OFFSET 0x06c
#define RGA3_WIN1_DST_SIZE_OFFSET 0x070
#define RGA3_WIN1_SCL_FAC_OFFSET 0x074
#define RGA3_WIN1_UV_VIR_STRIDE_OFFSET 0x078
#define RGA3_OVLP_CTRL_OFFSET 0x080
#define RGA3_OVLP_OFF_OFFSET 0x084
#define RGA3_OVLP_TOP_KEY_MIN_OFFSET 0x088
#define RGA3_OVLP_TOP_KEY_MAX_OFFSET 0x08c
#define RGA3_OVLP_TOP_CTRL_OFFSET 0x090
#define RGA3_OVLP_BOT_CTRL_OFFSET 0x094
#define RGA3_OVLP_TOP_ALPHA_OFFSET 0x098
#define RGA3_OVLP_BOT_ALPHA_OFFSET 0x09c
#define RGA3_WR_CTRL_OFFSET 0x0a0
#define RGA3_WR_FBCE_CTRL_OFFSET 0x0a4
#define RGA3_WR_VIR_STRIDE_OFFSET 0x0a8
#define RGA3_WR_PL_VIR_STRIDE_OFFSET 0x0ac
#define RGA3_WR_Y_BASE_OFFSET 0x0b0
#define RGA3_WR_U_BASE_OFFSET 0x0b4
#define RGA3_WR_V_BASE_OFFSET 0x0b8
#define RGA3_MMU_DTE_ADDR_OFFSET 0x0f00
#define RGA3_MMU_STATUS_OFFSET 0x0f04
#define RGA3_MMU_COMMAND_OFFSET 0x0f08
#define RGA3_MMU_PAGE_FAULT_ADDR_OFFSET 0x0f0c
#define RGA3_MMU_ZAP_ONE_LINE_OFFSET 0x0f10
#define RGA3_MMU_INT_RAWSTAT_OFFSET 0x0f14
#define RGA3_MMU_INT_CLEAR_OFFSET 0x0f18
#define RGA3_MMU_INT_MASK_OFFSET 0x0f1c
#define RGA3_MMU_INT_STATUS_OFFSET 0x0f20
#define RGA3_MMU_AUTO_GATING_OFFSET 0x0f24
#define RGA3_MMU_REG_LOAD_EN_OFFSET 0x0f28
int rga3_gen_reg_info(unsigned char *base, struct rga3_req *msg);
void rga_cmd_to_rga3_cmd(struct rga_req *req_rga, struct rga3_req *req);
//void RGA_MSG_2_RGA3_MSG_32(struct rga_req_32 *req_rga, struct rga3_req *req);
void rga3_soft_reset(struct rga_scheduler_t *scheduler);
int rga3_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler);
int rga3_init_reg(struct rga_job *job);
int rga3_get_version(struct rga_scheduler_t *scheduler);
#endif

View File

@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author:
* Cerf Yu <cerf.yu@rock-chips.com>
*/
#ifndef __LINUX_RKRGA_COMMON_H_
#define __LINUX_RKRGA_COMMON_H_
void rga_user_format_convert(uint32_t *df, uint32_t sf);
bool rga_is_yuv422p_format(u32 format);
void rga_convert_addr(struct rga_img_info_t *img, bool before_vir_get_channel);
int rga_get_format_bits(u32 format);
#endif

View File

@@ -0,0 +1,133 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author:
* Cerf Yu <cerf.yu@rock-chips.com>
* Huang Lee <Putin.li@rock-chips.com>
*/
#ifndef _RGA_DEBUGGER_H_
#define _RGA_DEBUGGER_H_
#ifdef CONFIG_ROCKCHIP_RGA_DEBUGGER
extern int RGA_DEBUG_REG;
extern int RGA_DEBUG_MSG;
extern int RGA_DEBUG_TIME;
extern int RGA_DEBUG_CHECK_MODE;
extern int RGA_DEBUG_NONUSE;
extern int RGA_DEBUG_INT_FLAG;
#define DEBUGGER_EN(name) (unlikely(RGA_DEBUG_##name ? true : false))
/*
* struct rga_debugger - RGA debugger information
*
* This structure represents a debugger to be created by the rga driver
* or core.
*/
struct rga_debugger {
#ifdef CONFIG_ROCKCHIP_RGA_DEBUG_FS
/* Directory of debugfs file */
struct dentry *debugfs_dir;
struct list_head debugfs_entry_list;
struct mutex debugfs_lock;
#endif
#ifdef CONFIG_ROCKCHIP_RGA_PROC_FS
/* Directory of procfs file */
struct proc_dir_entry *procfs_dir;
struct list_head procfs_entry_list;
struct mutex procfs_lock;
#endif
};
/*
* struct rga_debugger_list - debugfs/procfs info list entry
*
* This structure represents a debugfs/procfs file to be created by the rga
* driver or core.
*/
struct rga_debugger_list {
/* File name */
const char *name;
/*
* Show callback. &seq_file->private will be set to the &struct
* rga_debugger_node corresponding to the instance of this info
* on a given &struct rga_debugger.
*/
int (*show)(struct seq_file *seq, void *data);
/*
* Write callback. &seq_file->private will be set to the &struct
* rga_debugger_node corresponding to the instance of this info
* on a given &struct rga_debugger.
*/
ssize_t (*write)(struct file *file, const char __user *ubuf,
size_t len, loff_t *offp);
/* Procfs/Debugfs private data. */
void *data;
};
/*
* struct rga_debugger_node - Nodes for debugfs/procfs
*
* This structure represents each instance of procfs/debugfs created from the
* template.
*/
struct rga_debugger_node {
struct rga_debugger *debugger;
/* template for this node. */
const struct rga_debugger_list *info_ent;
/* Each Procfs/Debugfs file. */
#ifdef CONFIG_ROCKCHIP_RGA_DEBUG_FS
struct dentry *dent;
#endif
#ifdef CONFIG_ROCKCHIP_RGA_PROC_FS
struct proc_dir_entry *pent;
#endif
struct list_head list;
};
#ifdef CONFIG_ROCKCHIP_RGA_DEBUG_FS
int rga_debugfs_init(void);
int rga_debugfs_remove(void);
#else
static inline int rga_debugfs_remove(void)
{
return 0;
}
static inline int rga_debugfs_init(void)
{
return 0;
}
#endif /* #ifdef CONFIG_ROCKCHIP_RGA_DEBUG_FS */
#ifdef CONFIG_ROCKCHIP_RGA_PROC_FS
int rga_procfs_remove(void);
int rga_procfs_init(void);
#else
static inline int rga_procfs_remove(void)
{
return 0;
}
static inline int rga_procfs_init(void)
{
return 0;
}
#endif /* #ifdef CONFIG_ROCKCHIP_RGA_PROC_FS */
#else
#define DEBUGGER_EN(name) (unlikely(false))
#endif /* #ifdef CONFIG_ROCKCHIP_RGA_DEBUGGER */
void rga_cmd_print_debug_info(struct rga_req *req);
#endif /* #ifndef _RGA_DEBUGGER_H_ */

View File

@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author:
* Cerf Yu <cerf.yu@rock-chips.com>
* Huang Lee <Putin.li@rock-chips.com>
*/
#ifndef __RGA3_DMA_BUF_H__
#define __RGA3_DMA_BUF_H__
#include "rga_drv.h"
int rga_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr,
unsigned long v_addr, int format, uint32_t w,
uint32_t h, unsigned long *StartAddr, unsigned long *size);
int rga_dma_buf_get(struct rga_job *job);
int rga_iommu_map_virt_addr(struct rga_memory_parm *memory_parm,
struct rga_dma_buffer *virt_dma_buf,
struct device *rga_dev,
struct mm_struct *mm);
void rga_iommu_unmap_virt_addr(struct rga_dma_buffer *virt_addr);
int rga_dma_map_fd(int fd, struct rga_dma_buffer *rga_dma_buffer,
enum dma_data_direction dir, struct device *rga_dev);
void rga_dma_unmap_fd(struct rga_dma_buffer *rga_dma_buffer);
int rga_dma_get_info(struct rga_job *job);
void rga_dma_put_info(struct rga_job *job);
#endif /* #ifndef __RGA3_DMA_BUF_H__ */

View File

@@ -0,0 +1,379 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author: Huang Lee <Putin.li@rock-chips.com>
*/
#ifndef __LINUX_RGA_DRV_H_
#define __LINUX_RGA_DRV_H_
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-buf-cache.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/fb.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/poll.h>
#include <linux/regulator/consumer.h>
#include <linux/scatterlist.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/syscalls.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/uaccess.h>
#include <linux/version.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/pm_runtime.h>
#include <linux/sched/mm.h>
#include <asm/cacheflush.h>
#include <linux/iommu.h>
#include <linux/iova.h>
#include <linux/dma-iommu.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
#include <linux/dma-map-ops.h>
#endif
#include <linux/hrtimer.h>
#include "rga.h"
#include "rga_debugger.h"
#define RGA_CORE_REG_OFFSET 0x10000
/* sample interval: 1000ms */
#define RGA_LOAD_INTERVAL 1000000000
#if ((defined(CONFIG_RK_IOMMU) || defined(CONFIG_ROCKCHIP_IOMMU)) \
&& defined(CONFIG_ION_ROCKCHIP))
#define CONFIG_RGA_IOMMU
#endif
/* Driver information */
#define DRIVER_DESC "RGA multicore Device Driver"
#define DRIVER_NAME "rga_multicore"
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define DRIVER_MAJOR_VERISON 1
#define DRIVER_MINOR_VERSION 2
#define DRIVER_REVISION_VERSION 2
#define DRIVER_VERSION (STR(DRIVER_MAJOR_VERISON) "." STR(DRIVER_MINOR_VERSION) \
"." STR(DRIVER_REVISION_VERSION))
/* time limit */
#define RGA_ASYNC_TIMEOUT_DELAY 500
#define RGA_SYNC_TIMEOUT_DELAY HZ
#define RGA_RESET_TIMEOUT 1000
#define RGA_MAX_SCHEDULER 3
#define RGA_MAX_BUS_CLK 10
#define RGA_BUFFER_POOL_MAX_SIZE 64
#ifndef ABS
#define ABS(X) (((X) < 0) ? (-(X)) : (X))
#endif
#ifndef CLIP
#define CLIP(x, a, b) (((x) < (a)) \
? (a) : (((x) > (b)) ? (b) : (x)))
#endif
extern struct rga_drvdata_t *rga_drvdata;
enum {
RGA3_SCHEDULER_CORE0 = 1 << 0,
RGA3_SCHEDULER_CORE1 = 1 << 1,
RGA2_SCHEDULER_CORE0 = 1 << 2,
RGA_CORE_MASK = 0x7,
RGA_NONE_CORE = 0x0,
};
enum iommu_dma_cookie_type {
IOMMU_DMA_IOVA_COOKIE,
IOMMU_DMA_MSI_COOKIE,
};
struct rga_fence_context {
unsigned int context;
unsigned int seqno;
spinlock_t spinlock;
};
struct rga_fence_waiter {
/* Base sync driver waiter structure */
struct dma_fence_cb waiter;
struct rga_job *job;
};
struct rga_iommu_dma_cookie {
enum iommu_dma_cookie_type type;
/* Full allocator for IOMMU_DMA_IOVA_COOKIE */
struct iova_domain iovad;
};
/*
* legacy: Wait for the import process to completely replace the current
* dma_map and remove it
*/
struct rga_dma_buffer_t {
/* DMABUF information */
struct dma_buf *dma_buf;
struct dma_buf_attachment *attach;
struct sg_table *sgt;
dma_addr_t iova;
unsigned long size;
void *vaddr;
enum dma_data_direction dir;
/* It indicates whether the buffer is cached */
bool cached;
struct list_head link;
struct kref refcount;
struct iommu_domain *domain;
struct rga_iommu_dma_cookie *cookie;
/*
* use dma_buf directly,
* do not call dma_buf_put, such as mpi
*/
bool use_dma_buf;
bool use_viraddr;
};
struct rga_dma_buffer {
/* DMABUF information */
struct dma_buf *dma_buf;
struct dma_buf_attachment *attach;
struct sg_table *sgt;
void *vmap_ptr;
struct iommu_domain *domain;
struct rga_iommu_dma_cookie *cookie;
enum dma_data_direction dir;
dma_addr_t iova;
unsigned long size;
/*
* The offset of the first page of the sgt.
* Since alloc iova must be page aligned, the offset of the first page is
* identified separately.
*/
size_t offset;
/* The core of the mapping */
int core;
};
struct rga_virt_addr {
uint64_t addr;
struct page **pages;
int pages_order;
int page_count;
unsigned long size;
/* The offset of the first page of the virtual address */
size_t offset;
int result;
};
struct rga_internal_buffer {
/* DMA buffer */
struct rga_dma_buffer *dma_buffer;
uint32_t dma_buffer_size;
/* virtual address */
struct rga_virt_addr *virt_addr;
/* physical address */
uint64_t phys_addr;
struct rga_memory_parm memory_parm;
struct mm_struct *current_mm;
/* memory type. */
uint32_t type;
uint32_t handle;
uint32_t mm_flag;
struct kref refcount;
};
/*
* yqw add:
* In order to use the virtual address to refresh the cache,
* it may be merged into sgt later.
*/
struct rga2_mmu_other_t {
uint32_t *MMU_src0_base;
uint32_t *MMU_src1_base;
uint32_t *MMU_dst_base;
uint32_t MMU_src0_count;
uint32_t MMU_src1_count;
uint32_t MMU_dst_count;
uint32_t MMU_len;
bool MMU_map;
};
struct rga_job {
struct list_head head;
struct rga_req rga_command_base;
uint32_t cmd_reg[32 * 8];
uint32_t csc_reg[12];
struct rga_dma_buffer_t *rga_dma_buffer_src0;
struct rga_dma_buffer_t *rga_dma_buffer_src1;
struct rga_dma_buffer_t *rga_dma_buffer_dst;
/* used by rga2 */
struct rga_dma_buffer_t *rga_dma_buffer_els;
struct rga_internal_buffer *src_buffer;
struct rga_internal_buffer *src1_buffer;
struct rga_internal_buffer *dst_buffer;
/* used by rga2 */
struct rga_internal_buffer *els_buffer;
struct dma_buf *dma_buf_src0;
struct dma_buf *dma_buf_src1;
struct dma_buf *dma_buf_dst;
struct dma_buf *dma_buf_els;
/* for rga2 virtual_address */
struct mm_struct *mm;
struct rga2_mmu_other_t vir_page_table;
struct dma_fence *out_fence;
struct dma_fence *in_fence;
spinlock_t fence_lock;
ktime_t timestamp;
ktime_t running_time;
unsigned int flags;
int job_id;
int priority;
int core;
int ret;
};
struct rga_scheduler_t;
struct rga_backend_ops {
int (*get_version)(struct rga_scheduler_t *scheduler);
int (*set_reg)(struct rga_job *job, struct rga_scheduler_t *scheduler);
int (*init_reg)(struct rga_job *job);
void (*soft_reset)(struct rga_scheduler_t *scheduler);
};
struct rga_timer {
u32 busy_time;
u32 busy_time_record;
};
struct rga_scheduler_t {
struct device *dev;
void __iomem *rga_base;
struct clk *clks[RGA_MAX_BUS_CLK];
int num_clks;
int pd_refcount;
struct rga_job *running_job;
struct list_head todo_list;
spinlock_t irq_lock;
wait_queue_head_t job_done_wq;
const struct rga_backend_ops *ops;
const struct rga_hw_data *data;
int job_count;
int irq;
struct rga_version_t version;
int core;
struct rga_timer timer;
};
struct rga_drvdata_t {
struct miscdevice miscdev;
struct rga_fence_context *fence_ctx;
/* used by rga2's mmu lock */
struct mutex lock;
struct rga_scheduler_t *rga_scheduler[RGA_MAX_SCHEDULER];
int num_of_scheduler;
struct delayed_work power_off_work;
struct wake_lock wake_lock;
struct rga_mm *mm;
#ifdef CONFIG_ROCKCHIP_RGA_DEBUGGER
struct rga_debugger *debugger;
#endif
};
struct rga_irqs_data_t {
const char *name;
irqreturn_t (*irq_hdl)(int irq, void *ctx);
irqreturn_t (*irq_thread)(int irq, void *ctx);
};
struct rga_match_data_t {
const char * const *clks;
int num_clks;
const struct rga_irqs_data_t *irqs;
int num_irqs;
};
static inline int rga_read(int offset, struct rga_scheduler_t *rga_scheduler)
{
return readl(rga_scheduler->rga_base + offset);
}
static inline void rga_write(int value, int offset, struct rga_scheduler_t *rga_scheduler)
{
writel(value, rga_scheduler->rga_base + offset);
}
int rga_power_enable(struct rga_scheduler_t *rga_scheduler);
int rga_power_disable(struct rga_scheduler_t *rga_scheduler);
#endif /* __LINUX_RGA_FENCE_H_ */

View File

@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author: Huang Lee <Putin.li@rock-chips.com>
*/
#ifndef __LINUX_RGA_FENCE_H_
#define __LINUX_RGA_FENCE_H_
#include "rga_drv.h"
struct rga_fence_context *rga_fence_context_alloc(void);
void rga_fence_context_free(struct rga_fence_context *fence_ctx);
int rga_out_fence_alloc(struct rga_job *job);
int rga_out_fence_get_fd(struct rga_job *job);
struct dma_fence *rga_get_input_fence(int in_fence_fd);
int rga_wait_input_fence(struct dma_fence *in_fence);
int rga_add_dma_fence_callback(struct rga_job *job,
struct dma_fence *in_fence, dma_fence_func_t func);
#endif /* __LINUX_RGA_FENCE_H_ */

View File

@@ -0,0 +1,56 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author: Huang Lee <Putin.li@rock-chips.com>
*/
#ifndef __LINUX_RGA_HW_CONFIG_H_
#define __LINUX_RGA_HW_CONFIG_H_
#include "rga_drv.h"
struct rga_rect {
int w;
int h;
};
struct rga_win_data {
const char *name;
const uint32_t *raster_formats;
const uint32_t *fbc_formats;
const uint32_t *tile_formats;
uint32_t num_of_raster_formats;
uint32_t num_of_fbc_formats;
uint32_t num_of_tile_formats;
const unsigned int supported_rotations;
const unsigned int scale_up_mode;
const unsigned int scale_down_mode;
const unsigned int rd_mode;
};
struct rga_hw_data {
uint32_t version;
uint32_t feature;
uint32_t csc_r2y_mode;
uint32_t csc_y2r_mode;
struct rga_rect max_input;
struct rga_rect max_output;
struct rga_rect min_input;
struct rga_rect min_output;
unsigned int max_upscale_factor;
unsigned int max_downscale_factor;
const struct rga_win_data *win;
unsigned int win_size;
};
extern const struct rga_hw_data rga3_data;
extern const struct rga_hw_data rga2e_data;
#endif /* __LINUX_RGA_HW_CONFIG_H_ */

View File

@@ -0,0 +1,40 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author: Huang Lee <Putin.li@rock-chips.com>
*/
#ifndef __LINUX_RKRGA_JOB_H_
#define __LINUX_RKRGA_JOB_H_
#include <linux/spinlock.h>
#include <linux/dma-fence.h>
#include "rga_drv.h"
enum job_flags {
RGA_JOB_DONE = 1 << 0,
RGA_JOB_ASYNC = 1 << 1,
RGA_JOB_SYNC = 1 << 2,
RGA_JOB_USE_HANDLE = 1 << 3,
RGA_JOB_UNSUPPORT_RGA2 = 1 << 4,
};
struct rga_scheduler_t *rga_job_get_scheduler(int core);
void rga_job_done(struct rga_scheduler_t *rga_scheduler, int ret);
int rga_job_commit(struct rga_req *rga_command_base, int flags);
int rga_job_mpi_commit(struct rga_req *rga_command_base,
struct rga_mpi_job_t *mpi_job, int flags);
int rga_job_assign(struct rga_job *job);
struct rga_job *
rga_scheduler_get_pending_job_list(struct rga_scheduler_t *scheduler);
struct rga_job *
rga_scheduler_get_running_job(struct rga_scheduler_t *scheduler);
#endif /* __LINUX_RKRGA_JOB_H_ */

View File

@@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author:
* Cerf Yu <cerf.yu@rock-chips.com>
*/
#ifndef __LINUX_RKRGA_MM_H_
#define __LINUX_RKRGA_MM_H_
#include "rga_drv.h"
enum memory_flag {
/* It will identify whether the buffer is within 0 ~ 4G. */
RGA_MM_UNDER_4G = 1 << 0,
/* Logo enable IOMMU */
RGA_MM_NEED_USE_IOMMU = 1 << 1,
};
struct rga_mm {
struct mutex lock;
/*
* @memory_idr:
*
* Mapping of memory object handles to object pointers. Used by the GEM
* subsystem. Protected by @memory_lock.
*/
struct idr memory_idr;
/* the count of buffer in the cached_list */
int buffer_count;
};
struct rga_internal_buffer *rga_mm_lookup_handle(struct rga_mm *mm_session, uint32_t handle);
int rga_mm_lookup_flag(struct rga_mm *mm_session, uint64_t handle);
dma_addr_t rga_mm_lookup_iova(struct rga_internal_buffer *buffer, int core);
struct sg_table *rga_mm_lookup_sgt(struct rga_internal_buffer *buffer, int core);
void rga_mm_dump_info(struct rga_mm *session);
int rga_mm_get_handle_info(struct rga_job *job);
void rga_mm_put_handle_info(struct rga_job *job);
uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer);
int rga_mm_release_buffer(uint32_t handle);
int rga_mm_init(struct rga_mm **session);
int rga_mm_remove(struct rga_mm **session);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,262 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author: Cerf Yu <cerf.yu@rock-chips.com>
*/
#define pr_fmt(fmt) "rga_common: " fmt
#include "rga.h"
void rga_user_format_convert(uint32_t *df, uint32_t sf)
{
switch (sf) {
case 0x0:
*df = RGA2_FORMAT_RGBA_8888;
break;
case 0x1:
*df = RGA2_FORMAT_RGBX_8888;
break;
case 0x2:
*df = RGA2_FORMAT_RGB_888;
break;
case 0x3:
*df = RGA2_FORMAT_BGRA_8888;
break;
case 0x4:
*df = RGA2_FORMAT_RGB_565;
break;
case 0x5:
*df = RGA2_FORMAT_RGBA_5551;
break;
case 0x6:
*df = RGA2_FORMAT_RGBA_4444;
break;
case 0x7:
*df = RGA2_FORMAT_BGR_888;
break;
case 0x16:
*df = RGA2_FORMAT_BGRX_8888;
break;
case 0x8:
*df = RGA2_FORMAT_YCbCr_422_SP;
break;
case 0x9:
*df = RGA2_FORMAT_YCbCr_422_P;
break;
case 0xa:
*df = RGA2_FORMAT_YCbCr_420_SP;
break;
case 0xb:
*df = RGA2_FORMAT_YCbCr_420_P;
break;
case 0xc:
*df = RGA2_FORMAT_YCrCb_422_SP;
break;
case 0xd:
*df = RGA2_FORMAT_YCrCb_422_P;
break;
case 0xe:
*df = RGA2_FORMAT_YCrCb_420_SP;
break;
case 0xf:
*df = RGA2_FORMAT_YCrCb_420_P;
break;
case 0x10:
*df = RGA2_FORMAT_BPP_1;
break;
case 0x11:
*df = RGA2_FORMAT_BPP_2;
break;
case 0x12:
*df = RGA2_FORMAT_BPP_4;
break;
case 0x13:
*df = RGA2_FORMAT_BPP_8;
break;
case 0x14:
*df = RGA2_FORMAT_Y4;
break;
case 0x15:
*df = RGA2_FORMAT_YCbCr_400;
break;
case 0x18:
*df = RGA2_FORMAT_YVYU_422;
break;
case 0x19:
*df = RGA2_FORMAT_YVYU_420;
break;
case 0x1a:
*df = RGA2_FORMAT_VYUY_422;
break;
case 0x1b:
*df = RGA2_FORMAT_VYUY_420;
break;
case 0x1c:
*df = RGA2_FORMAT_YUYV_422;
break;
case 0x1d:
*df = RGA2_FORMAT_YUYV_420;
break;
case 0x1e:
*df = RGA2_FORMAT_UYVY_422;
break;
case 0x1f:
*df = RGA2_FORMAT_UYVY_420;
break;
case 0x20:
*df = RGA2_FORMAT_YCbCr_420_SP_10B;
break;
case 0x21:
*df = RGA2_FORMAT_YCrCb_420_SP_10B;
break;
case 0x22:
*df = RGA2_FORMAT_YCbCr_422_SP_10B;
break;
case 0x23:
*df = RGA2_FORMAT_YCrCb_422_SP_10B;
break;
case 0x24:
*df = RGA2_FORMAT_BGR_565;
break;
case 0x25:
*df = RGA2_FORMAT_BGRA_5551;
break;
case 0x26:
*df = RGA2_FORMAT_BGRA_4444;
break;
case 0x28:
*df = RGA2_FORMAT_ARGB_8888;
break;
case 0x29:
*df = RGA2_FORMAT_XRGB_8888;
break;
case 0x2a:
*df = RGA2_FORMAT_ARGB_5551;
break;
case 0x2b:
*df = RGA2_FORMAT_ARGB_4444;
break;
case 0x2c:
*df = RGA2_FORMAT_ABGR_8888;
break;
case 0x2d:
*df = RGA2_FORMAT_XBGR_8888;
break;
case 0x2e:
*df = RGA2_FORMAT_ABGR_5551;
break;
case 0x2f:
*df = RGA2_FORMAT_ABGR_4444;
break;
}
}
bool rga_is_yuv422p_format(u32 format)
{
bool ret = false;
switch (format) {
case RGA2_FORMAT_YCbCr_422_P:
case RGA2_FORMAT_YCrCb_422_P:
ret = true;
break;
}
return ret;
}
void rga_convert_addr(struct rga_img_info_t *img, bool before_vir_get_channel)
{
uint32_t fmt = 0;
rga_user_format_convert(&fmt, img->format);
/*
* If it is not using dma fd, the virtual/phyical address is assigned
* to the address of the corresponding channel.
*/
//img->yrgb_addr = img->uv_addr;
/*
* if before_vir_get_channel is true, then convert addr by default
* when has iova (before_vir_get_channel is false),
* need to consider whether fbc case
*/
if (img->rd_mode != RGA_FBC_MODE || before_vir_get_channel) {
img->uv_addr = img->yrgb_addr + (img->vir_w * img->vir_h);
//warning: rga3 may need /2 for all
if (rga_is_yuv422p_format(fmt))
img->v_addr =
img->uv_addr + (img->vir_w * img->vir_h) / 2;
else
img->v_addr =
img->uv_addr + (img->vir_w * img->vir_h) / 4;
} else {
img->uv_addr = img->yrgb_addr;
img->v_addr = 0;
}
}
int rga_get_format_bits(u32 format)
{
int bits = 0;
switch (format) {
case RGA2_FORMAT_RGBA_8888:
case RGA2_FORMAT_RGBX_8888:
case RGA2_FORMAT_BGRA_8888:
case RGA2_FORMAT_BGRX_8888:
case RGA2_FORMAT_ARGB_8888:
case RGA2_FORMAT_XRGB_8888:
case RGA2_FORMAT_ABGR_8888:
case RGA2_FORMAT_XBGR_8888:
bits = 32;
break;
case RGA2_FORMAT_RGB_888:
case RGA2_FORMAT_BGR_888:
bits = 24;
break;
case RGA2_FORMAT_RGB_565:
case RGA2_FORMAT_RGBA_5551:
case RGA2_FORMAT_RGBA_4444:
case RGA2_FORMAT_BGR_565:
case RGA2_FORMAT_YCbCr_422_SP:
case RGA2_FORMAT_YCbCr_422_P:
case RGA2_FORMAT_YCrCb_422_SP:
case RGA2_FORMAT_YCrCb_422_P:
case RGA2_FORMAT_BGRA_5551:
case RGA2_FORMAT_BGRA_4444:
case RGA2_FORMAT_ARGB_5551:
case RGA2_FORMAT_ARGB_4444:
case RGA2_FORMAT_ABGR_5551:
case RGA2_FORMAT_ABGR_4444:
bits = 16;
break;
case RGA2_FORMAT_YCbCr_420_SP:
case RGA2_FORMAT_YCbCr_420_P:
case RGA2_FORMAT_YCrCb_420_SP:
case RGA2_FORMAT_YCrCb_420_P:
bits = 12;
break;
case RGA2_FORMAT_YCbCr_420_SP_10B:
case RGA2_FORMAT_YCrCb_420_SP_10B:
case RGA2_FORMAT_YCbCr_422_SP_10B:
case RGA2_FORMAT_YCrCb_422_SP_10B:
bits = 15;
break;
default:
pr_err("unknown format [%d]\n", format);
return -1;
}
return bits;
}

View File

@@ -0,0 +1,572 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author:
* Cerf Yu <cerf.yu@rock-chips.com>
* Huang Lee <Putin.li@rock-chips.com>
*/
#define pr_fmt(fmt) "rga_debugger: " fmt
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/syscalls.h>
#include <linux/debugfs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include "rga.h"
#include "rga_debugger.h"
#include "rga_drv.h"
#include "rga_mm.h"
#define RGA_DEBUGGER_ROOT_NAME "rkrga"
#define STR_ENABLE(en) (en ? "EN" : "DIS")
int RGA_DEBUG_REG;
int RGA_DEBUG_MSG;
int RGA_DEBUG_TIME;
int RGA_DEBUG_CHECK_MODE;
int RGA_DEBUG_NONUSE;
int RGA_DEBUG_INT_FLAG;
static int rga_debug_show(struct seq_file *m, void *data)
{
seq_printf(m, "REG [%s]\n"
"MSG [%s]\n"
"TIME [%s]\n"
"INT [%s]\n"
"CHECK [%s]\n"
"STOP [%s]\n",
STR_ENABLE(RGA_DEBUG_REG),
STR_ENABLE(RGA_DEBUG_MSG),
STR_ENABLE(RGA_DEBUG_TIME),
STR_ENABLE(RGA_DEBUG_CHECK_MODE),
STR_ENABLE(RGA_DEBUG_NONUSE),
STR_ENABLE(RGA_DEBUG_INT_FLAG));
seq_puts(m, "\nhelp:\n");
seq_puts(m,
" 'echo reg > debug' to enable/disable register log printing.\n");
seq_puts(m,
" 'echo msg > debug' to enable/disable message log printing.\n");
seq_puts(m,
" 'echo time > debug' to enable/disable time log printing.\n");
seq_puts(m,
" 'echo int > debug' to enable/disable interruppt log printing.\n");
seq_puts(m, " 'echo check > debug' to enable/disable check mode.\n");
seq_puts(m,
" 'echo stop > debug' to enable/disable stop using hardware\n");
return 0;
}
static ssize_t rga_debug_write(struct file *file, const char __user *ubuf,
size_t len, loff_t *offp)
{
char buf[14];
if (len > sizeof(buf) - 1)
return -EINVAL;
if (copy_from_user(buf, ubuf, len))
return -EFAULT;
buf[len - 1] = '\0';
if (strncmp(buf, "reg", 4) == 0) {
if (RGA_DEBUG_REG) {
RGA_DEBUG_REG = 0;
pr_info("close rga reg!\n");
} else {
RGA_DEBUG_REG = 1;
pr_info("open rga reg!\n");
}
} else if (strncmp(buf, "msg", 3) == 0) {
if (RGA_DEBUG_MSG) {
RGA_DEBUG_MSG = 0;
pr_info("close rga test MSG!\n");
} else {
RGA_DEBUG_MSG = 1;
pr_info("open rga test MSG!\n");
}
} else if (strncmp(buf, "time", 4) == 0) {
if (RGA_DEBUG_TIME) {
RGA_DEBUG_TIME = 0;
pr_info("close rga test time!\n");
} else {
RGA_DEBUG_TIME = 1;
pr_info("open rga test time!\n");
}
} else if (strncmp(buf, "check", 5) == 0) {
if (RGA_DEBUG_CHECK_MODE) {
RGA_DEBUG_CHECK_MODE = 0;
pr_info("close rga check flag!\n");
} else {
RGA_DEBUG_CHECK_MODE = 1;
pr_info("open rga check flag!\n");
}
} else if (strncmp(buf, "stop", 4) == 0) {
if (RGA_DEBUG_NONUSE) {
RGA_DEBUG_NONUSE = 0;
pr_info("using rga hardware!\n");
} else {
RGA_DEBUG_NONUSE = 1;
pr_info("stop using rga hardware!\n");
}
} else if (strncmp(buf, "int", 3) == 0) {
if (RGA_DEBUG_INT_FLAG) {
RGA_DEBUG_INT_FLAG = 0;
pr_info("close inturrupt MSG!\n");
} else {
RGA_DEBUG_INT_FLAG = 1;
pr_info("open inturrupt MSG!\n");
}
} else if (strncmp(buf, "slt", 3) == 0) {
pr_err("Null");
}
return len;
}
static int rga_version_show(struct seq_file *m, void *data)
{
seq_printf(m, "%s: v%s\n", DRIVER_DESC, DRIVER_VERSION);
return 0;
}
static int rga_load_show(struct seq_file *m, void *data)
{
struct rga_scheduler_t *rga_scheduler = NULL;
unsigned long flags;
int i;
int load;
u32 busy_time_total;
seq_printf(m, "num of scheduler = %d\n", rga_drvdata->num_of_scheduler);
seq_printf(m, "================= load ==================\n");
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
rga_scheduler = rga_drvdata->rga_scheduler[i];
seq_printf(m, "scheduler[%d]: %s\n",
i, dev_driver_string(rga_scheduler->dev));
spin_lock_irqsave(&rga_scheduler->irq_lock, flags);
busy_time_total = rga_scheduler->timer.busy_time_record;
spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags);
load = (busy_time_total * 100000 / RGA_LOAD_INTERVAL);
seq_printf(m, "load = %d", load);
seq_printf(m, "-----------------------------------\n");
}
return 0;
}
static int rga_scheduler_show(struct seq_file *m, void *data)
{
struct rga_scheduler_t *rga_scheduler = NULL;
int i;
seq_printf(m, "num of scheduler = %d\n", rga_drvdata->num_of_scheduler);
seq_printf(m, "===================================\n");
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
rga_scheduler = rga_drvdata->rga_scheduler[i];
seq_printf(m, "scheduler[%d]: %s\n",
i, dev_driver_string(rga_scheduler->dev));
seq_printf(m, "-----------------------------------\n");
seq_printf(m, "pd_ref = %d\n", rga_scheduler->pd_refcount);
}
return 0;
}
static int rga_mm_session_show(struct seq_file *m, void *data)
{
int id, i;
struct rga_mm *mm_session = NULL;
struct rga_internal_buffer *dump_buffer;
mm_session = rga_drvdata->mm;
mutex_lock(&mm_session->lock);
seq_puts(m, "rga_mm dump:\n");
seq_printf(m, "buffer count = %d\n", mm_session->buffer_count);
seq_puts(m, "===============================================================\n");
idr_for_each_entry(&mm_session->memory_idr, dump_buffer, id) {
seq_printf(m, "handle = %d refcount = %d mm_flag = 0x%x\n",
dump_buffer->handle, kref_read(&dump_buffer->refcount),
dump_buffer->mm_flag);
switch (dump_buffer->type) {
case RGA_DMA_BUFFER:
seq_puts(m, "dma_buffer:\n");
for (i = 0; i < dump_buffer->dma_buffer_size; i++) {
seq_printf(m, "\t core %d:\n", dump_buffer->dma_buffer[i].core);
seq_printf(m, "\t\t dma_buf = %p, iova = 0x%lx\n",
dump_buffer->dma_buffer[i].dma_buf,
(unsigned long)dump_buffer->dma_buffer[i].iova);
}
break;
case RGA_VIRTUAL_ADDRESS:
seq_puts(m, "virtual address:\n");
seq_printf(m, "\t va = 0x%lx, pages = %p, size = %ld\n",
(unsigned long)dump_buffer->virt_addr->addr,
dump_buffer->virt_addr->pages,
dump_buffer->virt_addr->size);
for (i = 0; i < dump_buffer->dma_buffer_size; i++) {
seq_printf(m, "\t core %d:\n", dump_buffer->dma_buffer[i].core);
seq_printf(m, "\t\t iova = 0x%lx, sgt = %p, size = %ld\n",
(unsigned long)dump_buffer->dma_buffer[i].iova,
dump_buffer->dma_buffer[i].sgt,
dump_buffer->dma_buffer[i].size);
}
break;
case RGA_PHYSICAL_ADDRESS:
seq_puts(m, "physical address:\n");
seq_printf(m, "\t pa = 0x%lx\n", (unsigned long)dump_buffer->phys_addr);
break;
default:
seq_puts(m, "Illegal external buffer!\n");
break;
}
seq_puts(m, "---------------------------------------------------------------\n");
}
mutex_unlock(&mm_session->lock);
return 0;
}
struct rga_debugger_list rga_debugger_root_list[] = {
{"debug", rga_debug_show, rga_debug_write, NULL},
{"driver_version", rga_version_show, NULL, NULL},
{"load", rga_load_show, NULL, NULL},
{"scheduler_status", rga_scheduler_show, NULL, NULL},
{"mm_session", rga_mm_session_show, NULL, NULL},
};
static ssize_t rga_debugger_write(struct file *file, const char __user *ubuf,
size_t len, loff_t *offp)
{
struct seq_file *priv = file->private_data;
struct rga_debugger_node *node = priv->private;
if (node->info_ent->write)
return node->info_ent->write(file, ubuf, len, offp);
else
return len;
}
#ifdef CONFIG_ROCKCHIP_RGA_DEBUG_FS
static int rga_debugfs_open(struct inode *inode, struct file *file)
{
struct rga_debugger_node *node = inode->i_private;
return single_open(file, node->info_ent->show, node);
}
static const struct file_operations rga_debugfs_fops = {
.owner = THIS_MODULE,
.open = rga_debugfs_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = rga_debugger_write,
};
static int rga_debugfs_remove_files(struct rga_debugger *debugger)
{
struct rga_debugger_node *pos, *q;
struct list_head *entry_list;
mutex_lock(&debugger->debugfs_lock);
/* Delete debugfs entry list */
entry_list = &debugger->debugfs_entry_list;
list_for_each_entry_safe(pos, q, entry_list, list) {
if (pos->dent == NULL)
continue;
list_del(&pos->list);
kfree(pos);
pos = NULL;
}
/* Delete all debugfs node in this directory */
debugfs_remove_recursive(debugger->debugfs_dir);
debugger->debugfs_dir = NULL;
mutex_unlock(&debugger->debugfs_lock);
return 0;
}
static int rga_debugfs_create_files(const struct rga_debugger_list *files,
int count, struct dentry *root,
struct rga_debugger *debugger)
{
int i;
struct dentry *ent;
struct rga_debugger_node *tmp;
for (i = 0; i < count; i++) {
tmp = kmalloc(sizeof(struct rga_debugger_node), GFP_KERNEL);
if (tmp == NULL) {
pr_err("Cannot alloc node path /sys/kernel/debug/%pd/%s\n",
root, files[i].name);
goto MALLOC_FAIL;
}
tmp->info_ent = &files[i];
tmp->debugger = debugger;
ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
root, tmp, &rga_debugfs_fops);
if (!ent) {
pr_err("Cannot create /sys/kernel/debug/%pd/%s\n", root,
files[i].name);
goto CREATE_FAIL;
}
tmp->dent = ent;
mutex_lock(&debugger->debugfs_lock);
list_add_tail(&tmp->list, &debugger->debugfs_entry_list);
mutex_unlock(&debugger->debugfs_lock);
}
return 0;
CREATE_FAIL:
kfree(tmp);
MALLOC_FAIL:
rga_debugfs_remove_files(debugger);
return -1;
}
int rga_debugfs_remove(void)
{
struct rga_debugger *debugger;
debugger = rga_drvdata->debugger;
rga_debugfs_remove_files(debugger);
return 0;
}
int rga_debugfs_init(void)
{
int ret;
struct rga_debugger *debugger;
debugger = rga_drvdata->debugger;
debugger->debugfs_dir =
debugfs_create_dir(RGA_DEBUGGER_ROOT_NAME, NULL);
if (IS_ERR_OR_NULL(debugger->debugfs_dir)) {
pr_err("failed on mkdir /sys/kernel/debug/%s\n",
RGA_DEBUGGER_ROOT_NAME);
debugger->debugfs_dir = NULL;
return -EIO;
}
ret = rga_debugfs_create_files(rga_debugger_root_list, ARRAY_SIZE(rga_debugger_root_list),
debugger->debugfs_dir, debugger);
if (ret) {
pr_err("Could not install rga_debugger_root_list debugfs\n");
goto CREATE_FAIL;
}
return 0;
CREATE_FAIL:
rga_debugfs_remove();
return ret;
}
#endif /* #ifdef CONFIG_ROCKCHIP_RGA_DEBUG_FS */
#ifdef CONFIG_ROCKCHIP_RGA2_PROC_FS
static int rga_procfs_open(struct inode *inode, struct file *file)
{
struct rga_debugger_node *node = PDE_DATA(inode);
return single_open(file, node->info_ent->show, node);
}
static const struct file_operations rga_procfs_fops = {
.owner = THIS_MODULE,
.open = rga_procfs_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = rga_debugger_write,
};
static int rga_procfs_remove_files(struct rga_debugger *debugger)
{
struct rga_debugger_node *pos, *q;
struct list_head *entry_list;
mutex_lock(&debugger->procfs_lock);
/* Delete procfs entry list */
entry_list = &debugger->procfs_entry_list;
list_for_each_entry_safe(pos, q, entry_list, list) {
if (pos->pent == NULL)
continue;
list_del(&pos->list);
kfree(pos);
pos = NULL;
}
/* Delete all procfs node in this directory */
proc_remove(debugger->procfs_dir);
debugger->procfs_dir = NULL;
mutex_unlock(&debugger->procfs_lock);
return 0;
}
static int rga_procfs_create_files(const struct rga_debugger_list *files,
int count, struct proc_dir_entry *root,
struct rga_debugger *debugger)
{
int i;
struct proc_dir_entry *ent;
struct rga_debugger_node *tmp;
for (i = 0; i < count; i++) {
tmp = kmalloc(sizeof(struct rga_debugger_node), GFP_KERNEL);
if (tmp == NULL) {
pr_err("Cannot alloc node path for /proc/%s/%s\n",
RGA_DEBUGGER_ROOT_NAME, files[i].name);
goto MALLOC_FAIL;
}
tmp->info_ent = &files[i];
tmp->debugger = debugger;
ent = proc_create_data(files[i].name, S_IFREG | S_IRUGO,
root, &rga_procfs_fops, tmp);
if (!ent) {
pr_err("Cannot create /proc/%s/%s\n",
RGA_DEBUGGER_ROOT_NAME, files[i].name);
goto CREATE_FAIL;
}
tmp->pent = ent;
mutex_lock(&debugger->procfs_lock);
list_add_tail(&tmp->list, &debugger->procfs_entry_list);
mutex_unlock(&debugger->procfs_lock);
}
return 0;
CREATE_FAIL:
kfree(tmp);
MALLOC_FAIL:
rga_procfs_remove_files(debugger);
return -1;
}
int rga_procfs_remove(void)
{
struct rga_debugger *debugger;
debugger = rga_drvdata->debugger;
rga_procfs_remove_files(debugger);
return 0;
}
int rga_procfs_init(void)
{
int ret;
struct rga_debugger *debugger;
debugger = rga_drvdata->debugger;
debugger->procfs_dir = proc_mkdir(RGA_DEBUGGER_ROOT_NAME, NULL);
if (IS_ERR_OR_NULL(debugger->procfs_dir)) {
pr_err("failed on mkdir /proc/%s\n", RGA_DEBUGGER_ROOT_NAME);
debugger->procfs_dir = NULL;
return -EIO;
}
ret = rga_procfs_create_files(rga_debugger_root_list, ARRAY_SIZE(rga_debugger_root_list),
debugger->procfs_dir, debugger);
if (ret) {
pr_err("Could not install rga_debugger_root_list procfs\n");
goto CREATE_FAIL;
}
return 0;
CREATE_FAIL:
rga_procfs_remove();
return ret;
}
#endif /* #ifdef CONFIG_ROCKCHIP_RGA_PROC_FS */
void rga_cmd_print_debug_info(struct rga_req *req)
{
pr_info("============= start ==============\n");
pr_info("render_mode = %d, bitblit_mode=%d, rotate_mode = %d\n",
req->render_mode, req->bsfilter_flag,
req->rotate_mode);
pr_info("src: y = %lx uv = %lx v = %lx aw = %d ah = %d vw = %d vh = %d\n",
(unsigned long)req->src.yrgb_addr,
(unsigned long)req->src.uv_addr,
(unsigned long)req->src.v_addr,
req->src.act_w, req->src.act_h,
req->src.vir_w, req->src.vir_h);
pr_info("src: xoff = %d, yoff = %d, format = 0x%x, rd_mode = %d\n",
req->src.x_offset, req->src.y_offset,
req->src.format, req->src.rd_mode);
if (req->pat.yrgb_addr != 0 || req->pat.uv_addr != 0
|| req->pat.v_addr != 0) {
pr_info("pat: y=%lx uv=%lx v=%lx aw=%d ah=%d vw=%d vh=%d\n",
(unsigned long)req->pat.yrgb_addr,
(unsigned long)req->pat.uv_addr,
(unsigned long)req->pat.v_addr,
req->pat.act_w, req->pat.act_h,
req->pat.vir_w, req->pat.vir_h);
pr_info("pat: xoff = %d yoff = %d, format = 0x%x, rd_mode = %d\n",
req->pat.x_offset, req->pat.y_offset,
req->pat.format, req->pat.rd_mode);
}
pr_info("dst: y=%lx uv=%lx v=%lx aw=%d ah=%d vw=%d vh=%d\n",
(unsigned long)req->dst.yrgb_addr,
(unsigned long)req->dst.uv_addr,
(unsigned long)req->dst.v_addr,
req->dst.act_w, req->dst.act_h,
req->dst.vir_w, req->dst.vir_h);
pr_info("dst: xoff = %d, yoff = %d, format = 0x%x, rd_mode = %d\n",
req->dst.x_offset, req->dst.y_offset,
req->dst.format, req->dst.rd_mode);
pr_info("mmu: mmu_flag=%x en=%x\n",
req->mmu_info.mmu_flag, req->mmu_info.mmu_en);
pr_info("alpha: rop_mode = %x\n", req->alpha_rop_mode);
pr_info("yuv2rgb mode is %x\n", req->yuv2rgb_mode);
pr_info("set core = %d, priority = %d, in_fence_fd = %d\n",
req->core, req->priority, req->in_fence_fd);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,136 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author: Huang Lee <Putin.li@rock-chips.com>
*/
#define pr_fmt(fmt) "rga_fence: " fmt
#include <linux/dma-fence.h>
#include <linux/sync_file.h>
#include <linux/slab.h>
#include "rga_fence.h"
static const char *rga_fence_get_name(struct dma_fence *fence)
{
return DRIVER_NAME;
}
static const struct dma_fence_ops rga_fence_ops = {
.get_driver_name = rga_fence_get_name,
.get_timeline_name = rga_fence_get_name,
};
struct rga_fence_context *rga_fence_context_alloc(void)
{
struct rga_fence_context *fence_ctx = NULL;
fence_ctx = kzalloc(sizeof(*fence_ctx), GFP_KERNEL);
if (!fence_ctx)
return ERR_PTR(-ENOMEM);
fence_ctx->context = dma_fence_context_alloc(1);
spin_lock_init(&fence_ctx->spinlock);
return fence_ctx;
}
void rga_fence_context_free(struct rga_fence_context *fence_ctx)
{
kfree(fence_ctx);
}
int rga_out_fence_alloc(struct rga_job *job)
{
struct rga_fence_context *fence_ctx = rga_drvdata->fence_ctx;
struct dma_fence *fence = NULL;
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
if (!fence)
return -ENOMEM;
dma_fence_init(fence, &rga_fence_ops, &job->fence_lock,
fence_ctx->context, ++fence_ctx->seqno);
job->out_fence = fence;
return 0;
}
int rga_out_fence_get_fd(struct rga_job *job)
{
struct sync_file *sync_file = NULL;
int fence_fd = -1;
if (!job->out_fence)
return -EINVAL;
fence_fd = get_unused_fd_flags(O_CLOEXEC);
if (fence_fd < 0)
return fence_fd;
sync_file = sync_file_create(job->out_fence);
if (!sync_file)
return -ENOMEM;
fd_install(fence_fd, sync_file->file);
return fence_fd;
}
struct dma_fence *rga_get_input_fence(int in_fence_fd)
{
struct dma_fence *in_fence;
in_fence = sync_file_get_fence(in_fence_fd);
if (!in_fence)
pr_err("can not get in-fence from fd\n");
return in_fence;
}
int rga_wait_input_fence(struct dma_fence *in_fence)
{
int ret = 0;
ret = dma_fence_wait(in_fence, true);
dma_fence_put(in_fence);
return ret;
}
int rga_add_dma_fence_callback(struct rga_job *job, struct dma_fence *in_fence,
dma_fence_func_t func)
{
struct rga_fence_waiter *waiter;
int ret;
waiter = kmalloc(sizeof(*waiter), GFP_KERNEL);
if (!waiter) {
pr_err("%s: Failed to allocate waiter\n", __func__);
return -ENOMEM;
}
waiter->job = job;
ret = dma_fence_add_callback(in_fence, &waiter->waiter, func);
if (ret == -ENOENT) {
pr_err("'input fence' has been already signaled.");
goto err_free_waiter;
} else if (ret == -EINVAL) {
pr_err
("%s: failed to add callback to dma_fence, err: %d\n",
__func__, ret);
goto err_free_waiter;
}
return ret;
err_free_waiter:
kfree(waiter);
return ret;
}

View File

@@ -0,0 +1,229 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author:
* Huang Lee <Putin.li@rock-chips.com>
*/
#include "rga_hw_config.h"
const uint32_t rga3_raster_format[] = {
RGA2_FORMAT_RGBA_8888,
RGA2_FORMAT_BGRA_8888,
RGA2_FORMAT_RGB_888,
RGA2_FORMAT_BGR_888,
RGA2_FORMAT_RGB_565,
RGA2_FORMAT_BGR_565,
RGA2_FORMAT_YCbCr_422_SP,
RGA2_FORMAT_YCbCr_420_SP,
RGA2_FORMAT_YCrCb_422_SP,
RGA2_FORMAT_YCrCb_420_SP,
RGA2_FORMAT_YVYU_422,
RGA2_FORMAT_VYUY_422,
RGA2_FORMAT_YUYV_422,
RGA2_FORMAT_UYVY_422,
RGA2_FORMAT_YCbCr_420_SP_10B,
RGA2_FORMAT_YCrCb_420_SP_10B,
RGA2_FORMAT_YCbCr_422_SP_10B,
RGA2_FORMAT_YCrCb_422_SP_10B,
};
const uint32_t rga3_fbcd_format[] = {
RGA2_FORMAT_RGBA_8888,
RGA2_FORMAT_BGRA_8888,
RGA2_FORMAT_RGB_888,
RGA2_FORMAT_BGR_888,
RGA2_FORMAT_RGB_565,
RGA2_FORMAT_BGR_565,
RGA2_FORMAT_YCbCr_422_SP,
RGA2_FORMAT_YCbCr_420_SP,
RGA2_FORMAT_YCrCb_422_SP,
RGA2_FORMAT_YCrCb_420_SP,
RGA2_FORMAT_YCbCr_420_SP_10B,
RGA2_FORMAT_YCrCb_420_SP_10B,
RGA2_FORMAT_YCbCr_422_SP_10B,
RGA2_FORMAT_YCrCb_422_SP_10B,
};
const uint32_t rga3_tile_format[] = {
RGA2_FORMAT_YCbCr_422_SP,
RGA2_FORMAT_YCbCr_420_SP,
RGA2_FORMAT_YCrCb_422_SP,
RGA2_FORMAT_YCrCb_420_SP,
RGA2_FORMAT_YCbCr_420_SP_10B,
RGA2_FORMAT_YCrCb_420_SP_10B,
RGA2_FORMAT_YCbCr_422_SP_10B,
RGA2_FORMAT_YCrCb_422_SP_10B,
};
const uint32_t rga2e_raster_format[] = {
RGA2_FORMAT_RGBA_8888,
RGA2_FORMAT_RGBX_8888,
RGA2_FORMAT_BGRA_8888,
RGA2_FORMAT_BGRX_8888,
RGA2_FORMAT_RGB_888,
RGA2_FORMAT_BGR_888,
RGA2_FORMAT_RGB_565,
RGA2_FORMAT_BGR_565,
RGA2_FORMAT_YCbCr_422_P,
RGA2_FORMAT_YCbCr_420_P,
RGA2_FORMAT_YCrCb_422_P,
RGA2_FORMAT_YCrCb_420_P,
RGA2_FORMAT_YCbCr_422_SP,
RGA2_FORMAT_YCbCr_420_SP,
RGA2_FORMAT_YCrCb_422_SP,
RGA2_FORMAT_YCrCb_420_SP,
RGA2_FORMAT_YVYU_422,
RGA2_FORMAT_VYUY_422,
RGA2_FORMAT_YUYV_422,
RGA2_FORMAT_UYVY_422,
RGA2_FORMAT_YCbCr_420_SP_10B,
RGA2_FORMAT_YCrCb_420_SP_10B,
RGA2_FORMAT_YCbCr_422_SP_10B,
RGA2_FORMAT_YCrCb_422_SP_10B,
RGA2_FORMAT_Y4,
RGA2_FORMAT_YCbCr_400,
RGA2_FORMAT_RGBA_5551,
RGA2_FORMAT_BGRA_5551,
RGA2_FORMAT_RGBA_4444,
RGA2_FORMAT_BGRA_4444,
RGA2_FORMAT_XRGB_8888,
RGA2_FORMAT_XBGR_8888,
RGA2_FORMAT_BPP_1,
RGA2_FORMAT_BPP_2,
RGA2_FORMAT_BPP_4,
RGA2_FORMAT_BPP_8,
RGA2_FORMAT_ARGB_8888,
RGA2_FORMAT_ARGB_5551,
RGA2_FORMAT_ARGB_4444,
RGA2_FORMAT_ABGR_8888,
RGA2_FORMAT_ABGR_5551,
RGA2_FORMAT_ABGR_4444,
};
const struct rga_win_data rga3_win_data[] = {
{
.name = "rga3-win0",
.raster_formats = rga3_raster_format,
.num_of_raster_formats = ARRAY_SIZE(rga3_raster_format),
.fbc_formats = rga3_fbcd_format,
.num_of_fbc_formats = ARRAY_SIZE(rga3_fbcd_format),
.tile_formats = rga3_tile_format,
.num_of_tile_formats = ARRAY_SIZE(rga3_tile_format),
.supported_rotations = RGA_MODE_ROTATE_MASK,
.scale_up_mode = RGA_SCALE_UP_BIC,
.scale_down_mode = RGA_SCALE_DOWN_AVG,
.rd_mode = RGA_RASTER_MODE | RGA_FBC_MODE | RGA_TILE_MODE,
},
{
.name = "rga3-win1",
.raster_formats = rga3_raster_format,
.num_of_raster_formats = ARRAY_SIZE(rga3_raster_format),
.fbc_formats = rga3_fbcd_format,
.num_of_fbc_formats = ARRAY_SIZE(rga3_fbcd_format),
.tile_formats = rga3_tile_format,
.num_of_tile_formats = ARRAY_SIZE(rga3_tile_format),
.supported_rotations = RGA_MODE_ROTATE_MASK,
.scale_up_mode = RGA_SCALE_UP_BIC,
.scale_down_mode = RGA_SCALE_DOWN_AVG,
.rd_mode = RGA_RASTER_MODE | RGA_FBC_MODE | RGA_TILE_MODE,
},
{
.name = "rga3-wr",
.raster_formats = rga3_raster_format,
.num_of_raster_formats = ARRAY_SIZE(rga3_raster_format),
.fbc_formats = rga3_fbcd_format,
.num_of_fbc_formats = ARRAY_SIZE(rga3_fbcd_format),
.tile_formats = rga3_tile_format,
.num_of_tile_formats = ARRAY_SIZE(rga3_tile_format),
.supported_rotations = 0,
.scale_up_mode = RGA_SCALE_UP_NONE,
.scale_down_mode = RGA_SCALE_DOWN_NONE,
.rd_mode = RGA_RASTER_MODE | RGA_FBC_MODE | RGA_TILE_MODE,
},
};
const struct rga_win_data rga2e_win_data[] = {
{
.name = "rga2e-src0",
.raster_formats = rga2e_raster_format,
.num_of_raster_formats = ARRAY_SIZE(rga2e_raster_format),
.supported_rotations = RGA_MODE_ROTATE_MASK,
.scale_up_mode = RGA_SCALE_UP_BIC,
.scale_down_mode = RGA_SCALE_DOWN_AVG,
.rd_mode = RGA_RASTER_MODE,
},
{
.name = "rga2e-src1",
.raster_formats = rga2e_raster_format,
.num_of_raster_formats = ARRAY_SIZE(rga2e_raster_format),
.supported_rotations = RGA_MODE_ROTATE_MASK,
.scale_up_mode = RGA_SCALE_UP_BIC,
.scale_down_mode = RGA_SCALE_DOWN_AVG,
.rd_mode = RGA_RASTER_MODE,
},
{
.name = "rga2-dst",
.raster_formats = rga2e_raster_format,
.num_of_raster_formats = ARRAY_SIZE(rga2e_raster_format),
.supported_rotations = 0,
.scale_up_mode = RGA_SCALE_UP_NONE,
.scale_down_mode = RGA_SCALE_DOWN_NONE,
.rd_mode = RGA_RASTER_MODE,
},
};
const struct rga_hw_data rga3_data = {
.version = 0,
.min_input = { 128, 128 },
.min_output = { 128, 128 },
.max_input = { 8176, 8176 },
.max_output = { 8128, 8128 },
.win = rga3_win_data,
.win_size = ARRAY_SIZE(rga3_win_data),
/* 1 << factor mean real factor */
.max_upscale_factor = 3,
.max_downscale_factor = 3,
.feature = RGA_COLOR_KEY,
.csc_r2y_mode = RGA_MODE_CSC_BT601L |
RGA_MODE_CSC_BT601F | RGA_MODE_CSC_BT709 |
RGA_MODE_CSC_BT2020,
.csc_y2r_mode = RGA_MODE_CSC_BT601L |
RGA_MODE_CSC_BT601F | RGA_MODE_CSC_BT709 |
RGA_MODE_CSC_BT2020,
};
const struct rga_hw_data rga2e_data = {
.version = 0,
.min_input = { 0, 0 },
.min_output = { 0, 0 },
.max_input = { 8192, 8192 },
.max_output = { 4096, 4096 },
.win = rga2e_win_data,
.win_size = ARRAY_SIZE(rga2e_win_data),
/* 1 << factor mean real factor */
.max_upscale_factor = 4,
.max_downscale_factor = 4,
.feature = RGA_COLOR_FILL | RGA_COLOR_PALETTE |
RGA_COLOR_KEY | RGA_ROP_CALCULATE |
RGA_NN_QUANTIZE | RGA_DITHER,
.csc_r2y_mode = RGA_MODE_CSC_BT601L | RGA_MODE_CSC_BT601F |
RGA_MODE_CSC_BT709,
.csc_y2r_mode = RGA_MODE_CSC_BT601L | RGA_MODE_CSC_BT601F |
RGA_MODE_CSC_BT709,
};

View File

@@ -0,0 +1,745 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author: Huang Lee <Putin.li@rock-chips.com>
*/
#define pr_fmt(fmt) "rga_job: " fmt
#include "rga_job.h"
#include "rga_fence.h"
#include "rga_dma_buf.h"
#include "rga_mm.h"
#include "rga2_mmu_info.h"
struct rga_job *
rga_scheduler_get_pending_job_list(struct rga_scheduler_t *scheduler)
{
unsigned long flags;
struct rga_job *job;
spin_lock_irqsave(&scheduler->irq_lock, flags);
job = list_first_entry_or_null(&scheduler->todo_list,
struct rga_job, head);
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
return job;
}
struct rga_job *
rga_scheduler_get_running_job(struct rga_scheduler_t *scheduler)
{
unsigned long flags;
struct rga_job *job;
spin_lock_irqsave(&scheduler->irq_lock, flags);
job = scheduler->running_job;
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
return job;
}
struct rga_scheduler_t *rga_job_get_scheduler(int core)
{
struct rga_scheduler_t *scheduler = NULL;
int i;
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
if (core == rga_drvdata->rga_scheduler[i]->core) {
scheduler = rga_drvdata->rga_scheduler[i];
if (DEBUGGER_EN(MSG))
pr_info("job choose core: %d\n",
rga_drvdata->rga_scheduler[i]->core);
break;
}
}
return scheduler;
}
static int rga_job_get_current_mm(struct rga_job *job)
{
int mmu_flag;
struct rga_img_info_t *src0 = NULL;
struct rga_img_info_t *src1 = NULL;
struct rga_img_info_t *dst = NULL;
struct rga_img_info_t *els = NULL;
src0 = &job->rga_command_base.src;
dst = &job->rga_command_base.dst;
if (job->rga_command_base.render_mode != UPDATE_PALETTE_TABLE_MODE)
src1 = &job->rga_command_base.pat;
else
els = &job->rga_command_base.pat;
if (likely(src0 != NULL)) {
mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 8) & 1);
if (mmu_flag && src0->uv_addr)
goto get_current_mm;
}
if (likely(dst != NULL)) {
mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 10) & 1);
if (mmu_flag && dst->uv_addr)
goto get_current_mm;
}
if (src1 != NULL) {
mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 9) & 1);
if (mmu_flag && src1->yrgb_addr)
goto get_current_mm;
}
if (els != NULL) {
mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 11) & 1);
if (mmu_flag && els->yrgb_addr)
goto get_current_mm;
}
return 0;
get_current_mm:
mmgrab(current->mm);
mmget(current->mm);
job->mm = current->mm;
return 1;
}
static void rga_job_put_current_mm(struct rga_job *job)
{
if (job->mm == NULL)
return;
mmput(job->mm);
mmdrop(job->mm);
job->mm = NULL;
}
static void rga_job_free(struct rga_job *job)
{
if (job->out_fence)
dma_fence_put(job->out_fence);
if (~job->flags & RGA_JOB_USE_HANDLE)
rga_job_put_current_mm(job);
free_page((unsigned long)job);
}
static int rga_job_cleanup(struct rga_job *job)
{
rga_job_free(job);
return 0;
}
static int rga_job_judgment_support_core(struct rga_job *job)
{
int ret = 0;
uint32_t mm_flag;
struct rga_req *req;
struct rga_mm *mm;
req = &job->rga_command_base;
mm = rga_drvdata->mm;
if (mm == NULL) {
pr_err("rga mm is null!\n");
return -EFAULT;
}
mutex_lock(&mm->lock);
if (likely(req->src.yrgb_addr > 0)) {
ret = rga_mm_lookup_flag(mm, req->src.yrgb_addr);
if (ret < 0)
goto out_finish;
else
mm_flag = (uint32_t)ret;
if (~mm_flag & RGA_MM_UNDER_4G) {
job->flags |= RGA_JOB_UNSUPPORT_RGA2;
goto out_finish;
}
}
if (likely(req->dst.yrgb_addr > 0)) {
ret = rga_mm_lookup_flag(mm, req->dst.yrgb_addr);
if (ret < 0)
goto out_finish;
else
mm_flag = (uint32_t)ret;
if (~mm_flag & RGA_MM_UNDER_4G) {
job->flags |= RGA_JOB_UNSUPPORT_RGA2;
goto out_finish;
}
}
if (req->pat.yrgb_addr > 0) {
ret = rga_mm_lookup_flag(mm, req->pat.yrgb_addr);
if (ret < 0)
goto out_finish;
else
mm_flag = (uint32_t)ret;
if (~mm_flag & RGA_MM_UNDER_4G) {
job->flags |= RGA_JOB_UNSUPPORT_RGA2;
goto out_finish;
}
}
out_finish:
mutex_unlock(&mm->lock);
return ret;
}
static struct rga_job *rga_job_alloc(struct rga_req *rga_command_base)
{
struct rga_job *job = NULL;
job = (struct rga_job *)get_zeroed_page(GFP_KERNEL | GFP_DMA32);
if (!job)
return NULL;
spin_lock_init(&job->fence_lock);
INIT_LIST_HEAD(&job->head);
job->timestamp = ktime_get();
job->running_time = ktime_get();
job->rga_command_base = *rga_command_base;
if (rga_command_base->priority > 0) {
if (rga_command_base->priority > RGA_SCHED_PRIORITY_MAX)
job->priority = RGA_SCHED_PRIORITY_MAX;
else
job->priority = rga_command_base->priority;
}
if (job->rga_command_base.handle_flag & 1) {
job->flags |= RGA_JOB_USE_HANDLE;
rga_job_judgment_support_core(job);
} else {
rga_job_get_current_mm(job);
}
return job;
}
static void print_job_info(struct rga_job *job)
{
pr_info("job: priority = %d, core = %d\n",
job->priority, job->core);
}
static int rga_job_run(struct rga_job *job, struct rga_scheduler_t *scheduler)
{
int ret = 0;
/* enable power */
ret = rga_power_enable(scheduler);
if (ret < 0) {
pr_err("power enable failed");
return ret;
}
if (job->flags & RGA_JOB_USE_HANDLE) {
ret = rga_mm_get_handle_info(job);
if (ret < 0) {
pr_err("%s: failed to get buffer from handle\n", __func__);
goto failed;
}
} else {
ret = rga_dma_get_info(job);
if (ret < 0) {
pr_err("dma buf get failed");
goto failed;
}
}
ret = scheduler->ops->init_reg(job);
if (ret < 0) {
pr_err("init reg failed");
goto failed;
}
ret = scheduler->ops->set_reg(job, scheduler);
if (ret < 0) {
pr_err("set reg failed");
goto failed;
}
/* for debug */
if (DEBUGGER_EN(MSG))
print_job_info(job);
return ret;
failed:
rga_power_disable(scheduler);
return ret;
}
static void rga_job_next(struct rga_scheduler_t *rga_scheduler)
{
struct rga_job *job = NULL;
unsigned long flags;
next_job:
spin_lock_irqsave(&rga_scheduler->irq_lock, flags);
if (rga_scheduler->running_job ||
list_empty(&rga_scheduler->todo_list)) {
spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags);
return;
}
job = list_first_entry(&rga_scheduler->todo_list, struct rga_job, head);
list_del_init(&job->head);
rga_scheduler->job_count--;
rga_scheduler->running_job = job;
spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags);
job->ret = rga_job_run(job, rga_scheduler);
/* If some error before hw run */
if (job->ret < 0) {
pr_err("some error on rga_job_run before hw start, %s(%d)\n",
__func__, __LINE__);
spin_lock_irqsave(&rga_scheduler->irq_lock, flags);
rga_scheduler->running_job = NULL;
spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags);
if (job->flags & RGA_JOB_USE_HANDLE)
rga_mm_put_handle_info(job);
else
rga_dma_put_info(job);
if (job->out_fence)
dma_fence_signal(job->out_fence);
if (job->flags & RGA_JOB_ASYNC)
rga_job_cleanup(job);
else {
job->flags |= RGA_JOB_DONE;
wake_up(&rga_scheduler->job_done_wq);
}
goto next_job;
}
}
void rga_job_done(struct rga_scheduler_t *rga_scheduler, int ret)
{
struct rga_job *job;
unsigned long flags;
ktime_t now = ktime_get();
spin_lock_irqsave(&rga_scheduler->irq_lock, flags);
job = rga_scheduler->running_job;
rga_scheduler->running_job = NULL;
rga_scheduler->timer.busy_time += ktime_us_delta(now, job->timestamp);
spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags);
job->flags |= RGA_JOB_DONE;
job->ret = ret;
if (DEBUGGER_EN(TIME))
pr_err("%s use time = %lld\n", __func__,
ktime_us_delta(now, job->running_time));
job->running_time = now;
if (job->core == RGA2_SCHEDULER_CORE0)
rga2_dma_flush_cache_for_virtual_address(&job->vir_page_table,
rga_scheduler);
if (job->flags & RGA_JOB_USE_HANDLE)
rga_mm_put_handle_info(job);
else
rga_dma_put_info(job);
if (job->out_fence)
dma_fence_signal(job->out_fence);
if (job->flags & RGA_JOB_ASYNC)
rga_job_cleanup(job);
wake_up(&rga_scheduler->job_done_wq);
rga_job_next(rga_scheduler);
rga_power_disable(rga_scheduler);
}
static void rga_job_timeout_clean(struct rga_scheduler_t *scheduler)
{
unsigned long flags;
struct rga_job *job = NULL;
ktime_t now = ktime_get();
spin_lock_irqsave(&scheduler->irq_lock, flags);
job = scheduler->running_job;
if (job && (job->flags & RGA_JOB_ASYNC) &&
(ktime_to_ms(ktime_sub(now, job->timestamp)) >= RGA_ASYNC_TIMEOUT_DELAY)) {
scheduler->running_job = NULL;
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
scheduler->ops->soft_reset(scheduler);
if (job->flags & RGA_JOB_USE_HANDLE)
rga_mm_put_handle_info(job);
else
rga_dma_put_info(job);
if (job->out_fence)
dma_fence_signal(job->out_fence);
rga_job_cleanup(job);
rga_power_disable(scheduler);
} else {
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
}
}
static struct rga_scheduler_t *rga_job_schedule(struct rga_job *job)
{
unsigned long flags;
struct rga_scheduler_t *scheduler = NULL;
struct rga_job *job_pos;
bool first_match = 0;
if (rga_drvdata->num_of_scheduler > 1) {
job->core = rga_job_assign(job);
if (job->core <= 0) {
pr_err("job assign failed");
return NULL;
}
} else {
job->core = rga_drvdata->rga_scheduler[0]->core;
}
scheduler = rga_job_get_scheduler(job->core);
if (scheduler == NULL) {
pr_err("failed to get scheduler, %s(%d)\n", __func__, __LINE__);
return NULL;
}
rga_job_timeout_clean(scheduler);
spin_lock_irqsave(&scheduler->irq_lock, flags);
/* priority policy set by userspace */
if (list_empty(&scheduler->todo_list)
|| (job->priority == RGA_SCHED_PRIORITY_DEFAULT)) {
list_add_tail(&job->head, &scheduler->todo_list);
} else {
list_for_each_entry(job_pos, &scheduler->todo_list, head) {
if (job->priority > job_pos->priority &&
(!first_match)) {
list_add(&job->head, &job_pos->head);
first_match = true;
}
/*
* Increase the priority of subsequent tasks
* after inserting into the list
*/
if (first_match)
job_pos->priority++;
}
if (!first_match)
list_add_tail(&job->head, &scheduler->todo_list);
}
scheduler->job_count++;
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
rga_job_next(scheduler);
return scheduler;
}
static void rga_running_job_abort(struct rga_job *job,
struct rga_scheduler_t *rga_scheduler)
{
unsigned long flags;
spin_lock_irqsave(&rga_scheduler->irq_lock, flags);
/* invalid job */
if (job == rga_scheduler->running_job) {
rga_scheduler->running_job = NULL;
}
spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags);
rga_job_cleanup(job);
}
static void rga_invalid_job_abort(struct rga_job *job)
{
rga_job_cleanup(job);
}
static inline int rga_job_wait(struct rga_scheduler_t *rga_scheduler,
struct rga_job *job)
{
int left_time;
ktime_t now;
int ret;
left_time = wait_event_interruptible_timeout(rga_scheduler->job_done_wq,
job->flags & RGA_JOB_DONE, RGA_SYNC_TIMEOUT_DELAY);
switch (left_time) {
case 0:
pr_err("%s timeout", __func__);
rga_scheduler->ops->soft_reset(rga_scheduler);
ret = -EBUSY;
break;
case -ERESTARTSYS:
ret = -ERESTARTSYS;
break;
default:
ret = 0;
break;
}
now = ktime_get();
if (DEBUGGER_EN(TIME))
pr_err("%s use time = %lld\n", __func__,
ktime_to_us(ktime_sub(now, job->running_time)));
return ret;
}
static void rga_input_fence_signaled(struct dma_fence *fence,
struct dma_fence_cb *_waiter)
{
struct rga_fence_waiter *waiter = (struct rga_fence_waiter *)_waiter;
struct rga_scheduler_t *scheduler = NULL;
ktime_t now;
now = ktime_get();
if (DEBUGGER_EN(TIME))
pr_err("rga job wait in_fence signal use time = %lld\n",
ktime_to_us(ktime_sub(now, waiter->job->timestamp)));
scheduler = rga_job_schedule(waiter->job);
if (scheduler == NULL)
pr_err("failed to get scheduler, %s(%d)\n", __func__, __LINE__);
kfree(waiter);
}
int rga_job_commit(struct rga_req *rga_command_base, int flags)
{
struct rga_job *job = NULL;
struct rga_scheduler_t *scheduler = NULL;
struct dma_fence *in_fence;
int ret = 0;
job = rga_job_alloc(rga_command_base);
if (!job) {
pr_err("failed to alloc rga job!\n");
return -ENOMEM;
}
/*
* because fd can not pass on other thread,
* so need to get dma_buf first.
*/
ret = rga_dma_buf_get(job);
if (ret < 0) {
pr_err("%s: failed to get dma buf from fd\n",
__func__);
rga_job_free(job);
return ret;
}
if (flags == RGA_BLIT_ASYNC) {
ret = rga_out_fence_alloc(job);
if (ret) {
rga_job_free(job);
return ret;
}
job->flags |= RGA_JOB_ASYNC;
rga_command_base->out_fence_fd = rga_out_fence_get_fd(job);
if (DEBUGGER_EN(MSG))
pr_err("in_fence_fd = %d",
rga_command_base->in_fence_fd);
/* if input fence is valiable */
if (rga_command_base->in_fence_fd > 0) {
in_fence = rga_get_input_fence(
rga_command_base->in_fence_fd);
if (!in_fence) {
pr_err("%s: failed to get input dma_fence\n",
__func__);
rga_job_free(job);
return ret;
}
/* close input fence fd */
ksys_close(rga_command_base->in_fence_fd);
ret = dma_fence_get_status(in_fence);
/* ret = 1: fence has been signaled */
if (ret == 1) {
scheduler = rga_job_schedule(job);
if (scheduler == NULL) {
pr_err("failed to get scheduler, %s(%d)\n",
__func__, __LINE__);
ret = -EINVAL;
goto invalid_job;
}
/* if input fence is valid */
} else if (ret == 0) {
ret = rga_add_dma_fence_callback(job,
in_fence, rga_input_fence_signaled);
if (ret < 0) {
pr_err("%s: failed to add fence callback\n",
__func__);
rga_job_free(job);
return ret;
}
} else {
pr_err("%s: fence status error\n", __func__);
rga_job_free(job);
return ret;
}
} else {
scheduler = rga_job_schedule(job);
if (scheduler == NULL) {
pr_err("failed to get scheduler, %s(%d)\n",
__func__, __LINE__);
ret = -EINVAL;
goto invalid_job;
}
}
return ret;
/* sync mode: wait utill job finish */
} else if (flags == RGA_BLIT_SYNC) {
scheduler = rga_job_schedule(job);
if (scheduler == NULL) {
pr_err("failed to get scheduler, %s(%d)\n", __func__,
__LINE__);
ret = -EINVAL;
goto invalid_job;
}
ret = job->ret;
if (ret < 0) {
pr_err("some error on job, %s(%d)\n", __func__,
__LINE__);
goto running_job_abort;
}
ret = rga_job_wait(scheduler, job);
if (ret < 0) {
goto running_job_abort;
}
rga_job_cleanup(job);
}
return ret;
invalid_job:
rga_invalid_job_abort(job);
return ret;
/* only used by SYNC mode */
running_job_abort:
rga_running_job_abort(job, scheduler);
return ret;
}
int rga_job_mpi_commit(struct rga_req *rga_command_base,
struct rga_mpi_job_t *mpi_job, int flags)
{
struct rga_job *job = NULL;
struct rga_scheduler_t *scheduler = NULL;
int ret = 0;
job = rga_job_alloc(rga_command_base);
if (!job) {
pr_err("failed to alloc rga job!\n");
return -ENOMEM;
}
if (mpi_job != NULL) {
job->dma_buf_src0 = mpi_job->dma_buf_src0;
job->dma_buf_src1 = mpi_job->dma_buf_src1;
job->dma_buf_dst = mpi_job->dma_buf_dst;
}
if (flags == RGA_BLIT_ASYNC) {
//TODO:
pr_err("rk-debug TODO\n");
} else if (flags == RGA_BLIT_SYNC) {
scheduler = rga_job_schedule(job);
if (scheduler == NULL) {
pr_err("failed to get scheduler, %s(%d)\n", __func__,
__LINE__);
ret = -EINVAL;
goto invalid_job;
}
ret = job->ret;
if (ret < 0) {
pr_err("some error on job, %s(%d)\n", __func__,
__LINE__);
goto running_job_abort;
}
ret = rga_job_wait(scheduler, job);
if (ret < 0) {
goto running_job_abort;
}
rga_job_cleanup(job);
}
return ret;
invalid_job:
rga_invalid_job_abort(job);
return ret;
/* only used by SYNC mode */
running_job_abort:
rga_running_job_abort(job, scheduler);
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,319 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author: Huang Lee <Putin.li@rock-chips.com>
*/
#define pr_fmt(fmt) "rga_policy: " fmt
#include "rga_job.h"
#include "rga_common.h"
#include "rga_hw_config.h"
static int rga_set_feature(struct rga_req *rga_base)
{
int feature = 0;
if (rga_base->render_mode == COLOR_FILL_MODE)
feature |= RGA_COLOR_FILL;
if (rga_base->render_mode == COLOR_PALETTE_MODE)
feature |= RGA_COLOR_PALETTE;
if (rga_base->color_key_max > 0 || rga_base->color_key_min > 0)
feature |= RGA_COLOR_KEY;
if ((rga_base->alpha_rop_flag >> 1) & 1)
feature |= RGA_ROP_CALCULATE;
if ((rga_base->alpha_rop_flag >> 8) & 1)
feature |= RGA_NN_QUANTIZE;
return feature;
}
static bool rga_check_format(const struct rga_hw_data *data,
int rd_mode, int format, int win_num)
{
int i;
bool matched = false;
if (rd_mode == RGA_RASTER_MODE) {
for (i = 0; i < data->win[win_num].num_of_raster_formats; i++) {
if (format == data->win[win_num].raster_formats[i]) {
matched = true;
break;
}
}
} else if (rd_mode == RGA_FBC_MODE) {
for (i = 0; i < data->win[win_num].num_of_fbc_formats; i++) {
if (format == data->win[win_num].fbc_formats[i]) {
matched = true;
break;
}
}
} else if (rd_mode == RGA_TILE_MODE) {
for (i = 0; i < data->win[win_num].num_of_tile_formats; i++) {
if (format == data->win[win_num].tile_formats[i]) {
matched = true;
break;
}
}
}
return matched;
}
static bool rga_check_src0(const struct rga_hw_data *data,
struct rga_img_info_t *src0)
{
int format;
rga_user_format_convert(&format, src0->format);
if (src0->act_w < data->min_input.w ||
src0->act_h < data->min_input.h)
return false;
if (src0->act_w > data->max_input.w ||
src0->act_h > data->max_input.h)
return false;
if (!rga_check_format(data, src0->rd_mode, format, 0))
return false;
return true;
}
static bool rga_check_src1(const struct rga_hw_data *data,
struct rga_img_info_t *src1)
{
int format;
rga_user_format_convert(&format, src1->format);
if (src1->act_w < data->min_input.w ||
src1->act_h < data->min_input.h)
return false;
if (src1->act_w > data->max_input.w ||
src1->act_h > data->max_input.h)
return false;
if (!rga_check_format(data, src1->rd_mode, format, 1))
return false;
return true;
}
static bool rga_check_dst(const struct rga_hw_data *data,
struct rga_img_info_t *dst)
{
int format;
rga_user_format_convert(&format, dst->format);
if (dst->act_w < data->min_output.w ||
dst->act_h < data->min_output.h)
return false;
if (dst->act_w > data->max_output.w ||
dst->act_h > data->max_output.h)
return false;
if (!rga_check_format(data, dst->rd_mode, format, 2))
return false;
return true;
}
static bool rga_check_scale(const struct rga_hw_data *data,
struct rga_req *rga_base)
{
struct rga_img_info_t *src0 = &rga_base->src;
struct rga_img_info_t *dst = &rga_base->dst;
int sw, sh;
int dw, dh;
sw = src0->act_w;
sh = src0->act_h;
if ((rga_base->sina == 65536 && rga_base->cosa == 0)
|| (rga_base->sina == -65536 && rga_base->cosa == 0)) {
dw = dst->act_h;
dh = dst->act_w;
} else {
dw = dst->act_w;
dh = dst->act_h;
}
if (sw > dw) {
if ((sw >> data->max_downscale_factor) > dw)
return false;
} else if (sw < dw) {
if ((sw << data->max_upscale_factor) < dw)
return false;
}
if (sh > dh) {
if ((sh >> data->max_downscale_factor) > dh)
return false;
} else if (sh < dh) {
if ((sh << data->max_upscale_factor) < dh)
return false;
}
return true;
}
int rga_job_assign(struct rga_job *job)
{
struct rga_img_info_t *src0 = &job->rga_command_base.src;
struct rga_img_info_t *src1 = &job->rga_command_base.pat;
struct rga_img_info_t *dst = &job->rga_command_base.dst;
struct rga_req *rga_base = &job->rga_command_base;
const struct rga_hw_data *data;
struct rga_scheduler_t *scheduler = NULL;
int feature;
int core = RGA_NONE_CORE;
int optional_cores = RGA_NONE_CORE;
int i;
int min_of_job_count = 0;
unsigned long flags;
/* assigned by userspace */
if (rga_base->core > RGA_NONE_CORE) {
if (rga_base->core > RGA_CORE_MASK) {
pr_err("invalid setting core by user\n");
goto finish;
} else if (rga_base->core & RGA_CORE_MASK) {
optional_cores = rga_base->core;
goto skip_functional_policy;
}
}
feature = rga_set_feature(rga_base);
/* function */
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
data = rga_drvdata->rga_scheduler[i]->data;
scheduler = rga_drvdata->rga_scheduler[i];
if (DEBUGGER_EN(MSG))
pr_err("start policy on core = %d", scheduler->core);
if (scheduler->core == RGA2_SCHEDULER_CORE0 &&
job->flags & RGA_JOB_UNSUPPORT_RGA2) {
if (DEBUGGER_EN(MSG))
pr_debug("RGA2 only support under 4G memory!\n");
continue;
}
if (feature > 0) {
if (!(feature & data->feature)) {
if (DEBUGGER_EN(MSG))
pr_err("core = %d, break on feature",
scheduler->core);
continue;
}
}
/* only colorfill need single win (colorpalette?) */
if (!(feature & 1)) {
if (src1->yrgb_addr > 0) {
if ((!(src0->rd_mode & data->win[0].rd_mode)) ||
(!(src1->rd_mode & data->win[1].rd_mode)) ||
(!(dst->rd_mode & data->win[2].rd_mode))) {
if (DEBUGGER_EN(MSG))
pr_err("core = %d, ABC break on rd_mode",
scheduler->core);
continue;
}
} else {
if ((!(src0->rd_mode & data->win[0].rd_mode)) ||
(!(dst->rd_mode & data->win[2].rd_mode))) {
if (DEBUGGER_EN(MSG))
pr_err("core = %d, ABB break on rd_mode",
scheduler->core);
continue;
}
}
if (!rga_check_scale(data, rga_base)) {
if (DEBUGGER_EN(MSG))
pr_err("core = %d, break on rga_check_scale",
scheduler->core);
continue;
}
if (!rga_check_src0(data, src0)) {
if (DEBUGGER_EN(MSG))
pr_err("core = %d, break on rga_check_src0",
scheduler->core);
continue;
}
if (src1->yrgb_addr > 0) {
if (!rga_check_src1(data, src1)) {
if (DEBUGGER_EN(MSG))
pr_err("core = %d, break on rga_check_src1",
scheduler->core);
continue;
}
}
}
if (!rga_check_dst(data, dst)) {
if (DEBUGGER_EN(MSG))
pr_err("core = %d, break on rga_check_dst",
scheduler->core);
continue;
}
optional_cores |= scheduler->core;
}
if (DEBUGGER_EN(MSG))
pr_info("optional_cores = %d\n", optional_cores);
if (optional_cores == 0) {
core = -1;
pr_err("invalid function policy\n");
goto finish;
}
skip_functional_policy:
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
scheduler = rga_drvdata->rga_scheduler[i];
if (optional_cores & scheduler->core) {
spin_lock_irqsave(&scheduler->irq_lock, flags);
if (scheduler->running_job == NULL) {
core = scheduler->core;
spin_unlock_irqrestore(&scheduler->irq_lock,
flags);
break;
} else {
if ((min_of_job_count > scheduler->job_count) ||
(min_of_job_count == 0)) {
min_of_job_count = scheduler->job_count;
core = scheduler->core;
}
}
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
}
}
/* TODO: need consider full load */
finish:
if (DEBUGGER_EN(MSG))
pr_info("assign core: %d\n", core);
return core;
}