android13/kernel-5.10/drivers/video/rockchip/rga3/rga2_reg_info.c

2765 lines
75 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Rockchip Electronics Co., Ltd.
*
* Author: Huang Lee <Putin.li@rock-chips.com>
*/
#define pr_fmt(fmt) "rga2_reg: " fmt
#include "rga2_reg_info.h"
#include "rga_dma_buf.h"
#include "rga_iommu.h"
#include "rga_common.h"
#include "rga_hw_config.h"
#include "rga_debugger.h"
unsigned int rga2_rop_code[256] = {
0x00000007, 0x00000451, 0x00006051, 0x00800051,
0x00007041, 0x00800041, 0x00804830, 0x000004f0,//0
0x00800765, 0x000004b0, 0x00000065, 0x000004f4,
0x00000075, 0x000004e6, 0x00804850, 0x00800005,
0x00006850, 0x00800050, 0x00805028, 0x00000568,
0x00804031, 0x00000471, 0x002b6071, 0x018037aa,//1
0x008007aa, 0x00036071, 0x00002c6a, 0x00803631,
0x00002d68, 0x00802721, 0x008002d0, 0x000006d0,
0x0080066e, 0x00000528, 0x00000066, 0x0000056c,
0x018007aa, 0x0002e06a, 0x00003471, 0x00834031,//2
0x00800631, 0x0002b471, 0x00006071, 0x008037aa,
0x000036d0, 0x008002d4, 0x00002d28, 0x000006d4,
0x0000006e, 0x00000565, 0x00003451, 0x00800006,
0x000034f0, 0x00834830, 0x00800348, 0x00000748,//3
0x00002f48, 0x0080034c, 0x000034b0, 0x0000074c,
0x00000031, 0x00834850, 0x000034e6, 0x00800071,
0x008006f4, 0x00000431, 0x018007a1, 0x00b6e870,
0x00000074, 0x0000046e, 0x00002561, 0x00802f28,//4
0x00800728, 0x0002a561, 0x000026c2, 0x008002c6,
0x00007068, 0x018035aa, 0x00002c2a, 0x000006c6,
0x0000006c, 0x00000475, 0x000024e2, 0x008036b0,
0x00804051, 0x00800004, 0x00800251, 0x00000651,
0x00002e4a, 0x0080024e, 0x00000028, 0x00824842,
0x000024a2, 0x0000064e, 0x000024f4, 0x00800068,//5
0x008006b0, 0x000234f0, 0x00002741, 0x00800345,
0x00003651, 0x00800255, 0x00000030, 0x00834051,
0x00a34842, 0x000002b0, 0x00800271, 0x0002b651,
0x00800368, 0x0002a741, 0x0000364e, 0x00806830,//6
0x00006870, 0x008037a2, 0x00003431, 0x00000745,
0x00002521, 0x00000655, 0x0000346e, 0x00800062,
0x008002f0, 0x000236d0, 0x000026d4, 0x00807028,
0x000036c6, 0x00806031, 0x008005aa, 0x00000671,//7
0x00800671, 0x000005aa, 0x00006031, 0x008036c6,
0x00007028, 0x00802e55, 0x008236d0, 0x000002f0,
0x00000070, 0x0080346e, 0x00800655, 0x00802521,
0x00800745, 0x00803431, 0x000037a2, 0x00806870,//8
0x00006830, 0x0080364e, 0x00822f48, 0x00000361,
0x0082b651, 0x00000271, 0x00800231, 0x002b4051,
0x00034051, 0x00800030, 0x0080026e, 0x00803651,
0x0080036c, 0x00802741, 0x008234f0, 0x000006b0,//9
0x00000068, 0x00802c75, 0x0080064e, 0x008024a2,
0x0002c04a, 0x00800021, 0x00800275, 0x00802e51,
0x00800651, 0x00000251, 0x00800000, 0x00004051,
0x000036b0, 0x008024e2, 0x00800475, 0x00000045,//a
0x008006c6, 0x00802c2a, 0x000035aa, 0x00807068,
0x008002f4, 0x008026c2, 0x00822d68, 0x00000728,
0x00002f28, 0x00802561, 0x0080046e, 0x00000046,
0x00836870, 0x000007a2, 0x00800431, 0x00004071,//b
0x00000071, 0x008034e6, 0x00034850, 0x00800031,
0x0080074c, 0x008034b0, 0x00800365, 0x00802f48,
0x00800748, 0x00000341, 0x000026a2, 0x008034f0,
0x00800002, 0x00005048, 0x00800565, 0x00000055,//c
0x008006d4, 0x00802d28, 0x008002e6, 0x008036d0,
0x000037aa, 0x00806071, 0x0082b471, 0x00000631,
0x00002e2a, 0x00803471, 0x00826862, 0x010007aa,
0x0080056c, 0x00000054, 0x00800528, 0x00005068,//d
0x008006d0, 0x000002d0, 0x00002721, 0x00802d68,
0x00003631, 0x00802c6a, 0x00836071, 0x000007aa,
0x010037aa, 0x00a36870, 0x00800471, 0x00004031,
0x00800568, 0x00005028, 0x00000050, 0x00800545,//e
0x00800001, 0x00004850, 0x008004e6, 0x0000004e,
0x008004f4, 0x0000004c, 0x008004b0, 0x00004870,
0x008004f0, 0x00004830, 0x00000048, 0x0080044e,
0x00000051, 0x008004d4, 0x00800451, 0x00800007,//f
};
static void RGA2_reg_get_param(unsigned char *base, struct rga2_req *msg)
{
u32 *bRGA_SRC_X_FACTOR;
u32 *bRGA_SRC_Y_FACTOR;
u32 sw, sh;
u32 dw, dh;
u32 param_x, param_y;
bRGA_SRC_X_FACTOR = (u32 *) (base + RGA2_SRC_X_FACTOR_OFFSET);
bRGA_SRC_Y_FACTOR = (u32 *) (base + RGA2_SRC_Y_FACTOR_OFFSET);
if (((msg->rotate_mode & 0x3) == 1) ||
((msg->rotate_mode & 0x3) == 3)) {
dw = msg->dst.act_h;
dh = msg->dst.act_w;
} else {
dw = msg->dst.act_w;
dh = msg->dst.act_h;
}
sw = msg->src.act_w;
sh = msg->src.act_h;
if (sw > dw) {
#if SCALE_DOWN_LARGE
param_x = ((dw) << 16) / (sw) + 1;
#else
param_x = ((dw) << 16) / (sw);
#endif
*bRGA_SRC_X_FACTOR |= ((param_x & 0xffff) << 0);
} else if (sw < dw) {
#if SCALE_UP_LARGE
param_x = ((sw - 1) << 16) / (dw - 1);
#else
param_x = ((sw) << 16) / (dw);
#endif
*bRGA_SRC_X_FACTOR |= ((param_x & 0xffff) << 16);
} else {
*bRGA_SRC_X_FACTOR = 0; //((1 << 14) << 16) | (1 << 14);
}
if (sh > dh) {
#if SCALE_DOWN_LARGE
param_y = ((dh) << 16) / (sh) + 1;
#else
param_y = ((dh) << 16) / (sh);
#endif
*bRGA_SRC_Y_FACTOR |= ((param_y & 0xffff) << 0);
} else if (sh < dh) {
#if SCALE_UP_LARGE
param_y = ((sh - 1) << 16) / (dh - 1);
#else
param_y = ((sh) << 16) / (dh);
#endif
*bRGA_SRC_Y_FACTOR |= ((param_y & 0xffff) << 16);
} else {
*bRGA_SRC_Y_FACTOR = 0; //((1 << 14) << 16) | (1 << 14);
}
}
static void RGA2_set_mode_ctrl(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_MODE_CTL;
u32 reg = 0;
u32 render_mode = msg->render_mode;
bRGA_MODE_CTL = (u32 *) (base + RGA2_MODE_CTRL_OFFSET);
if (msg->render_mode == UPDATE_PALETTE_TABLE_MODE)
render_mode = 0x3;
reg =
((reg & (~m_RGA2_MODE_CTRL_SW_RENDER_MODE)) |
(s_RGA2_MODE_CTRL_SW_RENDER_MODE(render_mode)));
reg =
((reg & (~m_RGA2_MODE_CTRL_SW_BITBLT_MODE)) |
(s_RGA2_MODE_CTRL_SW_BITBLT_MODE(msg->bitblt_mode)));
reg =
((reg & (~m_RGA2_MODE_CTRL_SW_CF_ROP4_PAT)) |
(s_RGA2_MODE_CTRL_SW_CF_ROP4_PAT(msg->color_fill_mode)));
reg =
((reg & (~m_RGA2_MODE_CTRL_SW_ALPHA_ZERO_KET)) |
(s_RGA2_MODE_CTRL_SW_ALPHA_ZERO_KET(msg->alpha_zero_key)));
reg =
((reg & (~m_RGA2_MODE_CTRL_SW_GRADIENT_SAT)) |
(s_RGA2_MODE_CTRL_SW_GRADIENT_SAT(msg->alpha_rop_flag >> 7)));
reg =
((reg & (~m_RGA2_MODE_CTRL_SW_INTR_CF_E)) |
(s_RGA2_MODE_CTRL_SW_INTR_CF_E(msg->CMD_fin_int_enable)));
reg = ((reg & (~m_RGA2_MODE_CTRL_SW_MOSAIC_EN)) |
(s_RGA2_MODE_CTRL_SW_MOSAIC_EN(msg->mosaic_info.enable)));
reg = ((reg & (~m_RGA2_MODE_CTRL_SW_YIN_YOUT_EN)) |
(s_RGA2_MODE_CTRL_SW_YIN_YOUT_EN(msg->yin_yout_en)));
reg = ((reg & (~m_RGA2_MODE_CTRL_SW_OSD_E)) |
(s_RGA2_MODE_CTRL_SW_OSD_E(msg->osd_info.enable)));
*bRGA_MODE_CTL = reg;
}
static void RGA2_set_reg_src_info(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_SRC_INFO;
u32 *bRGA_SRC_BASE0, *bRGA_SRC_BASE1, *bRGA_SRC_BASE2;
u32 *bRGA_SRC_VIR_INFO;
u32 *bRGA_SRC_ACT_INFO;
u32 *bRGA_MASK_ADDR;
u32 *bRGA_SRC_TR_COLOR0, *bRGA_SRC_TR_COLOR1;
u8 disable_uv_channel_en = 0;
u32 reg = 0;
u8 src0_format = 0;
u8 src0_rb_swp = 0;
u8 src0_alpha_swp = 0;
u8 src0_cbcr_swp = 0;
u8 pixel_width = 1;
u32 stride = 0;
u32 uv_stride = 0;
u32 mask_stride = 0;
u32 ydiv = 1, xdiv = 2;
u8 yuv10 = 0;
u32 sw, sh;
u32 dw, dh;
u8 rotate_mode;
u8 vsp_scale_mode = 0;
u8 scale_w_flag, scale_h_flag;
bRGA_SRC_INFO = (u32 *) (base + RGA2_SRC_INFO_OFFSET);
bRGA_SRC_BASE0 = (u32 *) (base + RGA2_SRC_BASE0_OFFSET);
bRGA_SRC_BASE1 = (u32 *) (base + RGA2_SRC_BASE1_OFFSET);
bRGA_SRC_BASE2 = (u32 *) (base + RGA2_SRC_BASE2_OFFSET);
bRGA_SRC_VIR_INFO = (u32 *) (base + RGA2_SRC_VIR_INFO_OFFSET);
bRGA_SRC_ACT_INFO = (u32 *) (base + RGA2_SRC_ACT_INFO_OFFSET);
bRGA_MASK_ADDR = (u32 *) (base + RGA2_MASK_BASE_OFFSET);
bRGA_SRC_TR_COLOR0 = (u32 *) (base + RGA2_SRC_TR_COLOR0_OFFSET);
bRGA_SRC_TR_COLOR1 = (u32 *) (base + RGA2_SRC_TR_COLOR1_OFFSET);
if (msg->src.format == RGA_FORMAT_YCbCr_420_SP_10B ||
msg->src.format == RGA_FORMAT_YCrCb_420_SP_10B) {
if ((msg->src.act_w == msg->dst.act_w) &&
(msg->src.act_h == msg->dst.act_h) &&
(msg->rotate_mode == 0))
msg->rotate_mode = 1 << 6;
}
{
rotate_mode = msg->rotate_mode & 0x3;
sw = msg->src.act_w;
sh = msg->src.act_h;
if ((rotate_mode == 1) | (rotate_mode == 3)) {
dw = msg->dst.act_h;
dh = msg->dst.act_w;
} else {
dw = msg->dst.act_w;
dh = msg->dst.act_h;
}
if (sw > dw)
scale_w_flag = 1;
else if (sw < dw)
scale_w_flag = 2;
else {
scale_w_flag = 0;
if (msg->rotate_mode >> 6)
scale_w_flag = 3;
}
if (sh > dh)
scale_h_flag = 1;
else if (sh < dh)
scale_h_flag = 2;
else {
scale_h_flag = 0;
if (msg->rotate_mode >> 6)
scale_h_flag = 3;
}
/* uvvds need to force tile mode. */
if (msg->uvvds_mode && scale_w_flag == 0)
scale_w_flag = 3;
}
/* VSP scale mode select, HSD > VSD > VSP > HSP */
if (scale_h_flag == 0x2) {
/* After HSD, VSP needs to check dst_width */
if ((scale_w_flag == 0x1) && (dw < RGA2_VSP_BICUBIC_LIMIT))
vsp_scale_mode = 0x0;
else if (sw < RGA2_VSP_BICUBIC_LIMIT)
vsp_scale_mode = 0x0;
else
/* default select bilinear */
vsp_scale_mode = 0x1;
}
switch (msg->src.format) {
case RGA_FORMAT_RGBA_8888:
src0_format = 0x0;
pixel_width = 4;
break;
case RGA_FORMAT_BGRA_8888:
src0_format = 0x0;
src0_rb_swp = 0x1;
pixel_width = 4;
break;
case RGA_FORMAT_RGBX_8888:
src0_format = 0x1;
pixel_width = 4;
msg->src_trans_mode &= 0x07;
break;
case RGA_FORMAT_BGRX_8888:
src0_format = 0x1;
src0_rb_swp = 0x1;
pixel_width = 4;
msg->src_trans_mode &= 0x07;
break;
case RGA_FORMAT_RGB_888:
src0_format = 0x2;
pixel_width = 3;
msg->src_trans_mode &= 0x07;
break;
case RGA_FORMAT_BGR_888:
src0_format = 0x2;
src0_rb_swp = 1;
pixel_width = 3;
msg->src_trans_mode &= 0x07;
break;
case RGA_FORMAT_RGB_565:
src0_format = 0x4;
pixel_width = 2;
msg->src_trans_mode &= 0x07;
break;
case RGA_FORMAT_RGBA_5551:
src0_format = 0x5;
pixel_width = 2;
break;
case RGA_FORMAT_RGBA_4444:
src0_format = 0x6;
pixel_width = 2;
break;
case RGA_FORMAT_BGR_565:
src0_format = 0x4;
pixel_width = 2;
msg->src_trans_mode &= 0x07;
src0_rb_swp = 0x1;
break;
case RGA_FORMAT_BGRA_5551:
src0_format = 0x5;
pixel_width = 2;
src0_rb_swp = 0x1;
break;
case RGA_FORMAT_BGRA_4444:
src0_format = 0x6;
pixel_width = 2;
src0_rb_swp = 0x1;
break;
/* ARGB */
/*
* In colorkey mode, xrgb/xbgr does not
* need to enable the alpha channel
*/
case RGA_FORMAT_ARGB_8888:
src0_format = 0x0;
pixel_width = 4;
src0_alpha_swp = 1;
break;
case RGA_FORMAT_ABGR_8888:
src0_format = 0x0;
pixel_width = 4;
src0_alpha_swp = 1;
src0_rb_swp = 0x1;
break;
case RGA_FORMAT_XRGB_8888:
src0_format = 0x1;
pixel_width = 4;
src0_alpha_swp = 1;
msg->src_trans_mode &= 0x07;
break;
case RGA_FORMAT_XBGR_8888:
src0_format = 0x1;
pixel_width = 4;
src0_alpha_swp = 1;
src0_rb_swp = 0x1;
msg->src_trans_mode &= 0x07;
break;
case RGA_FORMAT_ARGB_5551:
src0_format = 0x5;
pixel_width = 2;
src0_alpha_swp = 1;
break;
case RGA_FORMAT_ABGR_5551:
src0_format = 0x5;
pixel_width = 2;
src0_alpha_swp = 1;
src0_rb_swp = 0x1;
break;
case RGA_FORMAT_ARGB_4444:
src0_format = 0x6;
pixel_width = 2;
src0_alpha_swp = 1;
break;
case RGA_FORMAT_ABGR_4444:
src0_format = 0x6;
pixel_width = 2;
src0_alpha_swp = 1;
src0_rb_swp = 0x1;
break;
case RGA_FORMAT_YVYU_422:
src0_format = 0x7;
pixel_width = 2;
src0_cbcr_swp = 1;
src0_rb_swp = 0x1;
break; //rbswap=ycswap
case RGA_FORMAT_VYUY_422:
src0_format = 0x7;
pixel_width = 2;
src0_cbcr_swp = 1;
src0_rb_swp = 0x0;
break;
case RGA_FORMAT_YUYV_422:
src0_format = 0x7;
pixel_width = 2;
src0_cbcr_swp = 0;
src0_rb_swp = 0x1;
break;
case RGA_FORMAT_UYVY_422:
src0_format = 0x7;
pixel_width = 2;
src0_cbcr_swp = 0;
src0_rb_swp = 0x0;
break;
case RGA_FORMAT_YCbCr_422_SP:
src0_format = 0x8;
xdiv = 1;
ydiv = 1;
break;
case RGA_FORMAT_YCbCr_422_P:
src0_format = 0x9;
xdiv = 2;
ydiv = 1;
break;
case RGA_FORMAT_YCbCr_420_SP:
src0_format = 0xa;
xdiv = 1;
ydiv = 2;
break;
case RGA_FORMAT_YCbCr_420_P:
src0_format = 0xb;
xdiv = 2;
ydiv = 2;
break;
case RGA_FORMAT_YCrCb_422_SP:
src0_format = 0x8;
xdiv = 1;
ydiv = 1;
src0_cbcr_swp = 1;
break;
case RGA_FORMAT_YCrCb_422_P:
src0_format = 0x9;
xdiv = 2;
ydiv = 1;
src0_cbcr_swp = 1;
break;
case RGA_FORMAT_YCrCb_420_SP:
src0_format = 0xa;
xdiv = 1;
ydiv = 2;
src0_cbcr_swp = 1;
break;
case RGA_FORMAT_YCrCb_420_P:
src0_format = 0xb;
xdiv = 2;
ydiv = 2;
src0_cbcr_swp = 1;
break;
case RGA_FORMAT_YCbCr_420_SP_10B:
src0_format = 0xa;
xdiv = 1;
ydiv = 2;
yuv10 = 1;
break;
case RGA_FORMAT_YCrCb_420_SP_10B:
src0_format = 0xa;
xdiv = 1;
ydiv = 2;
src0_cbcr_swp = 1;
yuv10 = 1;
break;
case RGA_FORMAT_YCbCr_422_SP_10B:
src0_format = 0x8;
xdiv = 1;
ydiv = 1;
yuv10 = 1;
break;
case RGA_FORMAT_YCrCb_422_SP_10B:
src0_format = 0x8;
xdiv = 1;
ydiv = 1;
src0_cbcr_swp = 1;
yuv10 = 1;
break;
case RGA_FORMAT_YCbCr_400:
src0_format = 0x8;
/* When Yin_Yout is enabled, no need to go through the software. */
disable_uv_channel_en = msg->yin_yout_en ? false : true;
xdiv = 1;
ydiv = 1;
break;
};
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SRC_FMT)) |
(s_RGA2_SRC_INFO_SW_SRC_FMT(src0_format)));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_RB_SWAP)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_RB_SWAP(src0_rb_swp)));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_ALPHA_SWAP)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_ALPHA_SWAP(src0_alpha_swp)));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_UV_SWAP)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_UV_SWAP(src0_cbcr_swp)));
if (msg->src1.format == RGA_FORMAT_RGBA_2BPP)
reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_CP_ENDIAN)) |
(s_RGA2_SRC_INFO_SW_SW_CP_ENDAIN(msg->osd_info.bpp2_info.endian_swap & 1)));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_CSC_MODE)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_CSC_MODE(msg->yuv2rgb_mode)));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_ROT_MODE)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_ROT_MODE(msg->rotate_mode & 0x3)));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_MIR_MODE)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_MIR_MODE
((msg->rotate_mode >> 4) & 0x3)));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_HSCL_MODE)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_HSCL_MODE((scale_w_flag))));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_VSCL_MODE)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_VSCL_MODE((scale_h_flag))));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_SCL_FILTER)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_SCL_FILTER((
msg->scale_bicu_mode))));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_TRANS_MODE)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_TRANS_MODE(msg->src_trans_mode)));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_TRANS_E)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_TRANS_E(msg->src_trans_mode >> 1)));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_DITHER_UP_E)) |
(s_RGA2_SRC_INFO_SW_SW_SRC_DITHER_UP_E
((msg->alpha_rop_flag >> 4) & 0x1)));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_VSP_MODE_SEL)) |
(s_RGA2_SRC_INFO_SW_SW_VSP_MODE_SEL((vsp_scale_mode))));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_YUV10_E)) |
(s_RGA2_SRC_INFO_SW_SW_YUV10_E((yuv10))));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_YUV10_ROUND_E)) |
(s_RGA2_SRC_INFO_SW_SW_YUV10_ROUND_E((yuv10))));
RGA2_reg_get_param(base, msg);
stride = (((msg->src.vir_w * pixel_width) + 3) & ~3) >> 2;
uv_stride = ((msg->src.vir_w / xdiv + 3) & ~3);
if (disable_uv_channel_en == 1) {
/*
* When Y400 as the input format, because the current
* RGA does not support closing
* the access of the UV channel, the address of the UV
* channel access is equal to
* the address of the Y channel access to ensure that
* the UV channel can access,
* preventing the RGA hardware from reporting errors.
*/
*bRGA_SRC_BASE0 =
(u32) (msg->src.yrgb_addr +
msg->src.y_offset * (stride << 2) +
msg->src.x_offset * pixel_width);
*bRGA_SRC_BASE1 = *bRGA_SRC_BASE0;
*bRGA_SRC_BASE2 = *bRGA_SRC_BASE0;
} else {
*bRGA_SRC_BASE0 =
(u32) (msg->src.yrgb_addr +
msg->src.y_offset * (stride << 2) +
msg->src.x_offset * pixel_width);
*bRGA_SRC_BASE1 =
(u32) (msg->src.uv_addr +
(msg->src.y_offset / ydiv) * uv_stride +
(msg->src.x_offset / xdiv));
*bRGA_SRC_BASE2 =
(u32) (msg->src.v_addr +
(msg->src.y_offset / ydiv) * uv_stride +
(msg->src.x_offset / xdiv));
}
//mask_stride = ((msg->src0_act.width + 31) & ~31) >> 5;
mask_stride = msg->rop_mask_stride;
*bRGA_SRC_VIR_INFO = stride | (mask_stride << 16);
*bRGA_SRC_ACT_INFO =
(msg->src.act_w - 1) | ((msg->src.act_h - 1) << 16);
*bRGA_MASK_ADDR = (u32) msg->rop_mask_addr;
*bRGA_SRC_INFO = reg;
*bRGA_SRC_TR_COLOR0 = msg->color_key_min;
*bRGA_SRC_TR_COLOR1 = msg->color_key_max;
}
static void RGA2_set_reg_dst_info(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_DST_INFO;
u32 *bRGA_DST_BASE0, *bRGA_DST_BASE1, *bRGA_DST_BASE2,
*bRGA_SRC_BASE3;
u32 *bRGA_DST_VIR_INFO;
u32 *bRGA_DST_ACT_INFO;
u32 *RGA_DST_Y4MAP_LUT0; //Y4 LUT0
u32 *RGA_DST_Y4MAP_LUT1; //Y4 LUT1
u32 *RGA_DST_NN_QUANTIZE_SCALE;
u32 *RGA_DST_NN_QUANTIZE_OFFSET;
u32 line_width_real;
u8 ydither_en = 0;
u8 src1_format = 0;
u8 src1_rb_swp = 0;
u8 src1_alpha_swp = 0;
u8 dst_format = 0;
u8 dst_rb_swp = 0;
u8 dst_cbcr_swp = 0;
u8 dst_alpha_swp = 0;
u8 dst_fmt_yuv400_en = 0;
u8 dst_fmt_y4_en = 0;
u8 dst_nn_quantize_en = 0;
u32 reg = 0;
u8 spw, dpw;
u8 bbp_shift = 0;
u32 s_stride, d_stride;
u32 x_mirr, y_mirr, rot_90_flag;
u32 yrgb_addr, u_addr, v_addr, s_yrgb_addr;
u32 d_uv_stride, x_div, y_div;
u32 y_lt_addr, y_ld_addr, y_rt_addr, y_rd_addr;
u32 u_lt_addr, u_ld_addr, u_rt_addr, u_rd_addr;
u32 v_lt_addr, v_ld_addr, v_rt_addr, v_rd_addr;
dpw = 1;
x_div = y_div = 1;
dst_nn_quantize_en = (msg->alpha_rop_flag >> 8) & 0x1;
bRGA_DST_INFO = (u32 *) (base + RGA2_DST_INFO_OFFSET);
bRGA_DST_BASE0 = (u32 *) (base + RGA2_DST_BASE0_OFFSET);
bRGA_DST_BASE1 = (u32 *) (base + RGA2_DST_BASE1_OFFSET);
bRGA_DST_BASE2 = (u32 *) (base + RGA2_DST_BASE2_OFFSET);
bRGA_SRC_BASE3 = (u32 *) (base + RGA2_SRC_BASE3_OFFSET);
bRGA_DST_VIR_INFO = (u32 *) (base + RGA2_DST_VIR_INFO_OFFSET);
bRGA_DST_ACT_INFO = (u32 *) (base + RGA2_DST_ACT_INFO_OFFSET);
RGA_DST_Y4MAP_LUT0 = (u32 *) (base + RGA2_DST_Y4MAP_LUT0_OFFSET);
RGA_DST_Y4MAP_LUT1 = (u32 *) (base + RGA2_DST_Y4MAP_LUT1_OFFSET);
RGA_DST_NN_QUANTIZE_SCALE =
(u32 *) (base + RGA2_DST_QUANTIZE_SCALE_OFFSET);
RGA_DST_NN_QUANTIZE_OFFSET =
(u32 *) (base + RGA2_DST_QUANTIZE_OFFSET_OFFSET);
switch (msg->src1.format) {
case RGA_FORMAT_RGBA_8888:
src1_format = 0x0;
spw = 4;
break;
case RGA_FORMAT_BGRA_8888:
src1_format = 0x0;
src1_rb_swp = 0x1;
spw = 4;
break;
case RGA_FORMAT_RGBX_8888:
src1_format = 0x1;
spw = 4;
break;
case RGA_FORMAT_BGRX_8888:
src1_format = 0x1;
src1_rb_swp = 0x1;
spw = 4;
break;
case RGA_FORMAT_RGB_888:
src1_format = 0x2;
spw = 3;
break;
case RGA_FORMAT_BGR_888:
src1_format = 0x2;
src1_rb_swp = 1;
spw = 3;
break;
case RGA_FORMAT_RGB_565:
src1_format = 0x4;
spw = 2;
break;
case RGA_FORMAT_RGBA_5551:
src1_format = 0x5;
spw = 2;
break;
case RGA_FORMAT_RGBA_4444:
src1_format = 0x6;
spw = 2;
break;
case RGA_FORMAT_BGR_565:
src1_format = 0x4;
spw = 2;
src1_rb_swp = 0x1;
break;
case RGA_FORMAT_BGRA_5551:
src1_format = 0x5;
spw = 2;
src1_rb_swp = 0x1;
break;
case RGA_FORMAT_BGRA_4444:
src1_format = 0x6;
spw = 2;
src1_rb_swp = 0x1;
break;
/* ARGB */
case RGA_FORMAT_ARGB_8888:
src1_format = 0x0;
spw = 4;
src1_alpha_swp = 1;
break;
case RGA_FORMAT_ABGR_8888:
src1_format = 0x0;
spw = 4;
src1_alpha_swp = 1;
src1_rb_swp = 0x1;
break;
case RGA_FORMAT_XRGB_8888:
src1_format = 0x1;
spw = 4;
src1_alpha_swp = 1;
break;
case RGA_FORMAT_XBGR_8888:
src1_format = 0x1;
spw = 4;
src1_alpha_swp = 1;
src1_rb_swp = 0x1;
break;
case RGA_FORMAT_ARGB_5551:
src1_format = 0x5;
spw = 2;
src1_alpha_swp = 1;
break;
case RGA_FORMAT_ABGR_5551:
src1_format = 0x5;
spw = 2;
src1_alpha_swp = 1;
src1_rb_swp = 0x1;
break;
case RGA_FORMAT_ARGB_4444:
src1_format = 0x6;
spw = 2;
src1_alpha_swp = 1;
break;
case RGA_FORMAT_ABGR_4444:
src1_format = 0x6;
spw = 2;
src1_alpha_swp = 1;
src1_rb_swp = 0x1;
break;
case RGA_FORMAT_RGBA_2BPP:
src1_format = 0x0;
spw = 1;
/* 2BPP = 8 >> 2 = 2bit */
bbp_shift = 2;
src1_alpha_swp = msg->osd_info.bpp2_info.ac_swap;
break;
default:
spw = 4;
break;
};
reg =
((reg & (~m_RGA2_DST_INFO_SW_SRC1_FMT)) |
(s_RGA2_DST_INFO_SW_SRC1_FMT(src1_format)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_SRC1_RB_SWP)) |
(s_RGA2_DST_INFO_SW_SRC1_RB_SWP(src1_rb_swp)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_SRC1_ALPHA_SWP)) |
(s_RGA2_DST_INFO_SW_SRC1_ALPHA_SWP(src1_alpha_swp)));
switch (msg->dst.format) {
case RGA_FORMAT_RGBA_8888:
dst_format = 0x0;
dpw = 4;
break;
case RGA_FORMAT_BGRA_8888:
dst_format = 0x0;
dst_rb_swp = 0x1;
dpw = 4;
break;
case RGA_FORMAT_RGBX_8888:
dst_format = 0x1;
dpw = 4;
break;
case RGA_FORMAT_BGRX_8888:
dst_format = 0x1;
dst_rb_swp = 0x1;
dpw = 4;
break;
case RGA_FORMAT_RGB_888:
dst_format = 0x2;
dpw = 3;
break;
case RGA_FORMAT_BGR_888:
dst_format = 0x2;
dst_rb_swp = 1;
dpw = 3;
break;
case RGA_FORMAT_RGB_565:
dst_format = 0x4;
dpw = 2;
break;
case RGA_FORMAT_RGBA_5551:
dst_format = 0x5;
dpw = 2;
break;
case RGA_FORMAT_RGBA_4444:
dst_format = 0x6;
dpw = 2;
break;
case RGA_FORMAT_BGR_565:
dst_format = 0x4;
dpw = 2;
dst_rb_swp = 0x1;
break;
case RGA_FORMAT_BGRA_5551:
dst_format = 0x5;
dpw = 2;
dst_rb_swp = 0x1;
break;
case RGA_FORMAT_BGRA_4444:
dst_format = 0x6;
dpw = 2;
dst_rb_swp = 0x1;
break;
/* ARGB */
case RGA_FORMAT_ARGB_8888:
dst_format = 0x0;
dpw = 4;
dst_alpha_swp = 1;
break;
case RGA_FORMAT_ABGR_8888:
dst_format = 0x0;
dpw = 4;
dst_alpha_swp = 1;
dst_rb_swp = 0x1;
break;
case RGA_FORMAT_XRGB_8888:
dst_format = 0x1;
dpw = 4;
dst_alpha_swp = 1;
break;
case RGA_FORMAT_XBGR_8888:
dst_format = 0x1;
dpw = 4;
dst_alpha_swp = 1;
dst_rb_swp = 0x1;
break;
case RGA_FORMAT_ARGB_5551:
dst_format = 0x5;
dpw = 2;
dst_alpha_swp = 1;
break;
case RGA_FORMAT_ABGR_5551:
dst_format = 0x5;
dpw = 2;
dst_alpha_swp = 1;
dst_rb_swp = 0x1;
break;
case RGA_FORMAT_ARGB_4444:
dst_format = 0x6;
dpw = 2;
dst_alpha_swp = 1;
break;
case RGA_FORMAT_ABGR_4444:
dst_format = 0x6;
dpw = 2;
dst_alpha_swp = 1;
dst_rb_swp = 0x1;
break;
case RGA_FORMAT_YCbCr_422_SP:
dst_format = 0x8;
x_div = 1;
y_div = 1;
break;
case RGA_FORMAT_YCbCr_422_P:
dst_format = 0x9;
x_div = 2;
y_div = 1;
break;
case RGA_FORMAT_YCbCr_420_SP:
dst_format = 0xa;
x_div = 1;
y_div = 2;
break;
case RGA_FORMAT_YCbCr_420_P:
dst_format = 0xb;
dst_cbcr_swp = 1;
x_div = 2;
y_div = 2;
break;
case RGA_FORMAT_YCrCb_422_SP:
dst_format = 0x8;
dst_cbcr_swp = 1;
x_div = 1;
y_div = 1;
break;
case RGA_FORMAT_YCrCb_422_P:
dst_format = 0x9;
dst_cbcr_swp = 1;
x_div = 2;
y_div = 1;
break;
case RGA_FORMAT_YCrCb_420_SP:
dst_format = 0xa;
dst_cbcr_swp = 1;
x_div = 1;
y_div = 2;
break;
case RGA_FORMAT_YCrCb_420_P:
dst_format = 0xb;
x_div = 2;
y_div = 2;
break;
case RGA_FORMAT_YCbCr_400:
dst_format = 0x8;
dst_fmt_yuv400_en = 1;
x_div = 1;
y_div = 1;
break;
case RGA_FORMAT_Y4:
dst_format = 0x8;
dst_fmt_y4_en = 1;
dst_fmt_yuv400_en = 1;
x_div = 1;
y_div = 1;
break;
case RGA_FORMAT_YUYV_422:
dst_format = 0xe;
dpw = 2;
dst_cbcr_swp = 1;
break;
case RGA_FORMAT_YVYU_422:
dst_format = 0xe;
dpw = 2;
break;
case RGA_FORMAT_YUYV_420:
dst_format = 0xf;
dpw = 2;
dst_cbcr_swp = 1;
break;
case RGA_FORMAT_YVYU_420:
dst_format = 0xf;
dpw = 2;
break;
case RGA_FORMAT_UYVY_422:
dst_format = 0xc;
dpw = 2;
dst_cbcr_swp = 1;
break;
case RGA_FORMAT_VYUY_422:
dst_format = 0xc;
dpw = 2;
break;
case RGA_FORMAT_UYVY_420:
dst_format = 0xd;
dpw = 2;
dst_cbcr_swp = 1;
break;
case RGA_FORMAT_VYUY_420:
dst_format = 0xd;
dpw = 2;
break;
};
reg =
((reg & (~m_RGA2_DST_INFO_SW_DST_FMT)) |
(s_RGA2_DST_INFO_SW_DST_FMT(dst_format)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_DST_RB_SWAP)) |
(s_RGA2_DST_INFO_SW_DST_RB_SWAP(dst_rb_swp)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_ALPHA_SWAP)) |
(s_RGA2_DST_INFO_SW_ALPHA_SWAP(dst_alpha_swp)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_DST_UV_SWAP)) |
(s_RGA2_DST_INFO_SW_DST_UV_SWAP(dst_cbcr_swp)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_DST_FMT_YUV400_EN)) |
(s_RGA2_DST_INFO_SW_DST_FMT_YUV400_EN(dst_fmt_yuv400_en)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_DST_FMT_Y4_EN)) |
(s_RGA2_DST_INFO_SW_DST_FMT_Y4_EN(dst_fmt_y4_en)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_DST_NN_QUANTIZE_EN)) |
(s_RGA2_DST_INFO_SW_DST_NN_QUANTIZE_EN(dst_nn_quantize_en)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_DITHER_UP_E)) |
(s_RGA2_DST_INFO_SW_DITHER_UP_E(msg->alpha_rop_flag >> 5)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_DITHER_DOWN_E)) |
(s_RGA2_DST_INFO_SW_DITHER_DOWN_E(msg->alpha_rop_flag >> 6)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_DITHER_MODE)) |
(s_RGA2_DST_INFO_SW_DITHER_MODE(msg->dither_mode)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_DST_CSC_MODE)) |
(s_RGA2_DST_INFO_SW_DST_CSC_MODE(msg->yuv2rgb_mode >> 2)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_CSC_CLIP_MODE)) |
(s_RGA2_DST_INFO_SW_CSC_CLIP_MODE(msg->yuv2rgb_mode >> 4)));
/* full csc enable */
reg =
((reg & (~m_RGA2_DST_INFO_SW_DST_CSC_MODE_2)) |
(s_RGA2_DST_INFO_SW_DST_CSC_MODE_2(msg->full_csc_en)));
/*
* Some older chips do not support src1 csc mode,
* they do not have these two registers.
*/
reg =
((reg & (~m_RGA2_DST_INFO_SW_SRC1_CSC_MODE)) |
(s_RGA2_DST_INFO_SW_SRC1_CSC_MODE(msg->yuv2rgb_mode >> 5)));
reg =
((reg & (~m_RGA2_DST_INFO_SW_SRC1_CSC_CLIP_MODE)) |
(s_RGA2_DST_INFO_SW_SRC1_CSC_CLIP_MODE(
msg->yuv2rgb_mode >> 7)));
reg = ((reg & (~m_RGA2_DST_INFO_SW_DST_UVHDS_MODE)) |
(s_RGA2_DST_INFO_SW_DST_UVHDS_MODE(msg->uvhds_mode)));
reg = ((reg & (~m_RGA2_DST_INFO_SW_DST_UVVDS_MODE)) |
(s_RGA2_DST_INFO_SW_DST_UVVDS_MODE(msg->uvvds_mode)));
ydither_en = (msg->dst.format == RGA_FORMAT_Y4)
&& ((msg->alpha_rop_flag >> 6) & 0x1);
*bRGA_DST_INFO = reg;
s_stride = (((msg->src1.vir_w * spw >> bbp_shift) + 3) & ~3) >> 2;
d_stride = ((msg->dst.vir_w * dpw + 3) & ~3) >> 2;
if (dst_fmt_y4_en) {
/* Y4 output will HALF */
d_stride = ((d_stride + 1) & ~1) >> 1;
}
d_uv_stride = (d_stride << 2) / x_div;
*bRGA_DST_VIR_INFO = d_stride | (s_stride << 16);
if ((msg->dst.vir_w % 2 != 0) &&
(msg->dst.act_w == msg->src.act_w)
&& (msg->dst.act_h == msg->src.act_h)
&& (msg->dst.format == RGA_FORMAT_BGR_888
|| msg->dst.format == RGA_FORMAT_RGB_888))
*bRGA_DST_ACT_INFO =
(msg->dst.act_w) | ((msg->dst.act_h - 1) << 16);
else
*bRGA_DST_ACT_INFO =
(msg->dst.act_w - 1) | ((msg->dst.act_h - 1) << 16);
s_stride <<= 2;
d_stride <<= 2;
if (((msg->rotate_mode & 0xf) == 0) ||
((msg->rotate_mode & 0xf) == 1)) {
x_mirr = 0;
y_mirr = 0;
} else {
x_mirr = 1;
y_mirr = 1;
}
rot_90_flag = msg->rotate_mode & 1;
x_mirr = (x_mirr + ((msg->rotate_mode >> 4) & 1)) & 1;
y_mirr = (y_mirr + ((msg->rotate_mode >> 5) & 1)) & 1;
if (ydither_en) {
if (x_mirr && y_mirr) {
pr_err("ydither mode do not support rotate x_mirr=%d,y_mirr=%d\n",
x_mirr, y_mirr);
}
if (msg->dst.act_w != msg->src.act_w)
pr_err("ydither mode do not support x dir scale\n");
if (msg->dst.act_h != msg->src.act_h)
pr_err("ydither mode do not support y dir scale\n");
}
if (dst_fmt_y4_en) {
*RGA_DST_Y4MAP_LUT0 = (msg->gr_color.gr_x_r & 0xffff) |
(msg->gr_color.gr_x_g << 16);
*RGA_DST_Y4MAP_LUT1 = (msg->gr_color.gr_y_r & 0xffff) |
(msg->gr_color.gr_y_g << 16);
}
if (dst_nn_quantize_en) {
*RGA_DST_NN_QUANTIZE_SCALE = (msg->gr_color.gr_x_r & 0xffff) |
(msg->gr_color.gr_x_g << 10) |
(msg->gr_color.gr_x_b << 20);
*RGA_DST_NN_QUANTIZE_OFFSET = (msg->gr_color.gr_y_r & 0xffff) |
(msg->gr_color.gr_y_g << 10) |
(msg->gr_color.gr_y_b << 20);
}
s_yrgb_addr =
(u32) msg->src1.yrgb_addr + (msg->src1.y_offset * s_stride) +
(msg->src1.x_offset * spw >> bbp_shift);
*bRGA_SRC_BASE3 = s_yrgb_addr;
if (dst_fmt_y4_en) {
yrgb_addr = (u32) msg->dst.yrgb_addr +
(msg->dst.y_offset * d_stride) +
((msg->dst.x_offset * dpw) >> 1);
} else {
yrgb_addr = (u32) msg->dst.yrgb_addr +
(msg->dst.y_offset * d_stride) +
(msg->dst.x_offset * dpw);
}
u_addr = (u32) msg->dst.uv_addr +
(msg->dst.y_offset / y_div) * d_uv_stride +
msg->dst.x_offset / x_div;
v_addr = (u32) msg->dst.v_addr +
(msg->dst.y_offset / y_div) * d_uv_stride +
msg->dst.x_offset / x_div;
y_lt_addr = yrgb_addr;
u_lt_addr = u_addr;
v_lt_addr = v_addr;
/* Warning */
line_width_real =
dst_fmt_y4_en ? ((msg->dst.act_w) >> 1) : msg->dst.act_w;
/*
* YUV packet mode is a new format, and the write behavior during
* rotation is different from the old format.
*/
if (rga_is_yuv422_packed_format(msg->dst.format)) {
y_ld_addr = yrgb_addr + (msg->dst.act_h - 1) * (d_stride);
y_rt_addr = yrgb_addr + (msg->dst.act_w * 2 - 1);
y_rd_addr = y_ld_addr + (msg->dst.act_w * 2 - 1);
} else if (rga_is_yuv420_packed_format(msg->dst.format)) {
y_ld_addr = (u32)msg->dst.yrgb_addr +
((msg->dst.y_offset + (msg->dst.act_h - 1)) * d_stride) +
msg->dst.x_offset;
y_rt_addr = yrgb_addr + (msg->dst.act_w * 2 - 1);
y_rd_addr = y_ld_addr + (msg->dst.act_w - 1);
} else {
/* 270 degree & Mirror V */
y_ld_addr = yrgb_addr + (msg->dst.act_h - 1) * (d_stride);
/* 90 degree & Mirror H */
y_rt_addr = yrgb_addr + (line_width_real - 1) * dpw;
/* 180 degree */
y_rd_addr = y_ld_addr + (line_width_real - 1) * dpw;
}
u_ld_addr = u_addr + ((msg->dst.act_h / y_div) - 1) * (d_uv_stride);
v_ld_addr = v_addr + ((msg->dst.act_h / y_div) - 1) * (d_uv_stride);
u_rt_addr = u_addr + (msg->dst.act_w / x_div) - 1;
v_rt_addr = v_addr + (msg->dst.act_w / x_div) - 1;
u_rd_addr = u_ld_addr + (msg->dst.act_w / x_div) - 1;
v_rd_addr = v_ld_addr + (msg->dst.act_w / x_div) - 1;
if (rot_90_flag == 0) {
if (y_mirr == 1) {
if (x_mirr == 1) {
yrgb_addr = y_rd_addr;
u_addr = u_rd_addr;
v_addr = v_rd_addr;
} else {
yrgb_addr = y_ld_addr;
u_addr = u_ld_addr;
v_addr = v_ld_addr;
}
} else {
if (x_mirr == 1) {
yrgb_addr = y_rt_addr;
u_addr = u_rt_addr;
v_addr = v_rt_addr;
} else {
yrgb_addr = y_lt_addr;
u_addr = u_lt_addr;
v_addr = v_lt_addr;
}
}
} else {
if (y_mirr == 1) {
if (x_mirr == 1) {
yrgb_addr = y_ld_addr;
u_addr = u_ld_addr;
v_addr = v_ld_addr;
} else {
yrgb_addr = y_rd_addr;
u_addr = u_rd_addr;
v_addr = v_rd_addr;
}
} else {
if (x_mirr == 1) {
yrgb_addr = y_lt_addr;
u_addr = u_lt_addr;
v_addr = v_lt_addr;
} else {
yrgb_addr = y_rt_addr;
u_addr = u_rt_addr;
v_addr = v_rt_addr;
}
}
}
*bRGA_DST_BASE0 = (u32) yrgb_addr;
if ((msg->dst.format == RGA_FORMAT_YCbCr_420_P)
|| (msg->dst.format == RGA_FORMAT_YCrCb_420_P)) {
if (dst_cbcr_swp == 0) {
*bRGA_DST_BASE1 = (u32) v_addr;
*bRGA_DST_BASE2 = (u32) u_addr;
} else {
*bRGA_DST_BASE1 = (u32) u_addr;
*bRGA_DST_BASE2 = (u32) v_addr;
}
} else {
*bRGA_DST_BASE1 = (u32) u_addr;
*bRGA_DST_BASE2 = (u32) v_addr;
}
}
static void RGA2_set_reg_alpha_info(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_ALPHA_CTRL0;
u32 *bRGA_ALPHA_CTRL1;
u32 *bRGA_FADING_CTRL;
u32 reg = 0;
union rga2_color_ctrl color_ctrl;
union rga2_alpha_ctrl alpha_ctrl;
struct rga_alpha_config *config;
bRGA_ALPHA_CTRL0 = (u32 *) (base + RGA2_ALPHA_CTRL0_OFFSET);
bRGA_ALPHA_CTRL1 = (u32 *) (base + RGA2_ALPHA_CTRL1_OFFSET);
bRGA_FADING_CTRL = (u32 *) (base + RGA2_FADING_CTRL_OFFSET);
color_ctrl.value = 0;
alpha_ctrl.value = 0;
config = &msg->alpha_config;
color_ctrl.bits.src_color_mode =
config->fg_pre_multiplied ? RGA_ALPHA_PRE_MULTIPLIED : RGA_ALPHA_NO_PRE_MULTIPLIED;
color_ctrl.bits.dst_color_mode =
config->bg_pre_multiplied ? RGA_ALPHA_PRE_MULTIPLIED : RGA_ALPHA_NO_PRE_MULTIPLIED;
if (config->fg_pixel_alpha_en)
color_ctrl.bits.src_blend_mode =
config->fg_global_alpha_en ? RGA_ALPHA_PER_PIXEL_GLOBAL :
RGA_ALPHA_PER_PIXEL;
else
color_ctrl.bits.src_blend_mode = RGA_ALPHA_GLOBAL;
if (config->bg_pixel_alpha_en)
color_ctrl.bits.dst_blend_mode =
config->bg_global_alpha_en ? RGA_ALPHA_PER_PIXEL_GLOBAL :
RGA_ALPHA_PER_PIXEL;
else
color_ctrl.bits.dst_blend_mode = RGA_ALPHA_GLOBAL;
/*
* Since the hardware uses 256 as 1, the original alpha value needs to
* be + (alpha >> 7).
*/
color_ctrl.bits.src_alpha_cal_mode = RGA_ALPHA_SATURATION;
color_ctrl.bits.dst_alpha_cal_mode = RGA_ALPHA_SATURATION;
/* porter duff alpha enable */
switch (config->mode) {
case RGA_ALPHA_BLEND_SRC:
/*
* SRC mode:
* Sf = 1, Df = 0
* [Rc,Ra] = [Sc,Sa]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_ONE;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_ZERO;
break;
case RGA_ALPHA_BLEND_DST:
/*
* SRC mode:
* Sf = 0, Df = 1
* [Rc,Ra] = [Dc,Da]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_ZERO;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_ONE;
break;
case RGA_ALPHA_BLEND_SRC_OVER:
/*
* SRC-OVER mode:
* Sf = 1, Df = (1 - Sa)
* [Rc,Ra] = [ Sc + (1 - Sa) * Dc, Sa + (1 - Sa) * Da ]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_ONE;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
break;
case RGA_ALPHA_BLEND_DST_OVER:
/*
* DST-OVER mode:
* Sf = (1 - Da) , Df = 1
* [Rc,Ra] = [ Sc * (1 - Da) + Dc, Sa * (1 - Da) + Da ]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_ONE;
break;
case RGA_ALPHA_BLEND_SRC_IN:
/*
* SRC-IN mode:
* Sf = Da , Df = 0
* [Rc,Ra] = [ Sc * Da, Sa * Da ]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_OPPOSITE;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_ZERO;
break;
case RGA_ALPHA_BLEND_DST_IN:
/*
* DST-IN mode:
* Sf = 0 , Df = Sa
* [Rc,Ra] = [ Dc * Sa, Da * Sa ]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_ZERO;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_OPPOSITE;
break;
case RGA_ALPHA_BLEND_SRC_OUT:
/*
* SRC-OUT mode:
* Sf = (1 - Da) , Df = 0
* [Rc,Ra] = [ Sc * (1 - Da), Sa * (1 - Da) ]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_ZERO;
break;
case RGA_ALPHA_BLEND_DST_OUT:
/*
* DST-OUT mode:
* Sf = 0 , Df = (1 - Sa)
* [Rc,Ra] = [ Dc * (1 - Sa), Da * (1 - Sa) ]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_ZERO;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
break;
case RGA_ALPHA_BLEND_SRC_ATOP:
/*
* SRC-ATOP mode:
* Sf = Da , Df = (1 - Sa)
* [Rc,Ra] = [ Sc * Da + Dc * (1 - Sa), Sa * Da + Da * (1 - Sa) ]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_OPPOSITE;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
break;
case RGA_ALPHA_BLEND_DST_ATOP:
/*
* DST-ATOP mode:
* Sf = (1 - Da) , Df = Sa
* [Rc,Ra] = [ Sc * (1 - Da) + Dc * Sa, Sa * (1 - Da) + Da * Sa ]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_OPPOSITE;
break;
case RGA_ALPHA_BLEND_XOR:
/*
* DST-XOR mode:
* Sf = (1 - Da) , Df = (1 - Sa)
* [Rc,Ra] = [ Sc * (1 - Da) + Dc * (1 - Sa), Sa * (1 - Da) + Da * (1 - Sa) ]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
break;
case RGA_ALPHA_BLEND_CLEAR:
/*
* DST-CLEAR mode:
* Sf = 0 , Df = 0
* [Rc,Ra] = [ 0, 0 ]
*/
color_ctrl.bits.src_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.src_factor_mode = RGA_ALPHA_ZERO;
color_ctrl.bits.dst_alpha_mode = RGA_ALPHA_STRAIGHT;
color_ctrl.bits.dst_factor_mode = RGA_ALPHA_ZERO;
break;
default:
break;
}
alpha_ctrl.bits.src_blend_mode = color_ctrl.bits.src_blend_mode;
alpha_ctrl.bits.dst_blend_mode = color_ctrl.bits.dst_blend_mode;
alpha_ctrl.bits.src_alpha_cal_mode = color_ctrl.bits.src_alpha_cal_mode;
alpha_ctrl.bits.dst_alpha_cal_mode = color_ctrl.bits.dst_alpha_cal_mode;
alpha_ctrl.bits.src_alpha_mode = color_ctrl.bits.src_alpha_mode;
alpha_ctrl.bits.src_factor_mode = color_ctrl.bits.src_factor_mode;
alpha_ctrl.bits.dst_alpha_mode = color_ctrl.bits.dst_alpha_mode;
alpha_ctrl.bits.dst_factor_mode = color_ctrl.bits.dst_factor_mode;
reg =
((reg & (~m_RGA2_ALPHA_CTRL0_SW_ALPHA_ROP_0)) |
(s_RGA2_ALPHA_CTRL0_SW_ALPHA_ROP_0(msg->alpha_rop_flag)));
reg =
((reg & (~m_RGA2_ALPHA_CTRL0_SW_ALPHA_ROP_SEL)) |
(s_RGA2_ALPHA_CTRL0_SW_ALPHA_ROP_SEL
(msg->alpha_rop_flag >> 1)));
reg =
((reg & (~m_RGA2_ALPHA_CTRL0_SW_ROP_MODE)) |
(s_RGA2_ALPHA_CTRL0_SW_ROP_MODE(msg->rop_mode)));
reg =
((reg & (~m_RGA2_ALPHA_CTRL0_SW_SRC_GLOBAL_ALPHA)) |
(s_RGA2_ALPHA_CTRL0_SW_SRC_GLOBAL_ALPHA
((uint8_t)config->fg_global_alpha_value)));
reg =
((reg & (~m_RGA2_ALPHA_CTRL0_SW_DST_GLOBAL_ALPHA)) |
(s_RGA2_ALPHA_CTRL0_SW_DST_GLOBAL_ALPHA
((uint8_t)config->bg_global_alpha_value)));
*bRGA_ALPHA_CTRL0 = reg;
*bRGA_ALPHA_CTRL1 = color_ctrl.value | (alpha_ctrl.value << 16);
if ((msg->alpha_rop_flag >> 2) & 1) {
*bRGA_FADING_CTRL = (1 << 24) | (msg->fading_b_value << 16) |
(msg->fading_g_value << 8) | (msg->fading_r_value);
}
}
static void RGA2_set_reg_rop_info(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_ALPHA_CTRL0;
u32 *bRGA_ROP_CTRL0;
u32 *bRGA_ROP_CTRL1;
u32 *bRGA_MASK_ADDR;
u32 *bRGA_FG_COLOR;
u32 *bRGA_PAT_CON;
u32 rop_code0 = 0;
u32 rop_code1 = 0;
bRGA_ALPHA_CTRL0 = (u32 *) (base + RGA2_ALPHA_CTRL0_OFFSET);
bRGA_ROP_CTRL0 = (u32 *) (base + RGA2_ROP_CTRL0_OFFSET);
bRGA_ROP_CTRL1 = (u32 *) (base + RGA2_ROP_CTRL1_OFFSET);
bRGA_MASK_ADDR = (u32 *) (base + RGA2_MASK_BASE_OFFSET);
bRGA_FG_COLOR = (u32 *) (base + RGA2_SRC_FG_COLOR_OFFSET);
bRGA_PAT_CON = (u32 *) (base + RGA2_PAT_CON_OFFSET);
if (msg->rop_mode == 0) {
rop_code0 = rga2_rop_code[(msg->rop_code & 0xff)];
} else if (msg->rop_mode == 1) {
rop_code0 = rga2_rop_code[(msg->rop_code & 0xff)];
} else if (msg->rop_mode == 2) {
rop_code0 = rga2_rop_code[(msg->rop_code & 0xff)];
rop_code1 = rga2_rop_code[(msg->rop_code & 0xff00) >> 8];
}
*bRGA_ROP_CTRL0 = rop_code0;
*bRGA_ROP_CTRL1 = rop_code1;
*bRGA_FG_COLOR = msg->fg_color;
*bRGA_MASK_ADDR = (u32) msg->rop_mask_addr;
*bRGA_PAT_CON = (msg->pat.act_w - 1) | ((msg->pat.act_h - 1) << 8)
| (msg->pat.x_offset << 16) | (msg->pat.y_offset << 24);
*bRGA_ALPHA_CTRL0 =
*bRGA_ALPHA_CTRL0 | (((msg->endian_mode >> 1) & 1) << 20);
}
static void RGA_set_reg_mosaic(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_MOSAIC_MODE;
bRGA_MOSAIC_MODE = (u32 *)(base + RGA2_MOSAIC_MODE_OFFSET);
*bRGA_MOSAIC_MODE = (u32)(msg->mosaic_info.mode & 0x7);
}
static void RGA2_set_reg_osd(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_OSD_CTRL0;
u32 *bRGA_OSD_CTRL1;
u32 *bRGA_OSD_INVERTSION_CAL0;
u32 *bRGA_OSD_INVERTSION_CAL1;
u32 *bRGA_OSD_COLOR0;
u32 *bRGA_OSD_COLOR1;
u32 *bRGA_OSD_LAST_FLAGS0;
u32 *bRGA_OSD_LAST_FLAGS1;
u32 reg;
u8 rgba2bpp_en = 0;
u8 block_num;
u16 fix_width;
bRGA_OSD_CTRL0 = (u32 *)(base + RGA2_OSD_CTRL0_OFFSET);
bRGA_OSD_CTRL1 = (u32 *)(base + RGA2_OSD_CTRL1_OFFSET);
bRGA_OSD_INVERTSION_CAL0 = (u32 *)(base + RGA2_OSD_INVERTSION_CAL0_OFFSET);
bRGA_OSD_INVERTSION_CAL1 = (u32 *)(base + RGA2_OSD_INVERTSION_CAL1_OFFSET);
bRGA_OSD_COLOR0 = (u32 *)(base + RGA2_OSD_COLOR0_OFFSET);
bRGA_OSD_COLOR1 = (u32 *)(base + RGA2_OSD_COLOR1_OFFSET);
bRGA_OSD_LAST_FLAGS0 = (u32 *)(base + RGA2_OSD_LAST_FLAGS0_OFFSET);
bRGA_OSD_LAST_FLAGS1 = (u32 *)(base + RGA2_OSD_LAST_FLAGS1_OFFSET);
/* To save the number of register bits. */
fix_width = msg->osd_info.mode_ctrl.block_fix_width / 2 - 1;
/* The register is '0' as the first. */
block_num = msg->osd_info.mode_ctrl.block_num - 1;
if (msg->src1.format == RGA_FORMAT_RGBA_2BPP)
rgba2bpp_en = 1;
reg = 0;
reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_MODE)) |
(s_RGA2_OSD_CTRL0_SW_OSD_MODE(msg->osd_info.mode_ctrl.mode)));
reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_VER_MODE)) |
(s_RGA2_OSD_CTRL0_SW_OSD_VER_MODE(msg->osd_info.mode_ctrl.direction_mode)));
reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_WIDTH_MODE)) |
(s_RGA2_OSD_CTRL0_SW_OSD_WIDTH_MODE(msg->osd_info.mode_ctrl.width_mode)));
reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_BLK_NUM)) |
(s_RGA2_OSD_CTRL0_SW_OSD_BLK_NUM(block_num)));
reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_FLAGS_INDEX)) |
(s_RGA2_OSD_CTRL0_SW_OSD_FLAGS_INDEX(msg->osd_info.mode_ctrl.flags_index)));
reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_FIX_WIDTH)) |
(s_RGA2_OSD_CTRL0_SW_OSD_FIX_WIDTH(fix_width)));
reg = ((reg & (~m_RGA2_OSD_CTRL0_SW_OSD_2BPP_MODE)) |
(s_RGA2_OSD_CTRL0_SW_OSD_2BPP_MODE(rgba2bpp_en)));
*bRGA_OSD_CTRL0 = reg;
reg = 0;
reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_COLOR_SEL)) |
(s_RGA2_OSD_CTRL1_SW_OSD_COLOR_SEL(msg->osd_info.mode_ctrl.color_mode)));
reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_FLAG_SEL)) |
(s_RGA2_OSD_CTRL1_SW_OSD_FLAG_SEL(msg->osd_info.mode_ctrl.invert_flags_mode)));
reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_DEFAULT_COLOR)) |
(s_RGA2_OSD_CTRL1_SW_OSD_DEFAULT_COLOR(msg->osd_info.mode_ctrl.default_color_sel)));
reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_AUTO_INVERST_MODE)) |
(s_RGA2_OSD_CTRL1_SW_OSD_AUTO_INVERST_MODE(msg->osd_info.mode_ctrl.invert_mode)));
reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_THRESH)) |
(s_RGA2_OSD_CTRL1_SW_OSD_THRESH(msg->osd_info.mode_ctrl.invert_thresh)));
reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_INVERT_A_EN)) |
(s_RGA2_OSD_CTRL1_SW_OSD_INVERT_A_EN(msg->osd_info.mode_ctrl.invert_enable)));
reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_INVERT_Y_DIS)) |
(s_RGA2_OSD_CTRL1_SW_OSD_INVERT_Y_DIS(msg->osd_info.mode_ctrl.invert_enable >> 1)));
reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_INVERT_C_DIS)) |
(s_RGA2_OSD_CTRL1_SW_OSD_INVERT_C_DIS(msg->osd_info.mode_ctrl.invert_enable >> 2)));
reg = ((reg & (~m_RGA2_OSD_CTRL1_SW_OSD_UNFIX_INDEX)) |
(s_RGA2_OSD_CTRL1_SW_OSD_UNFIX_INDEX(msg->osd_info.mode_ctrl.unfix_index)));
*bRGA_OSD_CTRL1 = reg;
*bRGA_OSD_INVERTSION_CAL0 = ((msg->osd_info.cal_factor.crb_max) << 24) |
((msg->osd_info.cal_factor.crb_min) << 16) |
((msg->osd_info.cal_factor.yg_max) << 8) |
((msg->osd_info.cal_factor.yg_min) << 0);
*bRGA_OSD_INVERTSION_CAL1 = ((msg->osd_info.cal_factor.alpha_max) << 8) |
((msg->osd_info.cal_factor.alpha_min) << 0);
*bRGA_OSD_LAST_FLAGS0 = (msg->osd_info.last_flags0);
*bRGA_OSD_LAST_FLAGS1 = (msg->osd_info.last_flags1);
if (msg->osd_info.mode_ctrl.color_mode == 1) {
*bRGA_OSD_COLOR0 = (msg->osd_info.bpp2_info.color0.value & 0xffffff);
*bRGA_OSD_COLOR1 = (msg->osd_info.bpp2_info.color1.value & 0xffffff);
}
if (rgba2bpp_en) {
*bRGA_OSD_COLOR0 = msg->osd_info.bpp2_info.color0.value;
*bRGA_OSD_COLOR1 = msg->osd_info.bpp2_info.color1.value;
}
}
static void RGA2_set_reg_color_palette(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_SRC_BASE0, *bRGA_SRC_INFO, *bRGA_SRC_VIR_INFO,
*bRGA_SRC_ACT_INFO, *bRGA_SRC_FG_COLOR, *bRGA_SRC_BG_COLOR;
u32 *p;
short x_off, y_off;
u16 src_stride;
u8 shift;
u32 sw;
u32 byte_num;
u32 reg;
bRGA_SRC_BASE0 = (u32 *) (base + RGA2_SRC_BASE0_OFFSET);
bRGA_SRC_INFO = (u32 *) (base + RGA2_SRC_INFO_OFFSET);
bRGA_SRC_VIR_INFO = (u32 *) (base + RGA2_SRC_VIR_INFO_OFFSET);
bRGA_SRC_ACT_INFO = (u32 *) (base + RGA2_SRC_ACT_INFO_OFFSET);
bRGA_SRC_FG_COLOR = (u32 *) (base + RGA2_SRC_FG_COLOR_OFFSET);
bRGA_SRC_BG_COLOR = (u32 *) (base + RGA2_SRC_BG_COLOR_OFFSET);
reg = 0;
shift = 3 - msg->palette_mode;
x_off = msg->src.x_offset;
y_off = msg->src.y_offset;
sw = msg->src.vir_w;
byte_num = sw >> shift;
src_stride = (byte_num + 3) & (~3);
p = (u32 *) ((unsigned long)msg->src.yrgb_addr);
p = p + (x_off >> shift) + y_off * src_stride;
*bRGA_SRC_BASE0 = (unsigned long)p;
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SRC_FMT)) |
(s_RGA2_SRC_INFO_SW_SRC_FMT((msg->palette_mode | 0xc))));
reg =
((reg & (~m_RGA2_SRC_INFO_SW_SW_CP_ENDIAN)) |
(s_RGA2_SRC_INFO_SW_SW_CP_ENDAIN(msg->endian_mode & 1)));
*bRGA_SRC_VIR_INFO = src_stride >> 2;
*bRGA_SRC_ACT_INFO =
(msg->src.act_w - 1) | ((msg->src.act_h - 1) << 16);
*bRGA_SRC_INFO = reg;
*bRGA_SRC_FG_COLOR = msg->fg_color;
*bRGA_SRC_BG_COLOR = msg->bg_color;
}
static void RGA2_set_reg_color_fill(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_CF_GR_A;
u32 *bRGA_CF_GR_B;
u32 *bRGA_CF_GR_G;
u32 *bRGA_CF_GR_R;
u32 *bRGA_SRC_FG_COLOR;
u32 *bRGA_MASK_ADDR;
u32 *bRGA_PAT_CON;
u32 mask_stride;
u32 *bRGA_SRC_VIR_INFO;
bRGA_SRC_FG_COLOR = (u32 *) (base + RGA2_SRC_FG_COLOR_OFFSET);
bRGA_CF_GR_A = (u32 *) (base + RGA2_CF_GR_A_OFFSET);
bRGA_CF_GR_B = (u32 *) (base + RGA2_CF_GR_B_OFFSET);
bRGA_CF_GR_G = (u32 *) (base + RGA2_CF_GR_G_OFFSET);
bRGA_CF_GR_R = (u32 *) (base + RGA2_CF_GR_R_OFFSET);
bRGA_MASK_ADDR = (u32 *) (base + RGA2_MASK_BASE_OFFSET);
bRGA_PAT_CON = (u32 *) (base + RGA2_PAT_CON_OFFSET);
bRGA_SRC_VIR_INFO = (u32 *) (base + RGA2_SRC_VIR_INFO_OFFSET);
mask_stride = msg->rop_mask_stride;
if (msg->color_fill_mode == 0) {
/* solid color */
*bRGA_CF_GR_A = (msg->gr_color.gr_x_a & 0xffff) |
(msg->gr_color.gr_y_a << 16);
*bRGA_CF_GR_B = (msg->gr_color.gr_x_b & 0xffff) |
(msg->gr_color.gr_y_b << 16);
*bRGA_CF_GR_G = (msg->gr_color.gr_x_g & 0xffff) |
(msg->gr_color.gr_y_g << 16);
*bRGA_CF_GR_R = (msg->gr_color.gr_x_r & 0xffff) |
(msg->gr_color.gr_y_r << 16);
*bRGA_SRC_FG_COLOR = msg->fg_color;
} else {
/* pattern color */
*bRGA_MASK_ADDR = (u32) msg->pat.yrgb_addr;
*bRGA_PAT_CON =
(msg->pat.act_w - 1) | ((msg->pat.act_h - 1) << 8)
| (msg->pat.x_offset << 16) | (msg->pat.y_offset << 24);
}
*bRGA_SRC_VIR_INFO = mask_stride << 16;
}
static void RGA2_set_reg_update_palette_table(u8 *base,
struct rga2_req *msg)
{
u32 *bRGA_MASK_BASE;
u32 *bRGA_FADING_CTRL;
bRGA_MASK_BASE = (u32 *) (base + RGA2_MASK_BASE_OFFSET);
bRGA_FADING_CTRL = (u32 *) (base + RGA2_FADING_CTRL_OFFSET);
*bRGA_FADING_CTRL = msg->fading_g_value << 8;
*bRGA_MASK_BASE = (u32) msg->pat.yrgb_addr;
}
static void RGA2_set_reg_update_patten_buff(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_PAT_MST;
u32 *bRGA_PAT_CON;
u32 *bRGA_PAT_START_POINT;
u32 *bRGA_FADING_CTRL;
u32 reg = 0;
struct rga_img_info_t *pat;
u32 num, offset;
pat = &msg->pat;
num = (pat->act_w * pat->act_h) - 1;
offset = pat->act_w * pat->y_offset + pat->x_offset;
bRGA_PAT_START_POINT = (u32 *) (base + RGA2_FADING_CTRL_OFFSET);
bRGA_PAT_MST = (u32 *) (base + RGA2_MASK_BASE_OFFSET);
bRGA_PAT_CON = (u32 *) (base + RGA2_PAT_CON_OFFSET);
bRGA_FADING_CTRL = (u32 *) (base + RGA2_FADING_CTRL_OFFSET);
*bRGA_PAT_MST = (u32) msg->pat.yrgb_addr;
*bRGA_PAT_START_POINT = (pat->act_w * pat->y_offset) + pat->x_offset;
reg = (pat->act_w - 1) | ((pat->act_h - 1) << 8) |
(pat->x_offset << 16) | (pat->y_offset << 24);
*bRGA_PAT_CON = reg;
*bRGA_FADING_CTRL = (num << 8) | offset;
}
static void RGA2_set_pat_info(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_PAT_CON;
u32 *bRGA_FADING_CTRL;
u32 reg = 0;
struct rga_img_info_t *pat;
u32 num, offset;
pat = &msg->pat;
num = ((pat->act_w * pat->act_h) - 1) & 0xff;
offset = (pat->act_w * pat->y_offset) + pat->x_offset;
bRGA_PAT_CON = (u32 *) (base + RGA2_PAT_CON_OFFSET);
bRGA_FADING_CTRL = (u32 *) (base + RGA2_FADING_CTRL_OFFSET);
reg = (pat->act_w - 1) | ((pat->act_h - 1) << 8) |
(pat->x_offset << 16) | (pat->y_offset << 24);
*bRGA_PAT_CON = reg;
*bRGA_FADING_CTRL = (num << 8) | offset;
}
static void RGA2_set_mmu_reg_info(u8 *base, struct rga2_req *msg)
{
u32 *bRGA_MMU_CTRL1;
u32 *bRGA_MMU_SRC_BASE;
u32 *bRGA_MMU_SRC1_BASE;
u32 *bRGA_MMU_DST_BASE;
u32 *bRGA_MMU_ELS_BASE;
u32 reg;
bRGA_MMU_CTRL1 = (u32 *) (base + RGA2_MMU_CTRL1_OFFSET);
bRGA_MMU_SRC_BASE = (u32 *) (base + RGA2_MMU_SRC_BASE_OFFSET);
bRGA_MMU_SRC1_BASE = (u32 *) (base + RGA2_MMU_SRC1_BASE_OFFSET);
bRGA_MMU_DST_BASE = (u32 *) (base + RGA2_MMU_DST_BASE_OFFSET);
bRGA_MMU_ELS_BASE = (u32 *) (base + RGA2_MMU_ELS_BASE_OFFSET);
reg = (msg->mmu_info.src0_mmu_flag & 0xf) |
((msg->mmu_info.src1_mmu_flag & 0xf) << 4) |
((msg->mmu_info.dst_mmu_flag & 0xf) << 8) |
((msg->mmu_info.els_mmu_flag & 0x3) << 12);
*bRGA_MMU_CTRL1 = reg;
*bRGA_MMU_SRC_BASE = (u32) (msg->mmu_info.src0_base_addr) >> 4;
*bRGA_MMU_SRC1_BASE = (u32) (msg->mmu_info.src1_base_addr) >> 4;
*bRGA_MMU_DST_BASE = (u32) (msg->mmu_info.dst_base_addr) >> 4;
*bRGA_MMU_ELS_BASE = (u32) (msg->mmu_info.els_base_addr) >> 4;
}
static int rga2_gen_reg_info(u8 *base, struct rga2_req *msg)
{
u8 dst_nn_quantize_en = 0;
RGA2_set_mode_ctrl(base, msg);
RGA2_set_pat_info(base, msg);
switch (msg->render_mode) {
case BITBLT_MODE:
RGA2_set_reg_src_info(base, msg);
RGA2_set_reg_dst_info(base, msg);
dst_nn_quantize_en = (msg->alpha_rop_flag >> 8) & 0x1;
if (dst_nn_quantize_en != 1) {
if ((msg->dst.format !=
RGA_FORMAT_Y4)) {
RGA2_set_reg_alpha_info(base, msg);
RGA2_set_reg_rop_info(base, msg);
}
}
if (msg->mosaic_info.enable)
RGA_set_reg_mosaic(base, msg);
if (msg->osd_info.enable)
RGA2_set_reg_osd(base, msg);
break;
case COLOR_FILL_MODE:
RGA2_set_reg_color_fill(base, msg);
RGA2_set_reg_dst_info(base, msg);
RGA2_set_reg_alpha_info(base, msg);
break;
case COLOR_PALETTE_MODE:
RGA2_set_reg_color_palette(base, msg);
RGA2_set_reg_dst_info(base, msg);
break;
case UPDATE_PALETTE_TABLE_MODE:
RGA2_set_reg_update_palette_table(base, msg);
break;
case UPDATE_PATTEN_BUF_MODE:
RGA2_set_reg_update_patten_buff(base, msg);
break;
default:
pr_err("ERROR msg render mode %d\n", msg->render_mode);
break;
}
RGA2_set_mmu_reg_info(base, msg);
return 0;
}
static void rga_cmd_to_rga2_cmd(struct rga_scheduler_t *scheduler,
struct rga_req *req_rga, struct rga2_req *req)
{
if (req_rga->render_mode == 6)
req->render_mode = UPDATE_PALETTE_TABLE_MODE;
else if (req_rga->render_mode == 7)
req->render_mode = UPDATE_PATTEN_BUF_MODE;
else if (req_rga->render_mode == 5)
req->render_mode = BITBLT_MODE;
else
req->render_mode = req_rga->render_mode;
memcpy(&req->src, &req_rga->src, sizeof(req_rga->src));
memcpy(&req->dst, &req_rga->dst, sizeof(req_rga->dst));
/* The application will only import pat or src1. */
if (req->render_mode == UPDATE_PALETTE_TABLE_MODE)
memcpy(&req->pat, &req_rga->pat, sizeof(req_rga->pat));
else
memcpy(&req->src1, &req_rga->pat, sizeof(req_rga->pat));
req->src.format = req_rga->src.format;
req->dst.format = req_rga->dst.format;
req->src1.format = req_rga->pat.format;
switch (req_rga->rotate_mode & 0x0F) {
case 1:
if (req_rga->sina == 0 && req_rga->cosa == 65536) {
/* rotate 0 */
req->rotate_mode = 0;
} else if (req_rga->sina == 65536 && req_rga->cosa == 0) {
/* rotate 90 */
req->rotate_mode = 1;
req->dst.x_offset = req_rga->dst.x_offset;
req->dst.act_w = req_rga->dst.act_h;
req->dst.act_h = req_rga->dst.act_w;
} else if (req_rga->sina == 0 && req_rga->cosa == -65536) {
/* rotate 180 */
req->rotate_mode = 2;
req->dst.x_offset = req_rga->dst.x_offset;
req->dst.y_offset = req_rga->dst.y_offset;
} else if (req_rga->sina == -65536 && req_rga->cosa == 0) {
/* totate 270 */
req->rotate_mode = 3;
req->dst.y_offset = req_rga->dst.y_offset;
req->dst.act_w = req_rga->dst.act_h;
req->dst.act_h = req_rga->dst.act_w;
}
break;
case 2:
//x_mirror
req->rotate_mode |= (1 << 4);
break;
case 3:
//y_mirror
req->rotate_mode |= (2 << 4);
break;
case 4:
//x_mirror+y_mirror
req->rotate_mode |= (3 << 4);
break;
default:
req->rotate_mode = 0;
break;
}
switch ((req_rga->rotate_mode & 0xF0) >> 4) {
case 2:
//x_mirror
req->rotate_mode |= (1 << 4);
break;
case 3:
//y_mirror
req->rotate_mode |= (2 << 4);
break;
case 4:
//x_mirror+y_mirror
req->rotate_mode |= (3 << 4);
break;
}
req->LUT_addr = req_rga->LUT_addr;
req->rop_mask_addr = req_rga->rop_mask_addr;
req->bitblt_mode = req_rga->bsfilter_flag;
req->src_a_global_val = req_rga->alpha_global_value;
req->dst_a_global_val = req_rga->alpha_global_value;
req->rop_code = req_rga->rop_code;
req->rop_mode = req_rga->alpha_rop_mode;
req->color_fill_mode = req_rga->color_fill_mode;
req->alpha_zero_key = req_rga->alpha_rop_mode >> 4;
req->src_trans_mode = req_rga->src_trans_mode;
req->color_key_min = req_rga->color_key_min;
req->color_key_max = req_rga->color_key_max;
req->fg_color = req_rga->fg_color;
req->bg_color = req_rga->bg_color;
memcpy(&req->gr_color, &req_rga->gr_color, sizeof(req_rga->gr_color));
req->palette_mode = req_rga->palette_mode;
req->yuv2rgb_mode = req_rga->yuv2rgb_mode;
req->endian_mode = req_rga->endian_mode;
req->rgb2yuv_mode = 0;
req->fading_alpha_value = 0;
req->fading_r_value = req_rga->fading.r;
req->fading_g_value = req_rga->fading.g;
req->fading_b_value = req_rga->fading.b;
/* alpha mode set */
req->alpha_rop_flag = 0;
/* alpha_rop_enable */
req->alpha_rop_flag |= (((req_rga->alpha_rop_flag & 1)));
/* rop_enable */
req->alpha_rop_flag |= (((req_rga->alpha_rop_flag >> 1) & 1) << 1);
/* fading_enable */
req->alpha_rop_flag |= (((req_rga->alpha_rop_flag >> 2) & 1) << 2);
/* alpha_cal_mode_sel */
req->alpha_rop_flag |= (((req_rga->alpha_rop_flag >> 4) & 1) << 3);
/* dst_dither_down */
req->alpha_rop_flag |= (((req_rga->alpha_rop_flag >> 5) & 1) << 6);
/* gradient fill mode sel */
req->alpha_rop_flag |= (((req_rga->alpha_rop_flag >> 6) & 1) << 7);
/* RGA_NN_QUANTIZE */
req->alpha_rop_flag |= (((req_rga->alpha_rop_flag >> 8) & 1) << 8);
req->dither_mode = req_rga->dither_mode;
/* RGA2 1106 add */
memcpy(&req->mosaic_info, &req_rga->mosaic_info, sizeof(req_rga->mosaic_info));
if ((scheduler->data->feature & RGA_YIN_YOUT) &&
rga_is_only_y_format(req->src.format) &&
rga_is_only_y_format(req->dst.format))
req->yin_yout_en = true;
req->uvhds_mode = req_rga->uvhds_mode;
req->uvvds_mode = req_rga->uvvds_mode;
memcpy(&req->osd_info, &req_rga->osd_info, sizeof(req_rga->osd_info));
if (((req_rga->alpha_rop_flag) & 1)) {
if ((req_rga->alpha_rop_flag >> 3) & 1) {
req->alpha_config.enable = true;
if ((req_rga->alpha_rop_flag >> 9) & 1) {
req->alpha_config.fg_pre_multiplied = false;
req->alpha_config.bg_pre_multiplied = false;
} else if (req->osd_info.enable) {
req->alpha_config.fg_pre_multiplied = true;
/* set dst(osd_block) real color mode */
req->alpha_config.bg_pre_multiplied = false;
} else {
req->alpha_config.fg_pre_multiplied = true;
req->alpha_config.bg_pre_multiplied = true;
}
req->alpha_config.fg_pixel_alpha_en = rga_is_alpha_format(req->src.format);
if (req->bitblt_mode)
req->alpha_config.bg_pixel_alpha_en =
rga_is_alpha_format(req->src1.format);
else
req->alpha_config.bg_pixel_alpha_en =
rga_is_alpha_format(req->dst.format);
req->alpha_config.fg_global_alpha_en = false;
req->alpha_config.bg_global_alpha_en = false;
req->alpha_config.fg_global_alpha_value = req_rga->alpha_global_value;
req->alpha_config.bg_global_alpha_value = req_rga->alpha_global_value;
/* porter duff alpha enable */
switch (req_rga->PD_mode) {
/* dst = 0 */
case 0:
break;
case 1:
req->alpha_config.mode = RGA_ALPHA_BLEND_SRC;
break;
case 2:
req->alpha_config.mode = RGA_ALPHA_BLEND_DST;
break;
case 3:
if ((req_rga->alpha_rop_mode & 3) == 0) {
/* both use globalAlpha. */
req->alpha_config.fg_global_alpha_en = true;
req->alpha_config.bg_global_alpha_en = true;
} else if ((req_rga->alpha_rop_mode & 3) == 1) {
/* Do not use globalAlpha. */
req->alpha_config.fg_global_alpha_en = false;
req->alpha_config.bg_global_alpha_en = false;
} else {
/* dst use globalAlpha */
req->alpha_config.fg_global_alpha_en = false;
req->alpha_config.bg_global_alpha_en = true;
}
req->alpha_config.mode = RGA_ALPHA_BLEND_SRC_OVER;
break;
case 4:
req->alpha_config.mode = RGA_ALPHA_BLEND_DST_OVER;
break;
case 5:
req->alpha_config.mode = RGA_ALPHA_BLEND_SRC_IN;
break;
case 6:
req->alpha_config.mode = RGA_ALPHA_BLEND_DST_IN;
break;
case 7:
req->alpha_config.mode = RGA_ALPHA_BLEND_SRC_OUT;
break;
case 8:
req->alpha_config.mode = RGA_ALPHA_BLEND_DST_OUT;
break;
case 9:
req->alpha_config.mode = RGA_ALPHA_BLEND_SRC_ATOP;
break;
case 10:
req->alpha_config.mode = RGA_ALPHA_BLEND_DST_ATOP;
break;
case 11:
req->alpha_config.mode = RGA_ALPHA_BLEND_XOR;
break;
case 12:
req->alpha_config.mode = RGA_ALPHA_BLEND_CLEAR;
break;
default:
break;
}
}
}
if (req_rga->mmu_info.mmu_en && (req_rga->mmu_info.mmu_flag & 1) == 1) {
req->mmu_info.src0_mmu_flag = 1;
req->mmu_info.dst_mmu_flag = 1;
if (req_rga->mmu_info.mmu_flag >> 31) {
req->mmu_info.src0_mmu_flag =
((req_rga->mmu_info.mmu_flag >> 8) & 1);
req->mmu_info.src1_mmu_flag =
((req_rga->mmu_info.mmu_flag >> 9) & 1);
req->mmu_info.dst_mmu_flag =
((req_rga->mmu_info.mmu_flag >> 10) & 1);
req->mmu_info.els_mmu_flag =
((req_rga->mmu_info.mmu_flag >> 11) & 1);
} else {
if (req_rga->src.yrgb_addr >= 0xa0000000) {
req->mmu_info.src0_mmu_flag = 0;
req->src.yrgb_addr =
req_rga->src.yrgb_addr - 0x60000000;
req->src.uv_addr =
req_rga->src.uv_addr - 0x60000000;
req->src.v_addr =
req_rga->src.v_addr - 0x60000000;
}
if (req_rga->dst.yrgb_addr >= 0xa0000000) {
req->mmu_info.dst_mmu_flag = 0;
req->dst.yrgb_addr =
req_rga->dst.yrgb_addr - 0x60000000;
}
if (req_rga->pat.yrgb_addr >= 0xa0000000) {
req->mmu_info.src1_mmu_flag = 0;
req->src1.yrgb_addr =
req_rga->pat.yrgb_addr - 0x60000000;
}
}
}
}
static void rga2_soft_reset(struct rga_scheduler_t *scheduler)
{
u32 i;
u32 reg;
u32 iommu_dte_addr = 0;
if (scheduler->data->mmu == RGA_IOMMU)
iommu_dte_addr = rga_read(RGA_IOMMU_DTE_ADDR, scheduler);
rga_write(m_RGA2_SYS_CTRL_ACLK_SRESET_P | m_RGA2_SYS_CTRL_CCLK_SRESET_P |
m_RGA2_SYS_CTRL_RST_PROTECT_P,
RGA2_SYS_CTRL, scheduler);
for (i = 0; i < RGA_RESET_TIMEOUT; i++) {
/* RGA_SYS_CTRL */
reg = rga_read(RGA2_SYS_CTRL, scheduler) & 1;
if (reg == 0)
break;
udelay(1);
}
if (scheduler->data->mmu == RGA_IOMMU) {
rga_write(iommu_dte_addr, RGA_IOMMU_DTE_ADDR, scheduler);
/* enable iommu */
rga_write(RGA_IOMMU_CMD_ENABLE_PAGING, RGA_IOMMU_COMMAND, scheduler);
}
if (i == RGA_RESET_TIMEOUT)
pr_err("RAG2 core[%d] soft reset timeout.\n", scheduler->core);
else
pr_info("RGA2 core[%d] soft reset complete.\n", scheduler->core);
}
static int rga2_check_param(const struct rga_hw_data *data, const struct rga2_req *req)
{
if (!((req->render_mode == COLOR_FILL_MODE))) {
if (unlikely(rga_hw_out_of_range(&data->input_range,
req->src.act_w, req->src.act_h))) {
pr_err("invalid src resolution act_w = %d, act_h = %d\n",
req->src.act_w, req->src.act_h);
return -EINVAL;
}
if (unlikely(req->src.vir_w * rga_get_pixel_stride_from_format(req->src.format) >
data->max_byte_stride * 8)) {
pr_err("invalid src stride, stride = %d, max_byte_stride = %d\n",
req->src.vir_w, data->max_byte_stride);
return -EINVAL;
}
if (unlikely(req->src.vir_w < req->src.act_w)) {
pr_err("invalid src_vir_w act_w = %d, vir_w = %d\n",
req->src.act_w, req->src.vir_w);
return -EINVAL;
}
}
if (unlikely(rga_hw_out_of_range(&data->output_range, req->dst.act_w, req->dst.act_h))) {
pr_err("invalid dst resolution act_w = %d, act_h = %d\n",
req->dst.act_w, req->dst.act_h);
return -EINVAL;
}
if (unlikely(req->dst.vir_w * rga_get_pixel_stride_from_format(req->dst.format) >
data->max_byte_stride * 8)) {
pr_err("invalid dst stride, stride = %d, max_byte_stride = %d\n",
req->dst.vir_w, data->max_byte_stride);
return -EINVAL;
}
if (unlikely(req->dst.vir_w < req->dst.act_w)) {
if (req->rotate_mode != 1) {
pr_err("invalid dst_vir_w act_h = %d, vir_h = %d\n",
req->dst.act_w, req->dst.vir_w);
return -EINVAL;
}
}
return 0;
}
static int rga2_align_check(struct rga2_req *req)
{
if (rga_is_yuv10bit_format(req->src.format))
if ((req->src.vir_w % 16) || (req->src.x_offset % 2) ||
(req->src.act_w % 2) || (req->src.y_offset % 2) ||
(req->src.act_h % 2) || (req->src.vir_h % 2))
pr_info("err src wstride, 10bit yuv\n");
if (rga_is_yuv10bit_format(req->dst.format))
if ((req->dst.vir_w % 16) || (req->dst.x_offset % 2) ||
(req->dst.act_w % 2) || (req->dst.y_offset % 2) ||
(req->dst.act_h % 2) || (req->dst.vir_h % 2))
pr_info("err dst wstride, 10bit yuv\n");
if (rga_is_yuv8bit_format(req->src.format))
if ((req->src.vir_w % 4) || (req->src.x_offset % 2) ||
(req->src.act_w % 2) || (req->src.y_offset % 2) ||
(req->src.act_h % 2) || (req->src.vir_h % 2))
pr_info("err src wstride, 8bit yuv\n");
if (rga_is_yuv8bit_format(req->dst.format))
if ((req->dst.vir_w % 4) || (req->dst.x_offset % 2) ||
(req->dst.act_w % 2) || (req->dst.y_offset % 2) ||
(req->dst.act_h % 2) || (req->dst.vir_h % 2))
pr_info("err dst wstride, 8bit yuv\n");
return 0;
}
static void print_debug_info(struct rga2_req *req)
{
pr_info("render_mode:%s,bitblit_mode=%d,rotate_mode:%s\n",
rga_get_render_mode_str(req->render_mode), req->bitblt_mode,
rga_get_rotate_mode_str(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=%s\n",
req->src.x_offset, req->src.y_offset,
rga_get_format_name(req->src.format));
if (req->src1.yrgb_addr != 0 || req->src1.uv_addr != 0
|| req->src1.v_addr != 0) {
pr_info("src1: y=%lx uv=%lx v=%lx aw=%d ah=%d vw=%d vh=%d\n",
(unsigned long)req->src1.yrgb_addr,
(unsigned long)req->src1.uv_addr,
(unsigned long)req->src1.v_addr,
req->src1.act_w, req->src1.act_h,
req->src1.vir_w, req->src1.vir_h);
pr_info("src1: xoff=%d yoff=%d format=%s\n",
req->src1.x_offset, req->src1.y_offset,
rga_get_format_name(req->src1.format));
}
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=%s\n",
req->dst.x_offset, req->dst.y_offset,
rga_get_format_name(req->dst.format));
pr_info("mmu: src=%.2x src1=%.2x dst=%.2x els=%.2x\n",
req->mmu_info.src0_mmu_flag, req->mmu_info.src1_mmu_flag,
req->mmu_info.dst_mmu_flag, req->mmu_info.els_mmu_flag);
pr_info("alpha: flag %x mode=%s\n",
req->alpha_rop_flag, rga_get_blend_mode_str(req->alpha_config.mode));
pr_info("alpha: pre_multi=[%d,%d] pixl=[%d,%d] glb=[%d,%d]\n",
req->alpha_config.fg_pre_multiplied, req->alpha_config.bg_pre_multiplied,
req->alpha_config.fg_pixel_alpha_en, req->alpha_config.bg_pixel_alpha_en,
req->alpha_config.fg_global_alpha_en, req->alpha_config.bg_global_alpha_en);
pr_info("alpha: fg_global_alpha=%x bg_global_alpha=%x\n",
req->alpha_config.fg_global_alpha_value, req->alpha_config.bg_global_alpha_value);
pr_info("yuv2rgb mode is %x\n", req->yuv2rgb_mode);
}
static int rga2_init_reg(struct rga_job *job)
{
struct rga2_req req;
int ret = 0;
struct rga_scheduler_t *scheduler = NULL;
scheduler = job->scheduler;
if (unlikely(scheduler == NULL)) {
pr_err("failed to get scheduler, %s(%d)\n", __func__, __LINE__);
return -EINVAL;
}
memset(&req, 0x0, sizeof(req));
rga_cmd_to_rga2_cmd(scheduler, &job->rga_command_base, &req);
memcpy(&job->full_csc, &job->rga_command_base.full_csc, sizeof(job->full_csc));
memcpy(&job->pre_intr_info, &job->rga_command_base.pre_intr_info,
sizeof(job->pre_intr_info));
/* check value if legal */
ret = rga2_check_param(scheduler->data, &req);
if (ret == -EINVAL) {
pr_err("req argument is inval\n");
return ret;
}
rga2_align_check(&req);
/* for debug */
if (DEBUGGER_EN(MSG))
print_debug_info(&req);
/* RGA2 mmu set */
if ((req.mmu_info.src0_mmu_flag & 1) || (req.mmu_info.src1_mmu_flag & 1) ||
(req.mmu_info.dst_mmu_flag & 1) || (req.mmu_info.els_mmu_flag & 1)) {
if (scheduler->data->mmu != RGA_MMU) {
pr_err("core[%d] has no MMU, please use physically contiguous memory.\n",
scheduler->core);
pr_err("mmu_flag[src, src1, dst, els] = [0x%x, 0x%x, 0x%x, 0x%x]\n",
req.mmu_info.src0_mmu_flag, req.mmu_info.src1_mmu_flag,
req.mmu_info.dst_mmu_flag, req.mmu_info.els_mmu_flag);
return -EINVAL;
}
ret = rga_set_mmu_base(job, &req);
if (ret < 0) {
pr_err("%s, [%d] set mmu info error\n", __func__,
__LINE__);
return -EFAULT;
}
}
/* In slave mode, the current frame completion interrupt must be enabled. */
if (scheduler->data->mmu == RGA_IOMMU)
req.CMD_fin_int_enable = 1;
if (rga2_gen_reg_info((uint8_t *)job->cmd_reg, &req) == -1) {
pr_err("gen reg info error\n");
return -EINVAL;
}
return ret;
}
static void rga2_dump_read_back_sys_reg(struct rga_scheduler_t *scheduler)
{
int i;
unsigned long flags;
uint32_t sys_reg[24] = {0};
spin_lock_irqsave(&scheduler->irq_lock, flags);
for (i = 0; i < 24; i++)
sys_reg[i] = rga_read(RGA2_SYS_REG_BASE + i * 4, scheduler);
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
pr_info("SYS_READ_BACK_REG\n");
for (i = 0; i < 6; i++)
pr_info("0x%04x : %.8x %.8x %.8x %.8x\n",
RGA2_SYS_REG_BASE + i * 0x10,
sys_reg[0 + i * 4], sys_reg[1 + i * 4],
sys_reg[2 + i * 4], sys_reg[3 + i * 4]);
}
static void rga2_dump_read_back_csc_reg(struct rga_scheduler_t *scheduler)
{
int i;
unsigned long flags;
uint32_t csc_reg[12] = {0};
spin_lock_irqsave(&scheduler->irq_lock, flags);
for (i = 0; i < 12; i++)
csc_reg[i] = rga_read(RGA2_CSC_REG_BASE + i * 4, scheduler);
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
pr_info("CSC_READ_BACK_REG\n");
for (i = 0; i < 3; i++)
pr_info("0x%04x : %.8x %.8x %.8x %.8x\n",
RGA2_CSC_REG_BASE + i * 0x10,
csc_reg[0 + i * 4], csc_reg[1 + i * 4],
csc_reg[2 + i * 4], csc_reg[3 + i * 4]);
}
static void rga2_dump_read_back_cmd_reg(struct rga_scheduler_t *scheduler)
{
int i;
unsigned long flags;
uint32_t cmd_reg[32] = {0};
spin_lock_irqsave(&scheduler->irq_lock, flags);
for (i = 0; i < 32; i++)
cmd_reg[i] = rga_read(RGA2_CMD_REG_BASE + i * 4, scheduler);
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
pr_info("CMD_READ_BACK_REG\n");
for (i = 0; i < 8; i++)
pr_info("0x%04x : %.8x %.8x %.8x %.8x\n",
RGA2_CMD_REG_BASE + i * 0x10,
cmd_reg[0 + i * 4], cmd_reg[1 + i * 4],
cmd_reg[2 + i * 4], cmd_reg[3 + i * 4]);
}
static void rga2_dump_read_back_reg(struct rga_scheduler_t *scheduler)
{
rga2_dump_read_back_sys_reg(scheduler);
rga2_dump_read_back_csc_reg(scheduler);
rga2_dump_read_back_cmd_reg(scheduler);
}
static void rga2_set_pre_intr_reg(struct rga_job *job, struct rga_scheduler_t *scheduler)
{
uint32_t reg;
if (job->pre_intr_info.read_intr_en) {
reg = s_RGA2_READ_LINE_SW_INTR_LINE_RD_TH(job->pre_intr_info.read_threshold);
rga_write(reg, RGA2_READ_LINE_CNT, scheduler);
}
if (job->pre_intr_info.write_intr_en) {
reg = s_RGA2_WRITE_LINE_SW_INTR_LINE_WR_START(job->pre_intr_info.write_start);
reg = ((reg & (~m_RGA2_WRITE_LINE_SW_INTR_LINE_WR_STEP)) |
(s_RGA2_WRITE_LINE_SW_INTR_LINE_WR_STEP(job->pre_intr_info.write_step)));
rga_write(reg, RGA2_WRITE_LINE_CNT, scheduler);
}
reg = rga_read(RGA2_SYS_CTRL, scheduler);
reg = ((reg & (~m_RGA2_SYS_CTRL_HOLD_MODE_EN)) |
(s_RGA2_SYS_CTRL_HOLD_MODE_EN(job->pre_intr_info.read_hold_en)));
rga_write(reg, RGA2_SYS_CTRL, scheduler);
reg = rga_read(RGA2_INT, scheduler);
reg = (reg | s_RGA2_INT_LINE_RD_CLEAR(0x1) | s_RGA2_INT_LINE_WR_CLEAR(0x1));
reg = ((reg & (~m_RGA2_INT_LINE_RD_EN)) |
(s_RGA2_INT_LINE_RD_EN(job->pre_intr_info.read_intr_en)));
reg = ((reg & (~m_RGA2_INT_LINE_WR_EN)) |
(s_RGA2_INT_LINE_WR_EN(job->pre_intr_info.write_intr_en)));
rga_write(reg, RGA2_INT, scheduler);
}
static void rga2_set_reg_full_csc(struct rga_job *job, struct rga_scheduler_t *scheduler)
{
uint8_t clip_y_max, clip_y_min;
uint8_t clip_uv_max, clip_uv_min;
clip_y_max = 0xff;
clip_y_min = 0x0;
clip_uv_max = 0xff;
clip_uv_min = 0;
/* full csc coefficient */
/* Y coefficient */
rga_write(job->full_csc.coe_y.r_v | (clip_y_max << 16) | (clip_y_min << 24),
RGA2_DST_CSC_00, scheduler);
rga_write(job->full_csc.coe_y.g_y | (clip_uv_max << 16) | (clip_uv_min << 24),
RGA2_DST_CSC_01, scheduler);
rga_write(job->full_csc.coe_y.b_u, RGA2_DST_CSC_02, scheduler);
rga_write(job->full_csc.coe_y.off, RGA2_DST_CSC_OFF0, scheduler);
/* U coefficient */
rga_write(job->full_csc.coe_u.r_v, RGA2_DST_CSC_10, scheduler);
rga_write(job->full_csc.coe_u.g_y, RGA2_DST_CSC_11, scheduler);
rga_write(job->full_csc.coe_u.b_u, RGA2_DST_CSC_12, scheduler);
rga_write(job->full_csc.coe_u.off, RGA2_DST_CSC_OFF1, scheduler);
/* V coefficient */
rga_write(job->full_csc.coe_v.r_v, RGA2_DST_CSC_20, scheduler);
rga_write(job->full_csc.coe_v.g_y, RGA2_DST_CSC_21, scheduler);
rga_write(job->full_csc.coe_v.b_u, RGA2_DST_CSC_22, scheduler);
rga_write(job->full_csc.coe_v.off, RGA2_DST_CSC_OFF2, scheduler);
}
static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler)
{
int i;
bool master_mode_en;
uint32_t sys_ctrl;
ktime_t now = ktime_get();
/*
* Currently there is no iova allocated for storing cmd for the IOMMU device,
* so the iommu device needs to use the slave mode.
*/
if (scheduler->data->mmu != RGA_IOMMU)
master_mode_en = true;
else
master_mode_en = false;
if (job->pre_intr_info.enable)
rga2_set_pre_intr_reg(job, scheduler);
if (job->full_csc.flag)
rga2_set_reg_full_csc(job, scheduler);
if (DEBUGGER_EN(REG)) {
uint32_t *p;
rga2_dump_read_back_sys_reg(scheduler);
rga2_dump_read_back_csc_reg(scheduler);
p = job->cmd_reg;
pr_info("CMD_REG\n");
for (i = 0; i < 8; i++)
pr_info("i = %x : %.8x %.8x %.8x %.8x\n", i,
p[0 + i * 4], p[1 + i * 4],
p[2 + i * 4], p[3 + i * 4]);
}
/* All CMD finish int */
rga_write(rga_read(RGA2_INT, scheduler) |
m_RGA2_INT_ERROR_ENABLE_MASK | m_RGA2_INT_ALL_CMD_DONE_INT_EN,
RGA2_INT, scheduler);
/* sys_reg init */
sys_ctrl = m_RGA2_SYS_CTRL_AUTO_CKG | m_RGA2_SYS_CTRL_AUTO_RST |
m_RGA2_SYS_CTRL_RST_PROTECT_P | m_RGA2_SYS_CTRL_DST_WR_OPT_DIS |
m_RGA2_SYS_CTRL_SRC0YUV420SP_RD_OPT_DIS;
if (master_mode_en) {
/* master mode */
sys_ctrl |= s_RGA2_SYS_CTRL_CMD_MODE(1);
/* cmd buffer flush cache to ddr */
rga_dma_sync_flush_range(&job->cmd_reg[0], &job->cmd_reg[32], scheduler);
/* set cmd_addr */
rga_write(virt_to_phys(job->cmd_reg), RGA2_CMD_BASE, scheduler);
rga_write(sys_ctrl, RGA2_SYS_CTRL, scheduler);
rga_write(m_RGA2_CMD_CTRL_CMD_LINE_ST_P, RGA2_CMD_CTRL, scheduler);
} else {
/* slave mode */
sys_ctrl |= s_RGA2_SYS_CTRL_CMD_MODE(0) | m_RGA2_SYS_CTRL_CMD_OP_ST_P;
/* set cmd_reg */
for (i = 0; i <= 32; i++)
rga_write(job->cmd_reg[i], 0x100 + i * 4, scheduler);
rga_write(sys_ctrl, RGA2_SYS_CTRL, scheduler);
}
if (DEBUGGER_EN(REG))
pr_info("sys_ctrl = %x, int = %x\n",
rga_read(RGA2_SYS_CTRL, scheduler),
rga_read(RGA2_INT, scheduler));
if (DEBUGGER_EN(TIME))
pr_info("set cmd use time = %lld\n",
ktime_us_delta(now, job->timestamp));
job->hw_running_time = now;
job->hw_recoder_time = now;
if (DEBUGGER_EN(REG))
rga2_dump_read_back_reg(scheduler);
return 0;
}
static int rga2_get_version(struct rga_scheduler_t *scheduler)
{
u32 major_version, minor_version, svn_version;
u32 reg_version;
if (!scheduler) {
pr_err("scheduler is null\n");
return -EINVAL;
}
reg_version = rga_read(RGA2_VERSION_NUM, scheduler);
major_version = (reg_version & RGA2_MAJOR_VERSION_MASK) >> 24;
minor_version = (reg_version & RGA2_MINOR_VERSION_MASK) >> 20;
svn_version = (reg_version & RGA2_SVN_VERSION_MASK);
/*
* some old rga ip has no rga version register, so force set to 2.00
*/
if (!major_version && !minor_version)
major_version = 2;
snprintf(scheduler->version.str, 10, "%x.%01x.%05x", major_version,
minor_version, svn_version);
scheduler->version.major = major_version;
scheduler->version.minor = minor_version;
scheduler->version.revision = svn_version;
return 0;
}
static int rga2_read_back_reg(struct rga_job *job, struct rga_scheduler_t *scheduler)
{
if (job->rga_command_base.osd_info.enable) {
job->rga_command_base.osd_info.cur_flags0 = rga_read(RGA2_OSD_CUR_FLAGS0,
scheduler);
job->rga_command_base.osd_info.cur_flags1 = rga_read(RGA2_OSD_CUR_FLAGS1,
scheduler);
}
return 0;
}
static int rga2_irq(struct rga_scheduler_t *scheduler)
{
struct rga_job *job = scheduler->running_job;
/* The hardware interrupt top-half don't need to lock the scheduler. */
if (job == NULL)
return IRQ_HANDLED;
if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state))
return IRQ_WAKE_THREAD;
job->intr_status = rga_read(RGA2_INT, scheduler);
job->hw_status = rga_read(RGA2_STATUS2, scheduler);
job->cmd_status = rga_read(RGA2_STATUS1, scheduler);
if (DEBUGGER_EN(INT_FLAG))
pr_info("irq handler, INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x]\n",
job->intr_status, job->hw_status, job->cmd_status);
if (job->intr_status &
(m_RGA2_INT_CUR_CMD_DONE_INT_FLAG | m_RGA2_INT_ALL_CMD_DONE_INT_FLAG)) {
set_bit(RGA_JOB_STATE_FINISH, &job->state);
} else if (job->intr_status & m_RGA2_INT_ERROR_FLAG_MASK) {
set_bit(RGA_JOB_STATE_INTR_ERR, &job->state);
pr_err("irq handler err! INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x]\n",
job->intr_status, job->hw_status, job->cmd_status);
scheduler->ops->soft_reset(scheduler);
}
/*clear INTR */
rga_write(rga_read(RGA2_INT, scheduler) |
(m_RGA2_INT_ERROR_CLEAR_MASK |
m_RGA2_INT_ALL_CMD_DONE_INT_CLEAR | m_RGA2_INT_NOW_CMD_DONE_INT_CLEAR |
m_RGA2_INT_LINE_RD_CLEAR | m_RGA2_INT_LINE_WR_CLEAR),
RGA2_INT, scheduler);
return IRQ_WAKE_THREAD;
}
static int rga2_isr_thread(struct rga_job *job, struct rga_scheduler_t *scheduler)
{
if (DEBUGGER_EN(INT_FLAG))
pr_info("isr thread, INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x]\n",
rga_read(RGA2_INT, scheduler),
rga_read(RGA2_STATUS2, scheduler),
rga_read(RGA2_STATUS1, scheduler));
if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) {
if (job->hw_status & m_RGA2_STATUS2_RPP_ERROR)
pr_err("RGA current status: rpp error!\n");
if (job->hw_status & m_RGA2_STATUS2_BUS_ERROR)
pr_err("RGA current status: bus error!\n");
if (job->intr_status & m_RGA2_INT_ERROR_INT_FLAG) {
pr_err("RGA bus error intr, please check your configuration and buffer.\n");
job->ret = -EFAULT;
} else if (job->intr_status & m_RGA2_INT_MMU_INT_FLAG) {
pr_err("mmu failed, please check size of the buffer or whether the buffer has been freed.\n");
job->ret = -EACCES;
}
if (job->ret == 0) {
pr_err("rga intr error[0x%x]!\n", job->intr_status);
job->ret = -EFAULT;
}
}
return IRQ_HANDLED;
}
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,
.read_back_reg = rga2_read_back_reg,
.irq = rga2_irq,
.isr_thread = rga2_isr_thread,
};