video/rockchip: rga3: Init version 1.1.1

Signed-off-by: Li Huang <putin.li@rock-chips.com>
Change-Id: Ib19d2d141e6b0eefa9d67b062e564559f58fb0b4
This commit is contained in:
Li Huang
2021-11-18 11:54:29 +08:00
committed by Tao Huang
parent cae208fa6f
commit 8ca0b5936e
23 changed files with 11072 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 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
rga3-$(CONFIG_ROCKCHIP_RGA_DEBUGGER) += rga_debugger.o
obj-$(CONFIG_ROCKCHIP_MULTI_RGA) += rga3.o

View File

@@ -0,0 +1,613 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _RGA_DRIVER_H_
#define _RGA_DRIVER_H_
#include <linux/mutex.h>
#include <linux/scatterlist.h>
#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 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_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
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 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 reservr[128];
};
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,47 @@
/* 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_sync_flush_range(void *pstart, void *pend, struct rga_scheduler_t *scheduler);
dma_addr_t rga2_dma_map_flush_page(struct page *page, int map, struct rga_scheduler_t *scheduler);
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,129 @@
/* 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;
extern struct rga_drvdata_t *rga_drvdata;
/*
* 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 */
#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,30 @@
/* 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 <linux/iommu.h>
#include <linux/iova.h>
#include <linux/dma-iommu.h>
#include "rga_drv.h"
void rga_dma_print_session_info(struct rga_dma_session *session);
int rga_dma_import_fd(int fd);
int rga_dma_release_fd(int fd);
int rga_dma_buf_get(struct rga_job *job);
int rga_dma_get_info(struct rga_job *job);
void rga_dma_put_info(struct rga_job *job);
int rga_get_format_bits(u32 format);
#endif /* #ifndef __RGA3_DMA_BUF_H__ */

View File

@@ -0,0 +1,274 @@
/* 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.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 <asm/cacheflush.h>
#include "rga.h"
#include "rga_debugger.h"
#define RGA_CORE_REG_OFFSET 0x10000
/* sample interval: 100ms */
#define RGA_LOAD_INTERVAL 100000
#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 DRIVER_VERSION "1.1.1"
#define RGA3_VERSION "2.000"
/* time limit */
#define RGA_ASYNC_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 MIN
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
#endif
#ifndef MAX
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
#endif
#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
enum {
RGA3_SCHEDULER_CORE0 = 1 << 0,
RGA3_SCHEDULER_CORE1 = 1 << 1,
RGA2_SCHEDULER_CORE0 = 1 << 2,
RGA_CORE_MASK = 0x7,
RGA_NONE_CORE = 0x0,
};
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_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;
/*
* use dma_buf directly,
* do not call dma_buf_put, such as mpi
*/
bool use_dma_buf;
};
struct rga_dma_buffer_pool {
int __user *fd;
int size;
};
struct rga_dma_session {
struct mutex lock;
/* cached dma buffer list */
struct list_head cached_list;
/* the count of buffer in the cached_list */
int buffer_count;
};
/*
* 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 dma_buf *dma_buf_src0;
struct dma_buf *dma_buf_src1;
struct dma_buf *dma_buf_dst;
struct dma_buf *dma_buf_els;
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;
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_scheduler_t {
struct device *dev;
void __iomem *rga_base;
struct clk *clks[RGA_MAX_BUS_CLK];
int num_clks;
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;
char version[16];
int core;
unsigned int core_offset;
};
struct rga_drvdata_t {
struct miscdevice miscdev;
struct rga_fence_context *fence_ctx;
struct mutex mutex; // mutex
/* 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_dma_session *dma_session;
#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);
}
#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,58 @@
/* 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 *fbcd_formats;
const uint32_t *tile_formats;
uint32_t num_of_raster_formats;
uint32_t num_of_fbcd_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;
void user_format_convert(uint32_t *df, uint32_t sf);
#endif /* __LINUX_RGA_HW_CONFIG_H_ */

View File

@@ -0,0 +1,26 @@
/* 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"
#define RGA_JOB_DONE (1 << 0)
#define RGA_JOB_ASYNC (1 << 1)
#define RGA_JOB_SYNC (1 << 2)
void rga_job_done(struct rga_scheduler_t *rga_scheduler, int ret);
int rga_commit(struct rga_req *rga_command_base, int flags);
int rga_kernel_commit(struct rga_req *rga_command_base,
struct rga_mpi_job_t *mpi_job, int flags);
#endif /* __LINUX_RKRGA_JOB_H_ */

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,486 @@
// 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"
#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)
{
seq_printf(m, "%s: v%s\n", DRIVER_DESC, DRIVER_VERSION);
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]: core = %d\n",
i, rga_scheduler->core);
seq_printf(m, "-----------------------------------\n");
}
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},
};
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);
}

View File

@@ -0,0 +1,590 @@
// 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_dma_buf: " fmt
#include "rga_dma_buf.h"
#include "rga.h"
#if CONFIG_ROCKCHIP_RGA_DEBUGGER
extern int RGA_DEBUG_CHECK_MODE;
#endif
static struct rga_scheduler_t *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 (RGA_DEBUG_MSG)
pr_info("choose core: %d\n",
rga_drvdata->rga_scheduler[i]->core);
break;
}
}
return scheduler;
}
static bool 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;
}
static void rga_convert_addr(struct rga_img_info_t *img)
{
/*
* 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 (img->rd_mode != RGA_FBC_MODE) {
img->uv_addr = img->yrgb_addr + (img->vir_w * img->vir_h);
//warning: rga3 may need /2 for all
if (is_yuv422p_format(img->format))
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;
}
static int rga_virtual_memory_check(void *vaddr, u32 w, u32 h, u32 format,
int fd)
{
int bits = 32;
int temp_data = 0;
void *one_line = NULL;
bits = rga_get_format_bits(format);
if (bits < 0)
return -1;
one_line = kzalloc(w * 4, GFP_KERNEL);
if (!one_line) {
pr_err("kzalloc fail %s[%d]\n", __func__, __LINE__);
return 0;
}
temp_data = w * (h - 1) * bits >> 3;
if (fd > 0) {
pr_info("vaddr is%p, bits is %d, fd check\n", vaddr, bits);
memcpy(one_line, (char *)vaddr + temp_data, w * bits >> 3);
pr_info("fd check ok\n");
} else {
pr_info("vir addr memory check.\n");
memcpy((void *)((char *)vaddr + temp_data), one_line,
w * bits >> 3);
pr_info("vir addr check ok.\n");
}
kfree(one_line);
return 0;
}
static int rga_dma_memory_check(struct rga_dma_buffer_t *rga_dma_buffer,
struct rga_img_info_t *img)
{
int ret = 0;
void *vaddr;
struct dma_buf *dma_buf;
dma_buf = rga_dma_buffer->dma_buf;
if (!IS_ERR_OR_NULL(dma_buf)) {
vaddr = dma_buf_vmap(dma_buf);
if (vaddr) {
ret = rga_virtual_memory_check(vaddr, img->vir_w,
img->vir_h, img->format, img->yrgb_addr);
} else {
pr_err("can't vmap the dma buffer!\n");
return -EINVAL;
}
dma_buf_vunmap(dma_buf, vaddr);
}
return ret;
}
static int rga_dma_map_buffer(struct dma_buf *dma_buf,
struct rga_dma_buffer_t *rga_dma_buffer,
enum dma_data_direction dir, struct device *rga_dev)
{
struct dma_buf_attachment *attach = NULL;
struct sg_table *sgt = NULL;
int ret = 0;
attach = dma_buf_attach(dma_buf, rga_dev);
if (IS_ERR(attach)) {
ret = -EINVAL;
pr_err("Failed to attach dma_buf\n");
goto err_get_attach;
}
sgt = dma_buf_map_attachment(attach, dir);
if (IS_ERR(sgt)) {
ret = -EINVAL;
pr_err("Failed to map src attachment\n");
goto err_get_sg;
}
rga_dma_buffer->dma_buf = dma_buf;
rga_dma_buffer->attach = attach;
rga_dma_buffer->sgt = sgt;
rga_dma_buffer->iova = sg_dma_address(sgt->sgl);
/* TODO: size for check */
rga_dma_buffer->size = sg_dma_len(sgt->sgl);
rga_dma_buffer->dir = dir;
return ret;
err_get_sg:
if (sgt)
dma_buf_unmap_attachment(attach, sgt, dir);
if (attach)
dma_buf_detach(dma_buf, attach);
err_get_attach:
if (dma_buf && (rga_dma_buffer->use_dma_buf == false))
dma_buf_put(dma_buf);
return ret;
}
static void rga_dma_unmap_buffer(struct rga_dma_buffer_t *rga_dma_buffer)
{
if (rga_dma_buffer->attach && rga_dma_buffer->sgt) {
dma_buf_unmap_attachment(rga_dma_buffer->attach,
rga_dma_buffer->sgt, rga_dma_buffer->dir);
}
if (rga_dma_buffer->attach)
dma_buf_detach(rga_dma_buffer->dma_buf, rga_dma_buffer->attach);
if (rga_dma_buffer->dma_buf && (rga_dma_buffer->use_dma_buf == false))
dma_buf_put(rga_dma_buffer->dma_buf);
}
static int rga_dma_fd_get_channel_info(struct rga_img_info_t *channel_info,
struct rga_dma_buffer_t **rga_dma_buffer,
int mmu_flag, int fd, int core)
{
int ret;
struct rga_dma_buffer_t *alloc_buffer;
struct rga_scheduler_t *scheduler = NULL;
struct dma_buf *dma_buf = NULL;
if (unlikely(!mmu_flag && fd)) {
pr_err("Fix it please enable mmu on dma fd channel\n");
return -EINVAL;
} else if (mmu_flag && fd) {
/* else, perform a single mapping to dma buffer */
alloc_buffer = kmalloc(sizeof(struct rga_dma_buffer_t),
GFP_KERNEL);
if (alloc_buffer == NULL) {
pr_err("rga2_dma_import_fd alloc error!\n");
return -ENOMEM;
}
dma_buf = dma_buf_get(fd);
if (IS_ERR(dma_buf)) {
ret = -EINVAL;
pr_err("dma_buf_get fail fd[%d]\n", fd);
kfree(alloc_buffer);
return ret;
}
alloc_buffer->cached = false;
alloc_buffer->use_dma_buf = false;
scheduler = get_scheduler(core);
if (scheduler == NULL) {
pr_err("failed to get scheduler, %s(%d)\n", __func__,
__LINE__);
kfree(alloc_buffer);
ret = -EINVAL;
return ret;
}
ret =
rga_dma_map_buffer(dma_buf, alloc_buffer,
DMA_BIDIRECTIONAL, scheduler->dev);
if (ret < 0) {
pr_err("Can't map dma-buf\n");
kfree(alloc_buffer);
return ret;
}
*rga_dma_buffer = alloc_buffer;
}
#if CONFIG_ROCKCHIP_RGA_DEBUGGER
if (RGA_DEBUG_CHECK_MODE) {
ret = rga_dma_memory_check(*rga_dma_buffer,
channel_info);
if (ret < 0) {
pr_err("Channel check memory error!\n");
/*
* Note: This error is released by external
* rga_dma_put_channel_info().
*/
return ret;
}
}
#endif
if (core == RGA2_SCHEDULER_CORE0)
channel_info->yrgb_addr = channel_info->uv_addr;
else if (core == RGA3_SCHEDULER_CORE0 || core == RGA3_SCHEDULER_CORE1) {
if (fd)
channel_info->yrgb_addr = (*rga_dma_buffer)->iova;
}
rga_convert_addr(channel_info);
return 0;
}
static int rga_dma_buf_get_channel_info(struct rga_img_info_t *channel_info,
struct rga_dma_buffer_t **rga_dma_buffer, int mmu_flag,
struct dma_buf **dma_buf, int core)
{
int ret;
struct rga_dma_buffer_t *alloc_buffer;
struct rga_scheduler_t *scheduler = NULL;
if (unlikely(!mmu_flag && *dma_buf)) {
pr_err("Fix it please enable mmu on dma buf channel\n");
return -EINVAL;
} else if (mmu_flag && *dma_buf) {
/* perform a single mapping to dma buffer */
alloc_buffer =
kmalloc(sizeof(struct rga_dma_buffer_t),
GFP_KERNEL);
if (alloc_buffer == NULL) {
pr_err("rga2_dma_import_fd alloc error!\n");
return -ENOMEM;
}
alloc_buffer->use_dma_buf = true;
scheduler = get_scheduler(core);
if (scheduler == NULL) {
pr_err("failed to get scheduler, %s(%d)\n", __func__,
__LINE__);
kfree(alloc_buffer);
ret = -EINVAL;
return ret;
}
ret =
rga_dma_map_buffer(*dma_buf, alloc_buffer,
DMA_BIDIRECTIONAL, scheduler->dev);
if (ret < 0) {
pr_err("Can't map dma-buf\n");
kfree(alloc_buffer);
return ret;
}
*rga_dma_buffer = alloc_buffer;
}
#if CONFIG_ROCKCHIP_RGA_DEBUGGER
if (RGA_DEBUG_CHECK_MODE) {
ret = rga_dma_memory_check(*rga_dma_buffer,
channel_info);
if (ret < 0) {
pr_err("Channel check memory error!\n");
/*
* Note: This error is released by external
* rga_dma_put_channel_info().
*/
return ret;
}
}
#endif
if (core == RGA2_SCHEDULER_CORE0)
channel_info->yrgb_addr = channel_info->uv_addr;
else if (core == RGA3_SCHEDULER_CORE0 || core == RGA3_SCHEDULER_CORE1)
channel_info->yrgb_addr = (*rga_dma_buffer)->iova;
rga_convert_addr(channel_info);
return 0;
}
static void rga_dma_put_channel_info(struct rga_dma_buffer_t **rga_dma_buffer)
{
struct rga_dma_buffer_t *buffer;
buffer = *rga_dma_buffer;
if (buffer == NULL)
return;
rga_dma_unmap_buffer(buffer);
kfree(buffer);
*rga_dma_buffer = NULL;
}
int rga_dma_buf_get(struct rga_job *job)
{
int ret = -EINVAL;
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->yrgb_addr) {
job->dma_buf_src0 = dma_buf_get(src0->yrgb_addr);
if (IS_ERR(job->dma_buf_src0)) {
ret = -EINVAL;
pr_err("%s src0 dma_buf_get fail fd[%lu]\n",
__func__, (unsigned long)src0->yrgb_addr);
return ret;
}
}
}
if (likely(dst != NULL)) {
mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 10) & 1);
if (mmu_flag && dst->yrgb_addr) {
job->dma_buf_dst = dma_buf_get(dst->yrgb_addr);
if (IS_ERR(job->dma_buf_dst)) {
ret = -EINVAL;
pr_err("%s dst dma_buf_get fail fd[%lu]\n",
__func__, (unsigned long)dst->yrgb_addr);
return ret;
}
}
}
if (src1 != NULL) {
mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 9) & 1);
if (mmu_flag && src1->yrgb_addr) {
job->dma_buf_src1 = dma_buf_get(src1->yrgb_addr);
if (IS_ERR(job->dma_buf_src0)) {
ret = -EINVAL;
pr_err("%s src1 dma_buf_get fail fd[%lu]\n",
__func__, (unsigned long)src1->yrgb_addr);
return ret;
}
}
}
if (els != NULL) {
mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 11) & 1);
if (mmu_flag && els->yrgb_addr) {
job->dma_buf_els = dma_buf_get(els->yrgb_addr);
if (IS_ERR(job->dma_buf_els)) {
ret = -EINVAL;
pr_err("%s els dma_buf_get fail fd[%lu]\n",
__func__, (unsigned long)els->yrgb_addr);
return ret;
}
}
}
return 0;
}
int rga_dma_get_info(struct rga_job *job)
{
int ret = 0;
uint32_t 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;
/* src0 channel */
if (likely(src0 != NULL)) {
mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 8) & 1);
if (job->dma_buf_src0 == NULL) {
ret = rga_dma_fd_get_channel_info(src0,
&job->rga_dma_buffer_src0, mmu_flag,
src0->yrgb_addr, job->core);
} else {
ret = rga_dma_buf_get_channel_info(src0,
&job->rga_dma_buffer_src0, mmu_flag,
&job->dma_buf_src0, job->core);
}
if (unlikely(ret < 0)) {
pr_err("src0 channel get info error!\n");
goto src0_channel_err;
}
}
/* dst channel */
if (likely(dst != NULL)) {
if (job->dma_buf_dst == NULL && dst != NULL) {
mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 10) & 1);
ret = rga_dma_fd_get_channel_info(dst,
&job->rga_dma_buffer_dst, mmu_flag,
dst->yrgb_addr, job->core);
} else if (dst != NULL) {
ret = rga_dma_buf_get_channel_info(dst,
&job->rga_dma_buffer_dst, mmu_flag,
&job->dma_buf_dst, job->core);
}
if (unlikely(ret < 0)) {
pr_err("dst channel get info error!\n");
goto dst_channel_err;
}
}
/* src1 channel */
if (src1 != NULL) {
mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 9) & 1);
if (job->dma_buf_src1 == NULL) {
ret = rga_dma_fd_get_channel_info(src1,
&job->rga_dma_buffer_src1, mmu_flag,
src1->yrgb_addr, job->core);
} else {
ret = rga_dma_buf_get_channel_info(src1,
&job->rga_dma_buffer_src1, mmu_flag,
&job->dma_buf_src1, job->core);
}
if (unlikely(ret < 0)) {
pr_err("src1 channel get info error!\n");
goto src1_channel_err;
}
}
/* els channel */
if (els != NULL) {
mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 11) & 1);
if (job->dma_buf_els == NULL && els != NULL) {
ret = rga_dma_fd_get_channel_info(els,
&job->rga_dma_buffer_els, mmu_flag,
els->yrgb_addr, job->core);
} else if (els != NULL) {
ret = rga_dma_buf_get_channel_info(els,
&job->rga_dma_buffer_els, mmu_flag,
&job->dma_buf_els, job->core);
}
if (unlikely(ret < 0)) {
pr_err("els channel get info error!\n");
goto els_channel_err;
}
}
return 0;
els_channel_err:
rga_dma_put_channel_info(&job->rga_dma_buffer_els);
dst_channel_err:
rga_dma_put_channel_info(&job->rga_dma_buffer_dst);
src1_channel_err:
rga_dma_put_channel_info(&job->rga_dma_buffer_src1);
src0_channel_err:
rga_dma_put_channel_info(&job->rga_dma_buffer_src0);
return ret;
}
void rga_dma_put_info(struct rga_job *job)
{
rga_dma_put_channel_info(&job->rga_dma_buffer_src0);
rga_dma_put_channel_info(&job->rga_dma_buffer_src1);
rga_dma_put_channel_info(&job->rga_dma_buffer_dst);
rga_dma_put_channel_info(&job->rga_dma_buffer_els);
}

View File

@@ -0,0 +1,758 @@
// 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: " fmt
#include "rga2_reg_info.h"
#include "rga3_reg_info.h"
#include "rga_dma_buf.h"
#include "rga_job.h"
#include "rga_fence.h"
#include "rga_hw_config.h"
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
#include <linux/pm_runtime.h>
#include <linux/dma-buf.h>
#endif
#include "rga2_mmu_info.h"
#include "rga_debugger.h"
struct rga2_mmu_info_t rga2_mmu_info;
struct rga_drvdata_t *rga_drvdata;
static const struct rga_backend_ops rga3_ops = {
.get_version = rga3_get_version,
.set_reg = rga3_set_reg,
.init_reg = rga3_init_reg,
.soft_reset = rga3_soft_reset
};
static const struct rga_backend_ops rga2_ops = {
.get_version = rga2_get_version,
.set_reg = rga2_set_reg,
.init_reg = rga2_init_reg,
.soft_reset = rga2_soft_reset
};
int rga_mpi_commit(struct rga_req *cmd, struct rga_mpi_job_t *mpi_job)
{
int ret;
ret = rga_kernel_commit(cmd, mpi_job, RGA_BLIT_SYNC);
if (ret < 0) {
pr_err("rga_kernel_commit failed\n");
return ret;
}
return ret;
}
EXPORT_SYMBOL_GPL(rga_mpi_commit);
#ifndef CONFIG_ROCKCHIP_FPGA
static int rga_power_enable(struct rga_scheduler_t *rga_scheduler)
{
int ret = -EINVAL;
int i;
ret = pm_runtime_get_sync(rga_scheduler->dev);
if (ret < 0) {
pr_err("failed to get pm runtime, ret = %d\n",
ret);
return ret;
}
for (i = 0; i < rga_scheduler->num_clks; i++) {
if (!IS_ERR(rga_scheduler->clks[i])) {
ret = clk_prepare_enable(rga_scheduler->clks[i]);
if (ret < 0)
goto err_enable_clk;
}
}
return 0;
err_enable_clk:
for (--i; i >= 0; --i)
if (!IS_ERR(rga_scheduler->clks[i]))
clk_disable_unprepare(rga_scheduler->clks[i]);
return ret;
}
static int rga_power_disable(struct rga_scheduler_t *rga_scheduler)
{
int i;
for (i = rga_scheduler->num_clks - 1; i >= 0; i--)
if (!IS_ERR(rga_scheduler->clks[i]))
clk_disable_unprepare(rga_scheduler->clks[i]);
pm_runtime_put(rga_scheduler->dev);
return 0;
}
#endif //CONFIG_ROCKCHIP_FPGA
static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
{
struct rga_drvdata_t *rga = rga_drvdata;
struct rga_req req_rga;
int ret = 0;
int i = 0;
int major_version = 0, minor_version = 0;
char version[16] = { 0 };
if (!rga) {
pr_err("rga_drvdata is null, rga is not init\n");
return -ENODEV;
}
if (RGA_DEBUG_NONUSE) {
return 0;
}
switch (cmd) {
case RGA_BLIT_SYNC:
case RGA_BLIT_ASYNC:
if (unlikely(copy_from_user(&req_rga,
(struct rga_req *)arg, sizeof(struct rga_req)))) {
pr_err("copy_from_user failed\n");
ret = -EFAULT;
break;
}
if (RGA_DEBUG_MSG)
rga_cmd_print_debug_info(&req_rga);
ret = rga_commit(&req_rga, cmd);
if (ret < 0) {
pr_err("rga_commit failed\n");
break;
}
if (copy_to_user((struct rga_req *)arg,
&req_rga, sizeof(struct rga_req))) {
pr_err("copy_to_user failed\n");
ret = -EFAULT;
break;
}
break;
case RGA_CACHE_FLUSH:
case RGA_FLUSH:
case RGA_GET_RESULT:
break;
case RGA_GET_VERSION:
sscanf(rga->rga_scheduler[i]->version, "%x.%x.%*x",
&major_version, &minor_version);
snprintf(version, 5, "%x.%02x", major_version, minor_version);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
/* TODO: userspcae to get version */
if (copy_to_user((void *)arg, version, sizeof(version)))
ret = -EFAULT;
#else
if (copy_to_user((void *)arg, RGA3_VERSION,
sizeof(RGA3_VERSION)))
ret = -EFAULT;
#endif
break;
case RGA2_GET_VERSION:
for (i = 0; i < rga->num_of_scheduler; i++) {
if (rga->rga_scheduler[i]->ops == &rga2_ops) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
if (copy_to_user((void *)arg, rga->rga_scheduler[i]->version,
sizeof(rga->rga_scheduler[i]->version)))
ret = -EFAULT;
#else
if (copy_to_user((void *)arg, RGA3_VERSION,
sizeof(RGA3_VERSION)))
ret = -EFAULT;
#endif
else
ret = true;
break;
}
}
/* This will indicate that the RGA2 version number cannot be obtained. */
if (ret != true)
ret = -EFAULT;
break;
case RGA_IMPORT_DMA:
case RGA_RELEASE_DMA:
default:
pr_err("unknown ioctl cmd!\n");
ret = -EINVAL;
break;
}
return ret;
}
#ifdef CONFIG_ROCKCHIP_RGA_DEBUGGER
static int rga_debugger_init(struct rga_debugger **debugger_p)
{
struct rga_debugger *debugger;
*debugger_p = kzalloc(sizeof(struct rga_debugger), GFP_KERNEL);
if (*debugger_p == NULL) {
pr_err("can not alloc for rga debugger\n");
return -ENOMEM;
}
debugger = *debugger_p;
#ifdef CONFIG_ROCKCHIP_RGA_DEBUG_FS
mutex_init(&debugger->debugfs_lock);
INIT_LIST_HEAD(&debugger->debugfs_entry_list);
#endif
#ifdef CONFIG_ROCKCHIP_RGA_PROC_FS
mutex_init(&debugger->procfs_lock);
INIT_LIST_HEAD(&debugger->procfs_entry_list);
#endif
rga_debugfs_init();
rga_procfs_init();
return 0;
}
static int rga_debugger_remove(struct rga_debugger **debugger_p)
{
rga_debugfs_remove();
rga_procfs_remove();
kfree(*debugger_p);
*debugger_p = NULL;
return 0;
}
#endif
static int rga_open(struct inode *inode, struct file *file)
{
return nonseekable_open(inode, file);
}
static int rga_release(struct inode *inode, struct file *file)
{
return 0;
}
static irqreturn_t rga3_irq_handler(int irq, void *data)
{
struct rga_scheduler_t *rga_scheduler = data;
if (RGA_DEBUG_INT_FLAG)
pr_info("irqthread INT[%x],STATS0[%x], STATS1[%x]\n",
rga_read(RGA3_INT_RAW, rga_scheduler),
rga_read(RGA3_STATUS0, rga_scheduler),
rga_read(RGA3_STATUS1, rga_scheduler));
/* TODO: if error interrupt then soft reset hardware */
//rga_scheduler->ops->soft_reset(job->core);
/*clear INT */
rga_write(1, RGA3_INT_CLR, rga_scheduler);
return IRQ_WAKE_THREAD;
}
static irqreturn_t rga3_irq_thread(int irq, void *data)
{
struct rga_scheduler_t *rga_scheduler = data;
struct rga_job *job;
job = rga_scheduler->running_job;
if (!job) {
pr_err("running job is invaild on irq thread\n");
return IRQ_HANDLED;
}
if (RGA_DEBUG_INT_FLAG)
pr_info("irq INT[%x], STATS0[%x], STATS1[%x]\n",
rga_read(RGA3_INT_RAW, rga_scheduler),
rga_read(RGA3_STATUS0, rga_scheduler),
rga_read(RGA3_STATUS1, rga_scheduler));
rga_job_done(rga_scheduler, 0);
return IRQ_HANDLED;
}
static irqreturn_t rga2_irq_handler(int irq, void *data)
{
struct rga_scheduler_t *rga_scheduler = data;
if (RGA_DEBUG_INT_FLAG)
pr_info("irqthread INT[%x],STATS0[%x]\n",
rga_read(RGA2_INT, rga_scheduler), rga_read(RGA2_STATUS,
rga_scheduler));
/*if error interrupt then soft reset hardware */
//warning
if (rga_read(RGA2_INT, rga_scheduler) & 0x01) {
pr_err("err irq! INT[%x],STATS0[%x]\n",
rga_read(RGA2_INT, rga_scheduler),
rga_read(RGA2_STATUS, rga_scheduler));
rga_scheduler->ops->soft_reset(rga_scheduler);
}
/*clear INT */
rga_write(rga_read(RGA2_INT, rga_scheduler) | (0x1 << 4) | (0x1 << 5) |
(0x1 << 6) | (0x1 << 7), RGA2_INT, rga_scheduler);
return IRQ_WAKE_THREAD;
}
static irqreturn_t rga2_irq_thread(int irq, void *data)
{
struct rga_scheduler_t *rga_scheduler = data;
struct rga_job *job;
job = rga_scheduler->running_job;
if (!job)
return IRQ_HANDLED;
if (RGA_DEBUG_INT_FLAG)
pr_info("irq INT[%x], STATS0[%x]\n",
rga_read(RGA2_INT, rga_scheduler), rga_read(RGA2_STATUS,
rga_scheduler));
rga_job_done(rga_scheduler, 0);
return IRQ_HANDLED;
}
const struct file_operations rga_fops = {
.owner = THIS_MODULE,
.open = rga_open,
.release = rga_release,
.unlocked_ioctl = rga_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = rga_ioctl,
#endif
};
static struct miscdevice rga_dev = {
.name = "rga",
.fops = &rga_fops,
};
static const char *const old_rga2_clks[] = {
"aclk_rga",
"hclk_rga",
"clk_rga",
};
static const char *const rk3588_rga2_clks[] = {
"aclk_rga2",
"hclk_rga2",
"clk_rga2",
};
static const char *const rga3_core_0_clks[] = {
"aclk_rga3_0",
"hclk_rga3_0",
"clk_rga3_0",
};
static const char *const rga3_core_1_clks[] = {
"aclk_rga3_1",
"hclk_rga3_1",
"clk_rga3_1",
};
static const struct rga_irqs_data_t single_rga2_irqs[] = {
{"rga2_irq", rga2_irq_handler, rga2_irq_thread}
};
static const struct rga_irqs_data_t rga3_core0_irqs[] = {
{"rga3_core0_irq", rga3_irq_handler, rga3_irq_thread}
};
static const struct rga_irqs_data_t rga3_core1_irqs[] = {
{"rga3_core1_irq", rga3_irq_handler, rga3_irq_thread}
};
static const struct rga_match_data_t old_rga2_match_data = {
.clks = old_rga2_clks,
.num_clks = ARRAY_SIZE(old_rga2_clks),
.irqs = single_rga2_irqs,
.num_irqs = ARRAY_SIZE(single_rga2_irqs)
};
static const struct rga_match_data_t rk3588_rga2_match_data = {
.clks = rk3588_rga2_clks,
.num_clks = ARRAY_SIZE(rk3588_rga2_clks),
.irqs = single_rga2_irqs,
.num_irqs = ARRAY_SIZE(single_rga2_irqs)
};
static const struct rga_match_data_t rga3_core0_match_data = {
.clks = rga3_core_0_clks,
.num_clks = ARRAY_SIZE(rga3_core_0_clks),
.irqs = rga3_core0_irqs,
.num_irqs = ARRAY_SIZE(rga3_core0_irqs)
};
static const struct rga_match_data_t rga3_core1_match_data = {
.clks = rga3_core_1_clks,
.num_clks = ARRAY_SIZE(rga3_core_1_clks),
.irqs = rga3_core1_irqs,
.num_irqs = ARRAY_SIZE(rga3_core1_irqs)
};
static const struct of_device_id rga3_core0_dt_ids[] = {
{
.compatible = "rockchip,rga3_core0",
.data = &rga3_core0_match_data,
},
{},
};
static const struct of_device_id rga3_core1_dt_ids[] = {
{
.compatible = "rockchip,rga3_core1",
.data = &rga3_core1_match_data,
},
{},
};
static const struct of_device_id rga2_dt_ids[] = {
{
.compatible = "rockchip,rga2_core0",
.data = &rk3588_rga2_match_data,
},
{
.compatible = "rockchip,rga2",
.data = &old_rga2_match_data,
},
};
static void init_scheduler(struct rga_scheduler_t *rga_scheduler,
const char *name)
{
spin_lock_init(&rga_scheduler->irq_lock);
INIT_LIST_HEAD(&rga_scheduler->todo_list);
init_waitqueue_head(&rga_scheduler->job_done_wq);
if (!strcmp(name, "rga3_core0")) {
rga_scheduler->ops = &rga3_ops;
/* TODO: get by hw version */
rga_scheduler->data = &rga3_data;
rga_scheduler->core = RGA3_SCHEDULER_CORE0;
} else if (!strcmp(name, "rga3_core1")) {
rga_scheduler->ops = &rga3_ops;
rga_scheduler->data = &rga3_data;
rga_scheduler->core = RGA3_SCHEDULER_CORE1;
} else if (!strcmp(name, "rga2")) {
rga_scheduler->ops = &rga2_ops;
rga_scheduler->data = &rga2e_data;
rga_scheduler->core = RGA2_SCHEDULER_CORE0;
}
}
static int rga_drv_probe(struct platform_device *pdev)
{
struct rga_drvdata_t *data = rga_drvdata;
struct resource *res;
int ret = 0;
const struct of_device_id *match = NULL;
struct device *dev = &pdev->dev;
const struct rga_match_data_t *match_data;
int i, irq;
struct rga_scheduler_t *rga_scheduler = NULL;
if (!pdev->dev.of_node)
return -EINVAL;
if (!strcmp(dev_driver_string(dev), "rga3_core0"))
match = of_match_device(rga3_core0_dt_ids, dev);
else if (!strcmp(dev_driver_string(dev), "rga3_core1"))
match = of_match_device(rga3_core1_dt_ids, dev);
else if (!strcmp(dev_driver_string(dev), "rga2"))
match = of_match_device(rga2_dt_ids, dev);
if (!match) {
dev_err(dev, "%s missing DT entry!\n", dev_driver_string(dev));
return -EINVAL;
}
rga_scheduler =
devm_kzalloc(&pdev->dev, sizeof(struct rga_scheduler_t),
GFP_KERNEL);
if (rga_scheduler == NULL) {
pr_err("failed to allocate scheduler. dev name = %s\n",
dev_driver_string(dev));
return -ENOMEM;
}
init_scheduler(rga_scheduler,
dev_driver_string(dev));
rga_scheduler->dev = &pdev->dev;
/* map the registers */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
pr_err("get memory resource failed.\n");
return -ENXIO;
}
rga_scheduler->rga_base =
devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!rga_scheduler->rga_base) {
pr_err("ioremap failed\n");
ret = -ENOENT;
return ret;
}
/* get the IRQ */
match_data = match->data;
/* there are irq names in dts */
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "no irq %s in dts\n",
match_data->irqs[0].name);
return irq;
}
rga_scheduler->irq = irq;
pr_err("%s, irq = %d, match scheduler\n",
match_data->irqs[0].name, irq);
ret = devm_request_threaded_irq(dev, irq,
match_data->irqs[0].irq_hdl,
match_data->irqs[0].irq_thread, IRQF_SHARED,
dev_driver_string(dev),
rga_scheduler);
if (ret < 0) {
pr_err("request irq name: %s failed: %d\n",
match_data->irqs[0].name, ret);
return ret;
}
#ifndef CONFIG_ROCKCHIP_FPGA
for (i = 0; i < match_data->num_clks; i++) {
struct clk *clk = devm_clk_get(dev, match_data->clks[i]);
if (IS_ERR(clk))
pr_err("failed to get %s\n", match_data->clks[i]);
rga_scheduler->clks[i] = clk;
}
rga_scheduler->num_clks = match_data->num_clks;
#endif
platform_set_drvdata(pdev, rga_scheduler);
/* PM init */
#ifndef CONFIG_ROCKCHIP_FPGA
pm_runtime_enable(&pdev->dev);
ret = rga_power_enable(rga_scheduler);
if (ret)
return ret;
#endif //CONFIG_ROCKCHIP_FPGA
rga_scheduler->ops->get_version(rga_scheduler);
pr_err("Driver loaded successfully rga[%d] ver:%s\n", i,
rga_scheduler->version);
data->rga_scheduler[data->num_of_scheduler] = rga_scheduler;
data->num_of_scheduler++;
pr_err("probe successfully\n");
return 0;
}
static int rga_drv_remove(struct platform_device *pdev)
{
struct rga_scheduler_t *rga_scheduler =
platform_get_drvdata(pdev);
#ifndef CONFIG_ROCKCHIP_FPGA
rga_power_disable(rga_scheduler);
pm_runtime_disable(&pdev->dev);
#endif //CONFIG_ROCKCHIP_FPGA
return 0;
}
static struct platform_driver rga3_core0_driver = {
.probe = rga_drv_probe,
.remove = rga_drv_remove,
.driver = {
.name = "rga3_core0",
.of_match_table = of_match_ptr(rga3_core0_dt_ids),
},
};
static struct platform_driver rga3_core1_driver = {
.probe = rga_drv_probe,
.remove = rga_drv_remove,
.driver = {
.name = "rga3_core1",
.of_match_table = of_match_ptr(rga3_core1_dt_ids),
},
};
static struct platform_driver rga2_driver = {
.probe = rga_drv_probe,
.remove = rga_drv_remove,
.driver = {
.name = "rga2",
.of_match_table = of_match_ptr(rga2_dt_ids),
},
};
static int __init rga_init(void)
{
int ret;
int order = 0;
uint32_t *buf_p;
uint32_t *buf;
/*
* malloc pre scale mid buf mmu table:
* RGA2_PHY_PAGE_SIZE * channel_num * address_size
*/
order = get_order(RGA2_PHY_PAGE_SIZE * 3 * sizeof(buf_p));
buf_p = (uint32_t *) __get_free_pages(GFP_KERNEL | GFP_DMA32, order);
if (buf_p == NULL) {
pr_err("Can not alloc pages for mmu_page_table\n");
return -ENOMEM;
}
rga2_mmu_info.buf_virtual = buf_p;
rga2_mmu_info.buf_order = order;
#if (defined(CONFIG_ARM) && defined(CONFIG_ARM_LPAE))
buf =
(uint32_t *) (uint32_t)
virt_to_phys((void *)((unsigned long)buf_p));
#else
buf = (uint32_t *) virt_to_phys((void *)((unsigned long)buf_p));
#endif
rga2_mmu_info.buf = buf;
rga2_mmu_info.front = 0;
rga2_mmu_info.back = RGA2_PHY_PAGE_SIZE * 3;
rga2_mmu_info.size = RGA2_PHY_PAGE_SIZE * 3;
order = get_order(RGA2_PHY_PAGE_SIZE * sizeof(struct page *));
rga2_mmu_info.pages =
(struct page **)__get_free_pages(GFP_KERNEL | GFP_DMA32, order);
if (rga2_mmu_info.pages == NULL)
pr_err("Can not alloc pages for rga2_mmu_info.pages\n");
rga2_mmu_info.pages_order = order;
rga_drvdata = kzalloc(sizeof(struct rga_drvdata_t), GFP_KERNEL);
if (rga_drvdata == NULL) {
pr_err("failed to allocate driver data.\n");
return -ENOMEM;
}
mutex_init(&rga_drvdata->mutex);
mutex_init(&rga_drvdata->lock);
wake_lock_init(&rga_drvdata->wake_lock, WAKE_LOCK_SUSPEND, "rga");
ret = platform_driver_register(&rga2_driver);
if (ret != 0) {
pr_err("Platform device rga2_driver register failed (%d).\n", ret);
return ret;
}
ret = platform_driver_register(&rga3_core0_driver);
if (ret != 0) {
pr_err("Platform device rga3_core0_driver register failed (%d).\n", ret);
return ret;
}
ret = platform_driver_register(&rga3_core1_driver);
if (ret != 0) {
pr_err("Platform device rga3_core1_driver register failed (%d).\n", ret);
return ret;
}
rga_drvdata->fence_ctx = rga_fence_context_alloc();
if (IS_ERR(rga_drvdata->fence_ctx)) {
pr_err("failed to allocate fence context for RGA\n");
ret = PTR_ERR(rga_drvdata->fence_ctx);
return ret;
}
ret = misc_register(&rga_dev);
if (ret) {
pr_err("cannot register miscdev (%d)\n", ret);
return ret;
}
#ifdef CONFIG_ROCKCHIP_RGA_DEBUGGER
rga_debugger_init(&rga_drvdata->debugger);
#endif
pr_info("Module initialized. v%s\n", DRIVER_VERSION);
return 0;
}
static void __exit rga_exit(void)
{
free_pages((unsigned long)rga2_mmu_info.buf_virtual,
rga2_mmu_info.buf_order);
free_pages((unsigned long)rga2_mmu_info.pages, rga2_mmu_info.pages_order);
#ifdef CONFIG_ROCKCHIP_RGA_DEBUGGER
rga_debugger_remove(&rga_drvdata->debugger);
#endif
wake_lock_destroy(&rga_drvdata->wake_lock);
rga_fence_context_free(rga_drvdata->fence_ctx);
platform_driver_unregister(&rga3_core0_driver);
platform_driver_unregister(&rga3_core1_driver);
platform_driver_unregister(&rga2_driver);
misc_deregister(&(rga_drvdata->miscdev));
kfree(rga_drvdata);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
module_init(rga_init);
#else
late_initcall(rga_init);
#endif
#else
fs_initcall(rga_init);
#endif
module_exit(rga_exit);
/* Module information */
MODULE_AUTHOR("putin.li@rock-chips.com");
MODULE_DESCRIPTION("Driver for rga device");
MODULE_LICENSE("GPL");

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,370 @@
// 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_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_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_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_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_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,
};
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),
.fbcd_formats = rga3_fbcd_format,
.num_of_raster_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),
.fbcd_formats = rga3_fbcd_format,
.num_of_raster_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),
.fbcd_formats = rga3_fbcd_format,
.num_of_raster_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 = { 8128, 8128 },
.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,
};
void 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;
}
}

View File

@@ -0,0 +1,797 @@
// 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_hw_config.h"
#include "rga2_mmu_info.h"
static struct rga_scheduler_t *get_scheduler(struct rga_job *job)
{
struct rga_scheduler_t *scheduler = NULL;
int i;
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
if (job->core == rga_drvdata->rga_scheduler[i]->core) {
scheduler = rga_drvdata->rga_scheduler[i];
if (RGA_DEBUG_MSG)
pr_info("job choose core: %d\n",
rga_drvdata->rga_scheduler[i]->core);
break;
}
}
return scheduler;
}
static void rga_job_free(struct rga_job *job)
{
if (job->out_fence)
dma_fence_put(job->out_fence);
free_page((unsigned long)job);
}
static int rga_job_cleanup(struct rga_job *job)
{
rga_job_free(job);
return 0;
}
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;
job->timestamp = 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;
}
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;
ret = rga_dma_get_info(job);
if (ret < 0) {
pr_err("dma buf get failed");
return ret;
}
ret = scheduler->ops->init_reg(job);
if (ret < 0) {
pr_err("init reg failed");
return ret;
}
ret = scheduler->ops->set_reg(job, scheduler);
if (ret < 0) {
pr_err("set reg failed");
return ret;
}
/* for debug */
if (RGA_DEBUG_MSG)
print_job_info(job);
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 on ASYNC mode before hw run */
if (job->ret < 0) {
pr_err("some error on rga_job_run, %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->out_fence)
dma_fence_signal(job->out_fence);
if (job->flags & RGA_JOB_ASYNC)
rga_job_cleanup(job);
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;
spin_lock_irqsave(&rga_scheduler->irq_lock, flags);
job = rga_scheduler->running_job;
rga_scheduler->running_job = NULL;
spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags);
job->flags |= RGA_JOB_DONE;
job->ret = ret;
now = ktime_get();
if (RGA_DEBUG_TIME)
pr_err("%s use time = %lld\n", __func__,
ktime_to_us(ktime_sub(now, job->timestamp)));
rga2_dma_flush_cache_for_virtual_address(&job->vir_page_table, rga_scheduler);
rga_dma_put_info(job);
if (job->out_fence)
dma_fence_signal(job->out_fence);
wake_up(&rga_scheduler->job_done_wq);
if (job->flags & RGA_JOB_ASYNC)
rga_job_cleanup(job);
rga_job_next(rga_scheduler);
}
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_src0(const struct rga_hw_data *data,
struct rga_img_info_t *src0)
{
int i;
bool matched = false;
int format;
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;
for (i = 0; i < data->win[0].num_of_raster_formats; i++) {
if (format == data->win[0].raster_formats[i]) {
matched = true;
break;
}
}
if (!matched)
return false;
return true;
}
static bool rga_check_src1(const struct rga_hw_data *data,
struct rga_img_info_t *src1)
{
int i;
bool matched = false;
int format;
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;
for (i = 0; i < data->win[1].num_of_raster_formats; i++) {
if (format == data->win[1].raster_formats[i]) {
matched = true;
break;
}
}
if (!matched)
return false;
return true;
}
static bool rga_check_dst(const struct rga_hw_data *data,
struct rga_img_info_t *dst)
{
int i;
bool matched = false;
int format;
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;
for (i = 0; i < data->win[2].num_of_raster_formats; i++) {
if (format == data->win[2].raster_formats[i]) {
matched = true;
break;
}
}
if (!matched)
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;
}
static 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 */
/* TODO: valid value */
if (rga_base->core > RGA_NONE_CORE)
return rga_base->core;
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 (RGA_DEBUG_MSG)
pr_err("start policy on core = %d", scheduler->core);
if ((scheduler->core != RGA2_SCHEDULER_CORE0) &&
(src0->uv_addr > 0 || src1->uv_addr > 0 ||
dst->uv_addr > 0)) {
if (RGA_DEBUG_MSG)
pr_err("rga3 can not support viraddr\n");
continue;
}
if (feature > 0) {
if (!(feature & data->feature)) {
if (RGA_DEBUG_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 (RGA_DEBUG_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 (RGA_DEBUG_MSG)
pr_err("core = %d, ABB break on rd_mode",
scheduler->core);
continue;
}
}
if (!rga_check_scale(data, rga_base)) {
if (RGA_DEBUG_MSG)
pr_err("core = %d, break on rga_check_scale",
scheduler->core);
continue;
}
if (!rga_check_src0(data, src0)) {
if (RGA_DEBUG_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 (RGA_DEBUG_MSG)
pr_err("core = %d, break on rga_check_src1",
scheduler->core);
continue;
}
}
}
if (!rga_check_dst(data, dst)) {
if (RGA_DEBUG_MSG)
pr_err("core = %d, break on rga_check_dst",
scheduler->core);
continue;
}
optional_cores |= scheduler->core;
}
if (RGA_DEBUG_MSG)
pr_info("optional_cores = %d\n", optional_cores);
if (optional_cores == 0) {
core = -1;
pr_err("invalid function policy\n");
goto finish;
}
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 (RGA_DEBUG_MSG)
pr_info("assign core: %d\n", core);
return core;
}
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 = get_scheduler(job);
if (scheduler == NULL) {
pr_err("failed to get scheduler, %s(%d)\n", __func__, __LINE__);
return NULL;
}
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;
if (job->ret == -ETIMEDOUT)
rga_scheduler->ops->soft_reset(rga_scheduler);
spin_lock_irqsave(&rga_scheduler->irq_lock, flags);
/* invalid job */
if (job == rga_scheduler->running_job) {
rga_scheduler->running_job = NULL;
rga_job_cleanup(job);
}
spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags);
}
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_ASYNC_TIMEOUT_DELAY);
if (left_time <= 0) {
ret = left_time < 0 ? left_time : -ETIMEDOUT;
if (ret < 0)
rga_scheduler->ops->soft_reset(rga_scheduler);
return ret;
}
now = ktime_get();
if (RGA_DEBUG_TIME)
pr_err("%s use time = %lld\n", __func__,
ktime_to_us(ktime_sub(now, job->timestamp)));
return 0;
}
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 (RGA_DEBUG_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_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;
}
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);
//TODO: job timeout clean
if (RGA_DEBUG_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__);
goto invalid_job;
}
/* if input fence is valid */
} else if (ret == 0) {
/*
* because fd can not pass on dma_fence_callback,
* 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;
}
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__);
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__);
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) {
pr_err("failed to wait rga job! May be timeout\n");
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_kernel_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;
}
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__);
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) {
pr_err("failed to wait rga job! May be timeout\n");
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;
}