diff --git a/linux-6.6/rk3568_patch/kernel.patch b/linux-6.6/rk3568_patch/kernel.patch index 1e12a66bb8706a40a3e4796bdff677eaebe4e272..592760a56883762721013e9d447304bd8bb23d31 100644 --- a/linux-6.6/rk3568_patch/kernel.patch +++ b/linux-6.6/rk3568_patch/kernel.patch @@ -1894659,10 +1894659,10 @@ index 000000000..11f401de2 +obj-$(CONFIG_ROCKCHIP_MULTI_RGA) += rga3.o diff --git a/drivers/video/rockchip/rga3/include/rga.h b/drivers/video/rockchip/rga3/include/rga.h new file mode 100644 -index 000000000..2a60a1ae7 +index 000000000..671867b22 --- /dev/null +++ b/drivers/video/rockchip/rga3/include/rga.h -@@ -0,0 +1,944 @@ +@@ -0,0 +1,1007 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _RGA_DRIVER_H_ +#define _RGA_DRIVER_H_ @@ -1894696,7 +1894696,7 @@ index 000000000..2a60a1ae7 +#define RGA_IMPORT_DMA 0x601d +#define RGA_RELEASE_DMA 0x601e + -+#define RGA_TASK_NUM_MAX 50 ++#define RGA_TASK_NUM_MAX 256 + +#define RGA_OUT_OF_RESOURCES -10 +#define RGA_MALLOC_ERROR -11 @@ -1894734,6 +1894734,17 @@ index 000000000..2a60a1ae7 + RGA_MODE_X_MIRROR | \ + RGA_MODE_Y_MIRROR) + ++enum rga_csc_mode { ++ RGA_Y2R_BT601_LIMIT = 0x1 << 0, ++ RGA_Y2R_BT601_FULL = 0x2 << 0, ++ RGA_Y2R_BT709_LIMIT = 0x3 << 0, ++ RGA_Y2R_MASK = 0x3 << 0, ++ RGA_R2Y_BT601_LIMIT = 0x2 << 0, ++ RGA_R2Y_BT601_FULL = 0x1 << 0, ++ RGA_R2Y_BT709_LIMIT = 0x3 << 0, ++ RGA_R2Y_MASK = 0x3 << 0, ++}; ++ +enum rga_memory_type { + RGA_DMA_BUFFER = 0, + RGA_VIRTUAL_ADDRESS, @@ -1894752,9 +1894763,19 @@ index 000000000..2a60a1ae7 +}; + +enum RGA_SCHEDULER_CORE { -+ RGA_SCHEDULER_RGA3_CORE0 = 1 << 0, -+ RGA_SCHEDULER_RGA3_CORE1 = 1 << 1, -+ RGA_SCHEDULER_RGA2_CORE0 = 1 << 2, ++ RGA3_SCHEDULER_CORE0 = 1 << 0, ++ RGA3_SCHEDULER_CORE1 = 1 << 1, ++ RGA2_SCHEDULER_CORE0 = 1 << 2, ++ RGA2_SCHEDULER_CORE1 = 1 << 3, ++ RGA_CORE_MASK = 0xf, ++ RGA_NONE_CORE = 0x0, ++}; ++ ++enum rga_scale_interp { ++ RGA_INTERP_DEFAULT = 0x0, ++ RGA_INTERP_LINEAR = 0x1, ++ RGA_INTERP_BICUBIC = 0x2, ++ RGA_INTERP_AVERAGE = 0x3, +}; + +/* RGA process mode enum */ @@ -1894772,6 +1894793,9 @@ index 000000000..2a60a1ae7 + RGA_RASTER_MODE = 0x1 << 0, + RGA_FBC_MODE = 0x1 << 1, + RGA_TILE_MODE = 0x1 << 2, ++ RGA_TILE4x4_MODE = 0x1 << 3, ++ RGA_RKFBC_MODE = 0x1 << 4, ++ RGA_AFBC32x8_MODE = 0x1 << 5, +}; + +enum { @@ -1894811,6 +1894835,7 @@ index 000000000..2a60a1ae7 + RGA_OSD = 0x1 << 11, + RGA_PRE_INTR = 0x1 << 12, + RGA_FULL_CSC = 0x1 << 13, ++ RGA_GAUSS = 0x1 << 14, +}; + +enum rga_surf_format { @@ -1894871,6 +1894896,12 @@ index 000000000..2a60a1ae7 + RGA_FORMAT_ABGR_4444 = 0x2f, + + RGA_FORMAT_RGBA_2BPP = 0x30, ++ RGA_FORMAT_A8 = 0x31, ++ ++ RGA_FORMAT_YCbCr_444_SP = 0x32, ++ RGA_FORMAT_YCrCb_444_SP = 0x33, ++ ++ RGA_FORMAT_Y8 = 0x34, + + RGA_FORMAT_UNKNOWN = 0x100, +}; @@ -1895067,6 +1895098,11 @@ index 000000000..2a60a1ae7 + uint8_t mode; +}; + ++struct rga_gauss_config { ++ uint32_t size; ++ uint64_t coe_ptr; ++}; ++ +/* MAX(min, (max - channel_value)) */ +struct rga_osd_invert_factor { + uint8_t alpha_max; @@ -1895244,6 +1895280,22 @@ index 000000000..2a60a1ae7 + uint32_t user_close_fence:1; +}; + ++struct rga_interp { ++ uint8_t horiz:4; ++ uint8_t verti:4; ++}; ++ ++struct rga_iommu_prefetch { ++ uint32_t y_threshold; ++ uint32_t uv_threshold; ++}; ++ ++struct rga_rgba5551_alpha { ++ uint16_t flags; ++ uint8_t alpha0; ++ uint8_t alpha1; ++}; ++ +struct rga_req { + /* (enum) process mode sel */ + uint8_t render_mode; @@ -1895277,8 +1895329,11 @@ index 000000000..2a60a1ae7 + /* ([7] = 1 AA_enable) */ + uint16_t alpha_rop_flag; + -+ /* 0 nearst / 1 bilnear / 2 bicubic */ -+ uint8_t scale_mode; ++ union { ++ struct rga_interp interp; ++ /* 0 nearst / 1 bilnear / 2 bicubic */ ++ uint8_t scale_mode; ++ }; + + /* color key max */ + uint32_t color_key_max; @@ -1895370,7 +1895425,11 @@ index 000000000..2a60a1ae7 + + struct rga_csc_clip full_csc_clip; + -+ uint8_t reservr[43]; ++ struct rga_rgba5551_alpha rgba5551_alpha; ++ ++ struct rga_gauss_config gauss_config; ++ ++ uint8_t reservr[24]; +}; + +struct rga_alpha_config { @@ -1895497,6 +1895556,14 @@ index 000000000..2a60a1ae7 + uint8_t uvvds_mode; + + struct rga_osd_info osd_info; ++ ++ struct rga_interp interp; ++ ++ struct rga_iommu_prefetch iommu_prefetch; ++ ++ struct rga_rgba5551_alpha rgba5551_alpha; ++ ++ struct rga_gauss_config gauss_config; +}; + +struct rga3_req { @@ -1895521,7 +1895588,8 @@ index 000000000..2a60a1ae7 + struct rga_alpha_config alpha_config; + + /* for abb mode presever alpha. */ -+ bool abb_alpha_pass; ++ bool bg_alpha_pass; ++ bool fg_alpha_pass; + + u8 scale_bicu_mode; + @@ -1895539,11 +1895607,6 @@ index 000000000..2a60a1ae7 + 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; + @@ -1895609,10 +1895672,10 @@ index 000000000..2a60a1ae7 +#endif /*_RGA_DRIVER_H_*/ diff --git a/drivers/video/rockchip/rga3/include/rga2_reg_info.h b/drivers/video/rockchip/rga3/include/rga2_reg_info.h new file mode 100644 -index 000000000..add2f41bd +index 000000000..187460833 --- /dev/null +++ b/drivers/video/rockchip/rga3/include/rga2_reg_info.h -@@ -0,0 +1,477 @@ +@@ -0,0 +1,573 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __REG2_INFO_H__ +#define __REG2_INFO_H__ @@ -1895621,7 +1895684,9 @@ index 000000000..add2f41bd + +#define RGA2_SYS_REG_BASE 0x000 +#define RGA2_CSC_REG_BASE 0x060 ++#define RGA2_OTHER_REG_BASE 0x090 +#define RGA2_CMD_REG_BASE 0x100 ++#define RGA2_IOMMU_REG_BASE 0xf00 + +/* sys reg */ +#define RGA2_SYS_CTRL 0x000 @@ -1895632,6 +1895697,7 @@ index 000000000..add2f41bd +#define RGA2_MMU_CTRL0 0x014 +#define RGA2_MMU_CMD_BASE 0x018 +#define RGA2_STATUS2 0x01c ++#define RGA2_WORK_CNT 0x020 +#define RGA2_VERSION_NUM 0x028 +#define RGA2_READ_LINE_CNT 0x030 +#define RGA2_WRITE_LINE_CNT 0x034 @@ -1895652,18 +1895718,27 @@ index 000000000..add2f41bd +#define RGA2_DST_CSC_22 0x088 +#define RGA2_DST_CSC_OFF2 0x08c + ++/* back door0 */ ++#define RGA2_BACKDOOR0 0x090 ++ +/* osd read-back reg */ +#define RGA2_OSD_CUR_FLAGS0 0x090 +#define RGA2_OSD_CUR_FLAGS1 0x09c ++#define RGA2_FIXED_OSD_CUR_FLAGS0 0x440 ++#define RGA2_FIXED_OSD_CUR_FLAGS1 0x444 + +/* mode ctrl */ +#define RGA2_MODE_CTRL_OFFSET 0x000 +#define RGA2_SRC_INFO_OFFSET 0x004 +#define RGA2_SRC_BASE0_OFFSET 0x008 ++#define RGA2_FBCIN_HEAD_BASE_OFFSET 0x008 // repeat +#define RGA2_SRC_BASE1_OFFSET 0x00c ++#define RGA2_FBCIN_PAYL_BASE_OFFSET 0x00c // repeat +#define RGA2_SRC_BASE2_OFFSET 0x010 ++#define RGA2_FBCIN_OFF_OFFSET 0x010 // repeat +#define RGA2_SRC_BASE3_OFFSET 0x014 +#define RGA2_SRC_VIR_INFO_OFFSET 0x018 ++#define RGA2_FBCIN_HEAD_VIR_INFO_OFFSET 0x018 // repeat +#define RGA2_SRC_ACT_INFO_OFFSET 0x01c +#define RGA2_SRC_X_FACTOR_OFFSET 0x020 +#define RGA2_OSD_CTRL0_OFFSET 0x020 // repeat @@ -1895671,6 +1895746,7 @@ index 000000000..add2f41bd +#define RGA2_OSD_CTRL1_OFFSET 0x024 // repeat +#define RGA2_SRC_BG_COLOR_OFFSET 0x028 +#define RGA2_OSD_COLOR0_OFFSET 0x028 // repeat ++#define RGA2_GAUSS_COE_OFFSET 0x028 // repeat +#define RGA2_SRC_FG_COLOR_OFFSET 0x02c +#define RGA2_OSD_COLOR1_OFFSET 0x02c // repeat +#define RGA2_SRC_TR_COLOR0_OFFSET 0x030 @@ -1895684,6 +1895760,7 @@ index 000000000..add2f41bd +#define RGA2_DST_BASE0_OFFSET 0x03c +#define RGA2_DST_BASE1_OFFSET 0x040 +#define RGA2_DST_BASE2_OFFSET 0x044 ++#define RGA2_TILE4x4_OUT_BASE_OFFSET 0x044 //repeat +#define RGA2_DST_VIR_INFO_OFFSET 0x048 +#define RGA2_DST_ACT_INFO_OFFSET 0x04c +#define RGA2_ALPHA_CTRL0_OFFSET 0x050 @@ -1895702,14 +1895779,17 @@ index 000000000..add2f41bd +#define RGA2_OSD_INVERTSION_CAL1_OFFSET 0x064 // repeat +#define RGA2_MASK_BASE_OFFSET 0x068 +#define RGA2_MMU_CTRL1_OFFSET 0x06c ++#define RGA2_UV_VIR_INFO 0x06c // repeat +#define RGA2_MMU_SRC_BASE_OFFSET 0x070 ++#define RGA2_PREFETCH_ADDR_TH_OFFSET 0x070 // repeat +#define RGA2_MMU_SRC1_BASE_OFFSET 0x074 +#define RGA2_MMU_DST_BASE_OFFSET 0x078 +#define RGA2_MMU_ELS_BASE_OFFSET 0x07c + +/*RGA_SYS*/ -+#define m_RGA2_SYS_CTRL_SRC0YUV420SP_RD_OPT_DIS (0x1 << 12) -+#define m_RGA2_SYS_CTRL_DST_WR_OPT_DIS (0x1 << 11) ++#define m_RGA2_SYS_CTRL_SRC0YUV420SP_RD_OPT_DIS (0x1 << 12) /* moved to RGA_BACKDOOR0 since RV1126B */ ++#define m_RGA2_SYS_CTRL_DST_WR_OPT_DIS (0x1 << 11) /* moved to RGA_BACKDOOR0 since RV1126B */ ++#define m_RGA2_MASTER_CMD_BYPASS_EN (0x1 << 11) /* after RV1126B */ +#define m_RGA2_SYS_CTRL_CMD_CONTINUE_P (0x1 << 10) +#define m_RGA2_SYS_CTRL_HOLD_MODE_EN (0x1 << 9) +#define m_RGA2_SYS_CTRL_RST_HANDSAVE_P (0x1 << 7) @@ -1895731,12 +1895811,22 @@ index 000000000..add2f41bd +#define m_RGA2_CMD_CTRL_INCR_VALID_P (0x1 << 1) +#define m_RGA2_CMD_CTRL_CMD_LINE_ST_P (0x1 << 0) + ++#define s_RGA2_CMD_CTRL_INCR_NUM(x) ((x & 0x3ff) << 3) ++ +/* RGA_STATUS1 */ +#define m_RGA2_STATUS1_SW_CMD_TOTAL_NUM (0xfff << 8) +#define m_RGA2_STATUS1_SW_CMD_CUR_NUM (0xfff << 8) +#define m_RGA2_STATUS1_SW_RGA_STA (0x1 << 0) + +/*RGA_INT*/ ++#define m_RGA2_INT_FBCIN_DEC_ERROR_CLEAR (1 << 24) ++#define m_RGA2_INT_FBCIN_DEC_ERROR_EN (1 << 23) ++#define m_RGA2_INT_FBCIN_DEC_ERROR (1 << 22) ++#define m_RGA2_INT_PREFETCH_TH_INTR (1 << 21) ++#define m_RGA2_INT_PRE_TH_CLEAR (1 << 20) ++#define m_RGA2_INT_SCL_ERROR_CLEAR (1 << 19) ++#define m_RGA2_INT_SCL_ERROR_EN (1 << 18) ++#define m_RGA2_INT_SCL_ERROR_INTR (1 << 17) +#define m_RGA2_INT_LINE_WR_CLEAR (1 << 16) +#define m_RGA2_INT_LINE_RD_CLEAR (1 << 15) +#define m_RGA2_INT_LINE_WR_EN (1 << 14) @@ -1895758,17 +1895848,23 @@ index 000000000..add2f41bd +#define m_RGA2_INT_ERROR_FLAG_MASK \ + ( \ + m_RGA2_INT_MMU_INT_FLAG | \ -+ m_RGA2_INT_ERROR_INT_FLAG \ ++ m_RGA2_INT_ERROR_INT_FLAG | \ ++ m_RGA2_INT_SCL_ERROR_INTR | \ ++ m_RGA2_INT_FBCIN_DEC_ERROR \ + ) +#define m_RGA2_INT_ERROR_CLEAR_MASK \ + ( \ -+ m_RGA2_INT_MMU_INT_CLEAR | \ -+ m_RGA2_INT_ERROR_INT_CLEAR \ ++ m_RGA2_INT_MMU_INT_CLEAR | \ ++ m_RGA2_INT_ERROR_INT_CLEAR | \ ++ m_RGA2_INT_SCL_ERROR_CLEAR | \ ++ m_RGA2_INT_FBCIN_DEC_ERROR_CLEAR \ +) +#define m_RGA2_INT_ERROR_ENABLE_MASK \ + ( \ + m_RGA2_INT_MMU_INT_EN | \ -+ m_RGA2_INT_ERROR_INT_EN \ ++ m_RGA2_INT_ERROR_INT_EN | \ ++ m_RGA2_INT_SCL_ERROR_EN | \ ++ m_RGA2_INT_FBCIN_DEC_ERROR_EN \ + ) + +#define s_RGA2_INT_LINE_WR_CLEAR(x) ((x & 0x1) << 16) @@ -1895802,6 +1895898,17 @@ index 000000000..add2f41bd +#define s_RGA2_WRITE_LINE_SW_INTR_LINE_WR_START(x) ((x & 0x1fff) << 0) +#define s_RGA2_WRITE_LINE_SW_INTR_LINE_WR_STEP(x) ((x & 0x1fff) << 16) + ++/* RGA BACKDOOR0 */ ++#define m_RGA2_HSDBIL_VSP_FIX_DIS (0x1 << 0) ++#define m_RGA2_HSP_LEFT_COPY_DIS (0x1 << 1) ++#define m_RGA2_AXI_WR128_DIS (0x1 << 2) ++#define m_RGA2_TABLE_PRE_FETCH_DIS (0X1 << 3) ++#define m_RGA2_FBCIN_BSP_DIS (0X1 << 4) ++#define m_RGA2_SRC1_RGB888_FIX_DIS (0X1 << 5) ++#define m_RGA2_SRC0_YUV420SP_RD_OPT_DIS (0X1 << 6) ++#define m_RGA2_DST_WR_OPT_DIS (0X1 << 7) ++#define m_RGA2_OUTSTANDING_CFG_DIS (0X1 << 8) ++ +/* RGA_MODE_CTRL */ +#define m_RGA2_MODE_CTRL_SW_RENDER_MODE (0x7 << 0) +#define m_RGA2_MODE_CTRL_SW_BITBLT_MODE (0x1 << 3) @@ -1895812,6 +1895919,15 @@ index 000000000..add2f41bd +#define m_RGA2_MODE_CTRL_SW_OSD_E (0x1<<8) +#define m_RGA2_MODE_CTRL_SW_MOSAIC_EN (0x1<<9) +#define m_RGA2_MODE_CTRL_SW_YIN_YOUT_EN (0x1<<10) ++#define m_RGA2_MODE_CTRL_SW_TILE4x4_IN_EN (0x1 << 12) ++#define m_RGA2_MODE_CTRL_SW_TILE4x4_OUT_EN (0x1 << 13) ++#define m_RGA2_MODE_CTRL_SW_TABLE_PRE_FETCH_MODE (0x3 << 14) ++#define m_RGA2_MODE_CTRL_SW_FBC_IN_EN (0x1 << 16) ++#define m_RGA2_MODE_CTRL_SW_SRC_GAUSS_EN (0x1 << 17) ++#define m_RGA2_MODE_CTRL_SW_FBC_BSP_DIS (0x1 << 18) /* moved to RGA_BACKDOOR0 since RV1126B */ ++#define m_RGA2_MODE_CTRL_SW_TABLE_PRE_FETCH_DIS (0x1 << 19) /* moved to RGA_BACKDOOR0 since RV1126B */ ++#define m_RGA2_MODE_CTRL_SW_AXI_WR128_DIS (0x1 << 20) /* moved to RGA_BACKDOOR0 since RV1126B */ ++#define m_RGA2_MODE_CTRL_SW_HSP_LEFT_COPY_DIS (0x1 << 21) /* moved to RGA_BACKDOOR0 since RV1126B */ + +#define s_RGA2_MODE_CTRL_SW_RENDER_MODE(x) ((x & 0x7) << 0) +#define s_RGA2_MODE_CTRL_SW_BITBLT_MODE(x) ((x & 0x1) << 3) @@ -1895822,8 +1895938,20 @@ index 000000000..add2f41bd +#define s_RGA2_MODE_CTRL_SW_OSD_E(x) ((x & 0x1) << 8) +#define s_RGA2_MODE_CTRL_SW_MOSAIC_EN(x) ((x & 0x1) << 9) +#define s_RGA2_MODE_CTRL_SW_YIN_YOUT_EN(x) ((x & 0x1) << 10) ++#define s_RGA2_MODE_CTRL_SW_TILE4x4_IN_EN(x) ((x & 0x1) << 12) ++#define s_RGA2_MODE_CTRL_SW_TILE4x4_OUT_EN(x) ((x & 0x1) << 13) ++#define s_RGA2_MODE_CTRL_SW_TABLE_PRE_FETCH_MODE(x) ((x & 0x3) << 14) ++#define s_RGA2_MODE_CTRL_SW_FBC_IN_EN(x) ((x & 0x1) << 16) ++#define s_RGA2_MODE_CTRL_SW_SRC_GAUSS_EN(x) ((x & 0x1) << 17) ++#define s_RGA2_MODE_CTRL_SW_FBC_BSP_DIS(x) ((x & 0x1) << 18) ++#define s_RGA2_MODE_CTRL_SW_TABLE_PRE_FETCH_DIS(x) ((x & 0x1) << 19) ++#define s_RGA2_MODE_CTRL_SW_AXI_WR128_DIS(x) ((x & 0x1) << 20) ++#define s_RGA2_MODE_CTRL_SW_HSP_LEFT_COPY_DIS(x) ((x & 0x1) << 21) ++ +/* RGA_SRC_INFO */ +#define m_RGA2_SRC_INFO_SW_SRC_FMT (0xf << 0) ++#define m_RGA2_SRC_INFO_SW_FBCIN_MODE (0x3 << 0) // repeat ++#define m_RGA2_SRC_INFO_SW_FBCIN_FMT (0x3 << 2) // repeat +#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) @@ -1895840,9 +1895968,14 @@ index 000000000..add2f41bd +#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 m_RGA2_SRC_INFO_SW_SW_VSD_MODE_SEL (0x1 << 29) ++#define m_RGA2_SRC_INFO_SW_SW_HSP_MODE_SEL (0x1 << 30) ++#define m_RGA2_SRC_INFO_SW_SW_HSD_MODE_SEL (0x1 << 31) + + +#define s_RGA2_SRC_INFO_SW_SRC_FMT(x) ((x & 0xf) << 0) ++#define s_RGA2_SRC_INFO_SW_FBCIN_MODE(x) ((x & 0x3) << 0) // repeat ++#define s_RGA2_SRC_INFO_SW_FBCIN_FMT(x) ((x & 0x3) << 2) // repeat +#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) @@ -1895860,6 +1895993,9 @@ index 000000000..add2f41bd +#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) ++#define s_RGA2_SRC_INFO_SW_SW_VSD_MODE_SEL(x) ((x & 0x1) << 29) ++#define s_RGA2_SRC_INFO_SW_SW_HSP_MODE_SEL(x) ((x & 0x1) << 30) ++#define s_RGA2_SRC_INFO_SW_SW_HSD_MODE_SEL(x) ((x & 0x1) << 31) + +/* RGA_SRC_VIR_INFO */ +#define m_RGA2_SRC_VIR_INFO_SW_SRC_VIR_STRIDE (0x7fff << 0) @@ -1895870,11 +1896006,15 @@ index 000000000..add2f41bd + + +/* 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 m_RGA2_SRC_ACT_INFO_SW_TILE4X4_IN_YOFF (0x3 << 30) ++#define m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT (0x7ff << 16) ++#define m_RGA2_SRC_ACT_INFO_SW_TILE4X4_IN_XOFF (0x3 << 14) ++#define m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH (0x7ff << 0) + -+#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) ++#define s_RGA2_SRC_ACT_INFO_SW_TILE4X4_IN_YOFF(x) ((x & 0x3) << 30) ++#define s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT(x) ((x & 0x7ff) << 16) ++#define s_RGA2_SRC_ACT_INFO_SW_TILE4X4_IN_XOFF(x) ((x & 0x3) << 14) ++#define s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH(x) ((x & 0x7ff) << 0) + +/* RGA2_OSD_CTRL0 */ +#define m_RGA2_OSD_CTRL0_SW_OSD_MODE (0x3 << 0) @@ -1895893,6 +1896033,15 @@ index 000000000..add2f41bd +#define s_RGA2_OSD_CTRL0_SW_OSD_FIX_WIDTH(x) ((x & 0x3ff) << 20) +#define s_RGA2_OSD_CTRL0_SW_OSD_2BPP_MODE(x) ((x & 0x1) << 30) + ++/* RGA2_GAUSS_COE */ ++#define m_RGA2_GAUSS_COE_SW_COE0 (0x3f << 0) ++#define m_RGA2_GAUSS_COE_SW_COE1 (0x3f << 8) ++#define m_RGA2_GAUSS_COE_SW_COE2 (0xff << 16) ++ ++#define s_RGA2_GAUSS_COE_SW_COE0(x) ((x & 0x3f) << 0) ++#define s_RGA2_GAUSS_COE_SW_COE1(x) ((x & 0x3f) << 8) ++#define s_RGA2_GAUSS_COE_SW_COE2(x) ((x & 0xff) << 16) ++ +/* RGA2_OSD_CTRL1 */ +#define m_RGA2_OSD_CTRL1_SW_OSD_COLOR_SEL (0x1 << 0) +#define m_RGA2_OSD_CTRL1_SW_OSD_FLAG_SEL (0x1 << 1) @@ -1895935,6 +1896084,7 @@ index 000000000..add2f41bd +#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_DST_UVVDS_MODE (0x1 << 27) ++#define m_RGA2_DST_INFO_SW_SRC1_A1555_ACONFIG_EN (0x1 << 28) + +#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) @@ -1895956,7 +1896106,7 @@ index 000000000..add2f41bd +#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_DST_UVVDS_MODE(x) ((x & 0x1) << 27) -+ ++#define s_RGA2_DST_INFO_SW_SRC1_A1555_ACONFIG_EN(x) ((x & 0x1) << 28) + +/* RGA_ALPHA_CTRL0 */ +#define m_RGA2_ALPHA_CTRL0_SW_ALPHA_ROP_0 (0x1 << 0) @@ -1896048,6 +1896198,15 @@ index 000000000..add2f41bd +#define s_RGA2_MMU_CTRL1_SW_ELS_MMU_FLUSH(x) ((x & 0x1) << 13) + +#define RGA2_VSP_BICUBIC_LIMIT 1996 ++#define RGA2_BILINEAR_PREC 12 ++ ++#define RGA2_IOMMU_PREFETCH_SHIFT 16 ++#define RGA2_IOMMU_PREFETCH_MASK 0xffff ++#define RGA2_IOMMU_PREFETCH_ALIGN(x) \ ++ (((x) + RGA2_IOMMU_PREFETCH_MASK) & ~RGA2_IOMMU_PREFETCH_MASK) ++#define RGA2_IOMMU_PREFETCH_ALIGN_DOWN(x) ((x) & ~RGA2_IOMMU_PREFETCH_MASK) ++#define RGA2_IOMMU_PREFETCH_THRESHOLD_MIN (0x1U << RGA2_IOMMU_PREFETCH_SHIFT) ++#define RGA2_IOMMU_PREFETCH_THRESHOLD_MAX (0xffffU << RGA2_IOMMU_PREFETCH_SHIFT) + +union rga2_color_ctrl { + uint32_t value; @@ -1896092,16 +1896251,19 @@ index 000000000..add2f41bd + diff --git a/drivers/video/rockchip/rga3/include/rga3_reg_info.h b/drivers/video/rockchip/rga3/include/rga3_reg_info.h new file mode 100644 -index 000000000..4db80cfb0 +index 000000000..1f9d66a50 --- /dev/null +++ b/drivers/video/rockchip/rga3/include/rga3_reg_info.h -@@ -0,0 +1,521 @@ +@@ -0,0 +1,524 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __REG3_INFO_H__ +#define __REG3_INFO_H__ + +#include "rga_drv.h" + ++#define RGA3_SYS_REG_BASE 0x000 ++#define RGA3_CMD_REG_BASE 0x100 ++ +/* sys reg */ +#define RGA3_SYS_CTRL 0x000 +#define RGA3_CMD_CTRL 0x004 @@ -1896619,10 +1896781,10 @@ index 000000000..4db80cfb0 + diff --git a/drivers/video/rockchip/rga3/include/rga_common.h b/drivers/video/rockchip/rga3/include/rga_common.h new file mode 100644 -index 000000000..32e83cc9c +index 000000000..4ed75821f --- /dev/null +++ b/drivers/video/rockchip/rga3/include/rga_common.h -@@ -0,0 +1,49 @@ +@@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1896637,6 +1896799,39 @@ index 000000000..32e83cc9c +#include "rga_drv.h" +#include "rga_hw_config.h" + ++#ifdef pr_fmt ++#undef pr_fmt ++#endif ++ ++#define pr_fmt(fmt) "%s: " fmt, "rga" ++ ++#define rga_log(fmt, args...) \ ++ pr_info("%-6d %-6d: " fmt, get_current()->tgid, get_current()->pid, ##args) ++#define rga_err(fmt, args...) \ ++ pr_err("%-6d %-6d: " fmt, get_current()->tgid, get_current()->pid, ##args) ++ ++#define rga_dev_log(dev, fmt, args...) \ ++ dev_info(dev, "%-6d %-6d: " fmt, current->tgid, current->pid, ##args) ++#define rga_dev_err(dev, fmt, args...) \ ++ dev_err(dev, "%-6d %-6d: " fmt, current->tgid, current->pid, ##args) ++ ++#define rga_job_log(job, fmt, args...) \ ++ pr_info("%-6d %-6d: ID[%d]: " fmt, job->session->tgid, job->pid, job->request_id, ##args) ++#define rga_job_err(job, fmt, args...) \ ++ pr_err("%-6d %-6d: ID[%d]: " fmt, job->session->tgid, job->pid, job->request_id, ##args) ++ ++#define rga_req_log(request, fmt, args...) \ ++ pr_info("%-6d %-6d: ID[%d]: " fmt, \ ++ request->session->tgid, request->pid, request->id, ##args) ++#define rga_req_err(request, fmt, args...) \ ++ pr_err("%-6d %-6d: ID[%d]: " fmt, request->session->tgid, request->pid, request->id, ##args) ++ ++#define rga_buf_log(buf, fmt, args...) \ ++ pr_info("%-6d %-6d: handle[%d]: " fmt, \ ++ buf->session->tgid, current->pid, buf->handle, ##args) ++#define rga_buf_err(buf, fmt, args...) \ ++ pr_err("%-6d %-6d: handle[%d]: " fmt, buf->session->tgid, current->pid, buf->handle, ##args) ++ +#define RGA_GET_PAGE_COUNT(size) (((size) >> PAGE_SHIFT) + (((size) & (~PAGE_MASK)) ? 1 : 0)) + +bool rga_is_rgb_format(uint32_t format); @@ -1896658,10 +1896853,13 @@ index 000000000..32e83cc9c + +const char *rga_get_format_name(uint32_t format); +const char *rga_get_render_mode_str(uint8_t mode); ++const char *rga_get_store_mode_str(uint32_t mode); ++const char *rga_get_interp_str(uint8_t interp); +const char *rga_get_rotate_mode_str(uint8_t mode); +const char *rga_get_blend_mode_str(enum rga_alpha_blend_mode mode); +const char *rga_get_memory_type_str(uint8_t type); +const char *rga_get_mmu_type_str(enum rga_mmu mmu_type); ++const char *rga_get_dma_data_direction_str(enum dma_data_direction dir); +const char *rga_get_core_name(enum RGA_SCHEDULER_CORE core); + +void rga_convert_addr(struct rga_img_info_t *img, bool before_vir_get_channel); @@ -1896670,11 +1896868,14 @@ index 000000000..32e83cc9c + int *yrgb_size, int *uv_size, int *v_size); +void rga_dump_memory_parm(struct rga_memory_parm *parm); +void rga_dump_external_buffer(struct rga_external_buffer *buffer); ++void rga_dump_req(struct rga_request *request, struct rga_req *req); ++ ++unsigned long rga_get_free_pages(gfp_t gfp_mask, unsigned int *order, unsigned long size); + +#endif diff --git a/drivers/video/rockchip/rga3/include/rga_debugger.h b/drivers/video/rockchip/rga3/include/rga_debugger.h new file mode 100644 -index 000000000..c274fe87f +index 000000000..cc2966ec5 --- /dev/null +++ b/drivers/video/rockchip/rga3/include/rga_debugger.h @@ -0,0 +1,145 @@ @@ -1896700,6 +1896901,7 @@ index 000000000..c274fe87f +extern int RGA_DEBUG_INT_FLAG; +extern int RGA_DEBUG_MM; +extern int RGA_DEBUG_CHECK_MODE; ++extern int RGA_DEBUG_INTERNAL_MODE; +extern int RGA_DEBUG_NONUSE; +extern int RGA_DEBUG_DUMP_IMAGE; + @@ -1896811,7 +1897013,6 @@ index 000000000..c274fe87f + +#endif /* #ifdef CONFIG_ROCKCHIP_RGA_DEBUGGER */ + -+void rga_cmd_print_debug_info(struct rga_req *req); +void rga_request_task_debug_info(struct seq_file *m, struct rga_req *req); +#ifdef CONFIG_NO_GKI +void rga_dump_job_image(struct rga_job *dump_job); @@ -1896825,10 +1897026,10 @@ index 000000000..c274fe87f + diff --git a/drivers/video/rockchip/rga3/include/rga_dma_buf.h b/drivers/video/rockchip/rga3/include/rga_dma_buf.h new file mode 100644 -index 000000000..2ff0857a6 +index 000000000..05a801c07 --- /dev/null +++ b/drivers/video/rockchip/rga3/include/rga_dma_buf.h -@@ -0,0 +1,46 @@ +@@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1896857,30 +1897058,33 @@ index 000000000..2ff0857a6 +int rga_virtual_memory_check(void *vaddr, u32 w, u32 h, u32 format, int fd); +int rga_dma_memory_check(struct rga_dma_buffer *rga_dma_buffer, struct rga_img_info_t *img); + -+int rga_iommu_map_sgt(struct sg_table *sgt, size_t size, -+ struct rga_dma_buffer *buffer, -+ struct device *rga_dev); -+int rga_iommu_map(phys_addr_t paddr, size_t size, -+ struct rga_dma_buffer *buffer, -+ struct device *rga_dev); -+void rga_iommu_unmap(struct rga_dma_buffer *buffer); ++int rga_dma_map_phys_addr(phys_addr_t phys_addr, size_t size, struct rga_dma_buffer *buffer, ++ enum dma_data_direction dir, struct device *map_dev); ++void rga_dma_unmap_phys_addr(struct rga_dma_buffer *buffer); ++ ++int rga_dma_map_sgt(struct sg_table *sgt, struct rga_dma_buffer *buffer, ++ enum dma_data_direction dir, struct device *map_dev); ++void rga_dma_unmap_sgt(struct rga_dma_buffer *buffer); + +int rga_dma_map_buf(struct dma_buf *dma_buf, struct rga_dma_buffer *rga_dma_buffer, -+ enum dma_data_direction dir, struct device *rga_dev); ++ enum dma_data_direction dir, struct device *map_dev); +int rga_dma_map_fd(int fd, struct rga_dma_buffer *rga_dma_buffer, -+ enum dma_data_direction dir, struct device *rga_dev); ++ enum dma_data_direction dir, struct device *map_dev); +void rga_dma_unmap_buf(struct rga_dma_buffer *rga_dma_buffer); + +void rga_dma_sync_flush_range(void *pstart, void *pend, struct rga_scheduler_t *scheduler); + ++struct rga_dma_buffer *rga_dma_alloc_coherent(struct rga_scheduler_t *scheduler, int size); ++int rga_dma_free(struct rga_dma_buffer *buffer); ++ +#endif /* #ifndef __RGA3_DMA_BUF_H__ */ + diff --git a/drivers/video/rockchip/rga3/include/rga_drv.h b/drivers/video/rockchip/rga3/include/rga_drv.h new file mode 100644 -index 000000000..e9743a403 +index 000000000..181dbe07a --- /dev/null +++ b/drivers/video/rockchip/rga3/include/rga_drv.h -@@ -0,0 +1,463 @@ +@@ -0,0 +1,499 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1896952,6 +1897156,7 @@ index 000000000..e9743a403 + +/* load interval: 1000ms */ +#define RGA_LOAD_INTERVAL_US 1000000 ++#define RGA_LOAD_ACTIVE_MAX_US 5000000 + +/* timer interval: 1000ms */ +#define RGA_TIMER_INTERVAL_NS 1000000000 @@ -1896970,8 +1897175,8 @@ index 000000000..e9743a403 + +#define DRIVER_MAJOR_VERISON 1 +#define DRIVER_MINOR_VERSION 3 -+#define DRIVER_REVISION_VERSION 1 -+#define DRIVER_PATCH_VERSION ++#define DRIVER_REVISION_VERSION 9 ++#define DRIVER_PATCH_VERSION g_i + +#define DRIVER_VERSION (STR(DRIVER_MAJOR_VERISON) "." STR(DRIVER_MINOR_VERSION) \ + "." STR(DRIVER_REVISION_VERSION) STR(DRIVER_PATCH_VERSION)) @@ -1896997,14 +1897202,6 @@ index 000000000..e9743a403 +extern struct rga_drvdata_t *rga_drvdata; + +enum { -+ RGA3_SCHEDULER_CORE0 = 1 << 0, -+ RGA3_SCHEDULER_CORE1 = 1 << 1, -+ RGA2_SCHEDULER_CORE0 = 1 << 2, -+ RGA_CORE_MASK = 0x7, -+ RGA_NONE_CORE = 0x0, -+}; -+ -+enum { + RGA_CMD_SLAVE = 1, + RGA_CMD_MASTER = 2, +}; @@ -1897031,6 +1897228,12 @@ index 000000000..e9743a403 + RGA_JOB_STATE_ABORT, +}; + ++enum RGA_DEVICE_TYPE { ++ RGA_DEVICE_RGA2 = 0, ++ RGA_DEVICE_RGA3, ++ RGA_DEVICE_BUTT, ++}; ++ +struct rga_iommu_dma_cookie { + enum iommu_dma_cookie_type type; + @@ -1897050,13 +1897253,14 @@ index 000000000..e9743a403 + struct dma_buf *dma_buf; + struct dma_buf_attachment *attach; + struct sg_table *sgt; -+ void *vmap_ptr; ++ void *vaddr; + + struct iommu_domain *domain; + + enum dma_data_direction dir; + + dma_addr_t iova; ++ dma_addr_t dma_addr; + unsigned long size; + /* + * The offset of the first page of the sgt. @@ -1897065,8 +1897269,11 @@ index 000000000..e9743a403 + */ + size_t offset; + -+ /* The scheduler of the mapping */ -+ struct rga_scheduler_t *scheduler; ++ /* ++ * The device used by dma-buf mapping, which usually corresponds to the ++ * default domain or the current device. ++ */ ++ struct device *map_dev; +}; + +struct rga_virt_addr { @@ -1897075,6 +1897282,7 @@ index 000000000..e9743a403 + struct page **pages; + int pages_order; + int page_count; ++ /* Actual effective size */ + unsigned long size; + + /* The offset of the first page of the virtual address */ @@ -1897110,6 +1897318,9 @@ index 000000000..e9743a403 + + struct kref refcount; + struct rga_session *session; ++ ++ /* The scheduler of the mapping */ ++ struct rga_scheduler_t *scheduler; +}; + +struct rga_scheduler_t; @@ -1897120,6 +1897331,12 @@ index 000000000..e9743a403 + pid_t tgid; + + char *pname; ++ ++ ktime_t last_active; ++ ++ bool release; ++ struct rw_semaphore release_rwsem; ++ struct kref refcount; +}; + +struct rga_job_buffer { @@ -1897146,6 +1897363,17 @@ index 000000000..e9743a403 + int page_count; +}; + ++struct rga_job_timestamp { ++ ktime_t init; ++ ktime_t insert; ++ ktime_t hw_execute; ++ ktime_t hw_done; ++ ktime_t done; ++ ++ /* The time only for hrtimer to calculate the load */ ++ ktime_t hw_recode; ++}; ++ +struct rga_job { + struct list_head head; + @@ -1897153,7 +1897381,7 @@ index 000000000..e9743a403 + struct rga_session *session; + + struct rga_req rga_command_base; -+ uint32_t cmd_reg[32 * 8]; ++ struct rga_dma_buffer *cmd_buf; + struct rga_full_csc full_csc; + struct rga_csc_clip full_csc_clip; + struct rga_pre_intr_info pre_intr_info; @@ -1897168,11 +1897396,8 @@ index 000000000..e9743a403 + struct mm_struct *mm; + + /* job time stamp */ -+ ktime_t timestamp; -+ /* The time when the job is actually executed on the hardware */ -+ ktime_t hw_running_time; -+ /* The time only for hrtimer to calculate the load */ -+ ktime_t hw_recoder_time; ++ struct rga_job_timestamp timestamp; ++ + unsigned int flags; + int request_id; + int priority; @@ -1897186,6 +1897411,8 @@ index 000000000..e9743a403 + uint32_t intr_status; + uint32_t hw_status; + uint32_t cmd_status; ++ ++ uint32_t work_cycle; +}; + +struct rga_backend_ops { @@ -1897194,6 +1897421,7 @@ index 000000000..e9743a403 + int (*init_reg)(struct rga_job *job); + void (*soft_reset)(struct rga_scheduler_t *scheduler); + int (*read_back_reg)(struct rga_job *job, struct rga_scheduler_t *scheduler); ++ int (*read_status)(struct rga_job *job, struct rga_scheduler_t *scheduler); + int (*irq)(struct rga_scheduler_t *scheduler); + int (*isr_thread)(struct rga_job *job, struct rga_scheduler_t *scheduler); +}; @@ -1897208,7 +1897436,7 @@ index 000000000..e9743a403 + void __iomem *rga_base; + struct rga_iommu_info *iommu_info; + -+ struct clk *clks[RGA_MAX_BUS_CLK]; ++ struct clk_bulk_data *clks; + int num_clks; + + enum rga_scheduler_status status; @@ -1897218,8 +1897446,11 @@ index 000000000..e9743a403 + 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; ++ unsigned long hw_issues_mask; ++ + int job_count; + int irq; + struct rga_version_t version; @@ -1897244,6 +1897475,7 @@ index 000000000..e9743a403 + int32_t release_fence_fd; + struct dma_fence *release_fence; + spinlock_t fence_lock; ++ struct work_struct fence_work; + + wait_queue_head_t finished_wq; + @@ -1897295,6 +1897527,7 @@ index 000000000..e9743a403 + + struct rga_scheduler_t *scheduler[RGA_MAX_SCHEDULER]; + int num_of_scheduler; ++ int device_count[RGA_DEVICE_BUTT]; + /* The scheduler_index used by default for memory mapping. */ + int map_scheduler_index; + struct rga_mmu_base *mmu_base; @@ -1897315,6 +1897548,9 @@ index 000000000..e9743a403 +#ifdef CONFIG_ROCKCHIP_RGA_DEBUGGER + struct rga_debugger *debugger; +#endif ++ ++ bool shutdown; ++ struct rw_semaphore rwsem; +}; + +struct rga_irqs_data_t { @@ -1897324,8 +1897560,9 @@ index 000000000..e9743a403 +}; + +struct rga_match_data_t { -+ const char * const *clks; -+ int num_clks; ++ enum RGA_DEVICE_TYPE device_type; ++ ++ const struct rga_backend_ops *ops; +}; + +static inline int rga_read(int offset, struct rga_scheduler_t *scheduler) @@ -1897341,12 +1897578,15 @@ index 000000000..e9743a403 +int rga_power_enable(struct rga_scheduler_t *scheduler); +int rga_power_disable(struct rga_scheduler_t *scheduler); + ++int rga_session_put(struct rga_session *session); ++void rga_session_get(struct rga_session *session); ++ +int rga_kernel_commit(struct rga_req *cmd); + +#endif /* __LINUX_RGA_FENCE_H_ */ diff --git a/drivers/video/rockchip/rga3/include/rga_fence.h b/drivers/video/rockchip/rga3/include/rga_fence.h new file mode 100644 -index 000000000..7e3bbeebb +index 000000000..75c7c2292 --- /dev/null +++ b/drivers/video/rockchip/rga3/include/rga_fence.h @@ -0,0 +1,101 @@ @@ -1897410,12 +1897650,12 @@ index 000000000..7e3bbeebb +#else +static inline struct dma_fence *rga_dma_fence_alloc(void) +{ -+ return NULL; ++ return ERR_PTR(-EINVAL); +} + +static inline int rga_dma_fence_get_fd(struct dma_fence *fence) +{ -+ return 0; ++ return -1; +} + +static inline struct dma_fence *rga_get_dma_fence_from_fd(int fence_fd) @@ -1897432,7 +1897672,7 @@ index 000000000..7e3bbeebb + dma_fence_func_t func, + void *private) +{ -+ return 0; ++ return -EINVAL; +} + +static inline void rga_dma_fence_put(struct dma_fence *fence) @@ -1897445,7 +1897685,7 @@ index 000000000..7e3bbeebb + +static inline int rga_dma_fence_get_status(struct dma_fence *fence) +{ -+ return 0; ++ return -EINVAL; +} + +#endif /* #ifdef CONFIG_SYNC_FILE */ @@ -1897453,10 +1897693,10 @@ index 000000000..7e3bbeebb +#endif /* __LINUX_RGA_FENCE_H_ */ diff --git a/drivers/video/rockchip/rga3/include/rga_hw_config.h b/drivers/video/rockchip/rga3/include/rga_hw_config.h new file mode 100644 -index 000000000..46f7531aa +index 000000000..34f48e004 --- /dev/null +++ b/drivers/video/rockchip/rga3/include/rga_hw_config.h -@@ -0,0 +1,81 @@ +@@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1897479,9 +1897719,16 @@ index 000000000..46f7531aa + RGA_RASTER_INDEX, + RGA_AFBC16x16_INDEX, + RGA_TILE8x8_INDEX, ++ RGA_TILE4x4_INDEX, ++ RGA_RKFBC64x4_INDEX, ++ RGA_AFBC32x8_INDEX, + RGA_FORMAT_INDEX_BUTT, +}; + ++enum rga_hw_issue { ++ RGA_HW_ISSUE_DIS_AUTO_RST, ++}; ++ +struct rga_win_data { + const char *name; + const uint32_t *formats[RGA_FORMAT_INDEX_BUTT]; @@ -1897528,7 +1897775,14 @@ index 000000000..46f7531aa +extern const struct rga_hw_data rga3_data; +extern const struct rga_hw_data rga2e_data; +extern const struct rga_hw_data rga2e_1106_data; ++extern const struct rga_hw_data rga2e_3506_data; +extern const struct rga_hw_data rga2e_iommu_data; ++extern const struct rga_hw_data rga2p_iommu_data; ++extern const struct rga_hw_data rga2p_lite_1103b_data; ++extern const struct rga_hw_data rga2p_iommu_non_fbc_data; ++ ++#define rga_hw_has_issue(scheduler, issue) test_bit(issue, &((scheduler)->hw_issues_mask)) ++#define rga_hw_set_issue_mask(scheduler, issue) set_bit(issue, &((scheduler)->hw_issues_mask)) + +/* Returns false if in range, true otherwise */ +static inline bool rga_hw_out_of_range(const struct rga_rect_range *range, int width, int height) @@ -1897625,10 +1897879,10 @@ index 000000000..b80a1f48b + diff --git a/drivers/video/rockchip/rga3/include/rga_job.h b/drivers/video/rockchip/rga3/include/rga_job.h new file mode 100644 -index 000000000..0fc776173 +index 000000000..28bf35bac --- /dev/null +++ b/drivers/video/rockchip/rga3/include/rga_job.h -@@ -0,0 +1,53 @@ +@@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1897644,18 +1897898,21 @@ index 000000000..0fc776173 + +#include "rga_drv.h" + ++#define RGA_CMD_REG_SIZE 256 /* 32 * 8 bit */ ++ +enum job_flags { + RGA_JOB_DONE = 1 << 0, + RGA_JOB_ASYNC = 1 << 1, + RGA_JOB_SYNC = 1 << 2, + RGA_JOB_USE_HANDLE = 1 << 3, + RGA_JOB_UNSUPPORT_RGA_MMU = 1 << 4, ++ RGA_JOB_DEBUG_FAKE_BUFFER = 1 << 5, +}; + +void rga_job_scheduler_dump_info(struct rga_scheduler_t *scheduler); +void rga_job_next(struct rga_scheduler_t *scheduler); +struct rga_job *rga_job_done(struct rga_scheduler_t *scheduler); -+struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request); ++int rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request); +int rga_job_mpi_commit(struct rga_req *rga_command_base, struct rga_request *request); + +int rga_job_assign(struct rga_job *job); @@ -1897666,6 +1897923,8 @@ index 000000000..0fc776173 + uint32_t id); + +int rga_request_commit(struct rga_request *user_request); ++void rga_request_scheduler_shutdown(struct rga_scheduler_t *scheduler); ++void rga_request_scheduler_abort(struct rga_scheduler_t *scheduler); +void rga_request_session_destroy_abort(struct rga_session *session); +int rga_request_put(struct rga_request *request); +void rga_request_get(struct rga_request *request); @@ -1897684,7 +1897943,7 @@ index 000000000..0fc776173 +#endif /* __LINUX_RKRGA_JOB_H_ */ diff --git a/drivers/video/rockchip/rga3/include/rga_mm.h b/drivers/video/rockchip/rga3/include/rga_mm.h new file mode 100644 -index 000000000..d68fd75dc +index 000000000..a75f2470b --- /dev/null +++ b/drivers/video/rockchip/rga3/include/rga_mm.h @@ -0,0 +1,67 @@ @@ -1897732,7 +1897991,7 @@ index 000000000..d68fd75dc + if (buffer == NULL) + return true; + -+ return buffer->scheduler == NULL ? true : false; ++ return buffer->map_dev == NULL ? true : false; +} + +struct rga_internal_buffer *rga_mm_lookup_handle(struct rga_mm *mm_session, uint32_t handle); @@ -1897757,10 +1898016,10 @@ index 000000000..d68fd75dc +#endif diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c new file mode 100644 -index 000000000..d2e379fa9 +index 000000000..9574318b5 --- /dev/null +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c -@@ -0,0 +1,2744 @@ +@@ -0,0 +1,3383 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1897768,8 +1898027,6 @@ index 000000000..d2e379fa9 + * Author: Huang Lee + */ + -+#define pr_fmt(fmt) "rga2_reg: " fmt -+ +#include "rga2_reg_info.h" +#include "rga_dma_buf.h" +#include "rga_iommu.h" @@ -1897777,6 +1898034,13 @@ index 000000000..d2e379fa9 +#include "rga_hw_config.h" +#include "rga_debugger.h" + ++enum rga2_scale_mode_reg { ++ RGA2_SCALE_BYPASS = 0x0, ++ RGA2_SCALE_DOWN = 0x1, ++ RGA2_SCALE_UP = 0x2, ++ RGA2_SCALE_FORCE_TILE = 0x3, ++}; ++ +unsigned int rga2_rop_code[256] = { + 0x00000007, 0x00000451, 0x00006051, 0x00800051, + 0x00007041, 0x00800041, 0x00804830, 0x000004f0,//0 @@ -1897859,16 +1898123,68 @@ index 000000000..d2e379fa9 + 0x00000051, 0x008004d4, 0x00800451, 0x00800007,//f +}; + ++static void rga2_scale_down_bilinear_protect(u32 *param_fix, u32 *src_fix, ++ u32 param, u32 offset, u32 src, u32 dst) ++{ ++ int final_coor, final_diff, final_steps; ++ ++ while (1) { ++ final_coor = offset + param * (dst - 1); ++ final_diff = (src - 1) * (1 << RGA2_BILINEAR_PREC) - final_coor; ++ ++ /* ++ * The hardware requires that the last point of the dst map on ++ * src must not exceed the range of src. ++ */ ++ if (final_diff <= 0) ++ param = param - 1; ++ else ++ break; ++ } ++ ++ /* ++ * The hardware requires that the last point of dst mapping on ++ * src be between the last two points of each row/column, so ++ * actual width/height needs to be modified. ++ */ ++ final_steps = (final_coor & ((1 << RGA2_BILINEAR_PREC) - 1)) ? ++ ((final_coor >> RGA2_BILINEAR_PREC) + 1) : ++ (final_coor >> RGA2_BILINEAR_PREC); ++ ++ *param_fix = param; ++ *src_fix = final_steps + 1; ++} ++ ++static void rag2_scale_down_average_protect(u32 *param_fix, u32 param, ++ u32 src, u32 dst) ++{ ++ /* division Loss */ ++ param = param + 1; ++ ++ /* ++ * Ensure that the (src - 1) drop point is to the left of the last ++ * point of the dst. ++ */ ++ while ((param * (src - 1)) > (dst << 16)) ++ param--; ++ ++ *param_fix = param; ++} ++ +static void RGA2_reg_get_param(unsigned char *base, struct rga2_req *msg) +{ + u32 *bRGA_SRC_X_FACTOR; + u32 *bRGA_SRC_Y_FACTOR; ++ u32 *bRGA_SRC_ACT_INFO; + u32 sw, sh; + u32 dw, dh; + u32 param_x, param_y; ++ u32 scale_x_offset, scale_y_offset; ++ u32 src_fix, param_fix; + + bRGA_SRC_X_FACTOR = (u32 *) (base + RGA2_SRC_X_FACTOR_OFFSET); + bRGA_SRC_Y_FACTOR = (u32 *) (base + RGA2_SRC_Y_FACTOR_OFFSET); ++ bRGA_SRC_ACT_INFO = (u32 *) (base + RGA2_SRC_ACT_INFO_OFFSET); + + if (((msg->rotate_mode & 0x3) == 1) || + ((msg->rotate_mode & 0x3) == 3)) { @@ -1897883,12 +1898199,32 @@ index 000000000..d2e379fa9 + 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); ++ if (msg->interp.horiz == RGA_INTERP_LINEAR) { ++ /* default to half_pixel mode. */ ++ param_x = (sw << RGA2_BILINEAR_PREC) / dw; ++ scale_x_offset = (1 << RGA2_BILINEAR_PREC) >> 1; ++ ++ rga2_scale_down_bilinear_protect(¶m_fix, &src_fix, ++ param_x, scale_x_offset, sw, dw); ++ if (DEBUGGER_EN(MSG)) { ++ if (param_x != param_fix) ++ rga_log("scale: Bi-linear horiz factor %#x fix to %#x\n", ++ param_x, param_fix); ++ if (sw != src_fix) ++ rga_log("scale: Bi-linear src_width %d -> %d\n", ++ sw, src_fix); ++ } ++ ++ *bRGA_SRC_X_FACTOR = ((param_fix & 0xffff) | ((scale_x_offset) << 16)); ++ *bRGA_SRC_ACT_INFO = ++ ((*bRGA_SRC_ACT_INFO & (~m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH)) | ++ s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH((src_fix - 1))); ++ } else { ++ param_x = (dw << 16) / sw; ++ rag2_scale_down_average_protect(¶m_x, param_x, sw, dw); ++ ++ *bRGA_SRC_X_FACTOR |= ((param_x & 0xffff) << 0); ++ } + } else if (sw < dw) { +#if SCALE_UP_LARGE + param_x = ((sw - 1) << 16) / (dw - 1); @@ -1897901,12 +1898237,32 @@ index 000000000..d2e379fa9 + } + + 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); ++ if (msg->interp.verti == RGA_INTERP_LINEAR) { ++ /* default to half_pixel mode. */ ++ param_y = (sh << RGA2_BILINEAR_PREC) / dh; ++ scale_y_offset = (1 << RGA2_BILINEAR_PREC) >> 1; ++ ++ rga2_scale_down_bilinear_protect(¶m_fix, &src_fix, ++ param_y, scale_y_offset, sh, dh); ++ if (DEBUGGER_EN(MSG)) { ++ if (param_y != param_fix) ++ rga_log("scale: Bi-linear verti factor %#x fix to %#x\n", ++ param_y, param_fix); ++ if (sh != src_fix) ++ rga_log("scale: Bi-linear src_height %d fix to %d\n", ++ sh, src_fix); ++ } ++ ++ *bRGA_SRC_Y_FACTOR = ((param_fix & 0xffff) | ((scale_y_offset) << 16)); ++ *bRGA_SRC_ACT_INFO = ++ ((*bRGA_SRC_ACT_INFO & (~m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT)) | ++ s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT((src_fix - 1))); ++ } else { ++ param_y = (dh << 16) / sh; ++ rag2_scale_down_average_protect(¶m_y, param_y, sh, dh); ++ ++ *bRGA_SRC_Y_FACTOR |= ((param_y & 0xffff) << 0); ++ } + } else if (sh < dh) { +#if SCALE_UP_LARGE + param_y = ((sh - 1) << 16) / (dh - 1); @@ -1897955,9 +1898311,28 @@ index 000000000..d2e379fa9 + reg = ((reg & (~m_RGA2_MODE_CTRL_SW_YIN_YOUT_EN)) | + (s_RGA2_MODE_CTRL_SW_YIN_YOUT_EN(msg->yin_yout_en))); + ++ if (msg->src.rd_mode == RGA_TILE4x4_MODE) ++ reg = ((reg & (~m_RGA2_MODE_CTRL_SW_TILE4x4_IN_EN)) | ++ (s_RGA2_MODE_CTRL_SW_TILE4x4_IN_EN(1))); ++ ++ if (msg->dst.rd_mode == RGA_TILE4x4_MODE) ++ reg = ((reg & (~m_RGA2_MODE_CTRL_SW_TILE4x4_OUT_EN)) | ++ (s_RGA2_MODE_CTRL_SW_TILE4x4_OUT_EN(1))); ++ ++ reg = ((reg & (~m_RGA2_MODE_CTRL_SW_TABLE_PRE_FETCH_MODE)) | ++ (s_RGA2_MODE_CTRL_SW_TABLE_PRE_FETCH_MODE(0))); /* 128k */ ++ ++ if (msg->src.rd_mode == RGA_RKFBC_MODE || msg->src.rd_mode == RGA_AFBC32x8_MODE) ++ reg = ((reg & (~m_RGA2_MODE_CTRL_SW_FBC_IN_EN)) | ++ (s_RGA2_MODE_CTRL_SW_FBC_IN_EN(1))); ++ + reg = ((reg & (~m_RGA2_MODE_CTRL_SW_OSD_E)) | + (s_RGA2_MODE_CTRL_SW_OSD_E(msg->osd_info.enable))); + ++ if (msg->gauss_config.size > 0) ++ reg = ((reg & (~m_RGA2_MODE_CTRL_SW_SRC_GAUSS_EN)) | ++ (s_RGA2_MODE_CTRL_SW_SRC_GAUSS_EN(1))); ++ + *bRGA_MODE_CTL = reg; +} + @@ -1897969,6 +1898344,10 @@ index 000000000..d2e379fa9 + u32 *bRGA_SRC_ACT_INFO; + u32 *bRGA_MASK_ADDR; + u32 *bRGA_SRC_TR_COLOR0, *bRGA_SRC_TR_COLOR1; ++ u32 *bRGA_FBCIN_HEAD_BASE; ++ u32 *bRGA_FBCIN_PAYL_BASE; ++ u32 *bRGA_FBCIN_OFF; ++ u32 *bRGA_FBCIN_HEAD_VIR_INFO; + + u8 disable_uv_channel_en = 0; + @@ -1897980,9 +1898359,12 @@ index 000000000..d2e379fa9 + + u8 src0_cbcr_swp = 0; + u8 pixel_width = 1; ++ u8 plane_width = 0; ++ u8 pixel_depth = 8; + u32 stride = 0; + u32 uv_stride = 0; + u32 mask_stride = 0; ++ u32 byte_stride = 0; + u32 ydiv = 1, xdiv = 2; + u8 yuv10 = 0; + @@ -1897990,7 +1898372,17 @@ index 000000000..d2e379fa9 + u32 dw, dh; + u8 rotate_mode; + u8 vsp_scale_mode = 0; ++ u8 vsd_scale_mode = 0; ++ u8 hsp_scale_mode = 0; ++ u8 hsd_scale_mode = 0; + u8 scale_w_flag, scale_h_flag; ++ u32 yrgb_offset = 0, uv_offset = 0, v_offset = 0; ++ u32 tile_x_offset = 0; ++ u32 tile_y_offset = 0; ++ u32 tile_block_size; ++ ++ u32 fbc_fmt = 0, fbc_mode = 0; ++ u32 head_base_addr, payload_base_addr; + + bRGA_SRC_INFO = (u32 *) (base + RGA2_SRC_INFO_OFFSET); + @@ -1898006,15 +1898398,10 @@ index 000000000..d2e379fa9 + 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 || -+ msg->src.format == RGA_FORMAT_YCbCr_422_SP_10B || -+ msg->src.format == RGA_FORMAT_YCrCb_422_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; -+ } ++ bRGA_FBCIN_HEAD_BASE = (u32 *) (base + RGA2_FBCIN_HEAD_BASE_OFFSET); ++ bRGA_FBCIN_PAYL_BASE = (u32 *) (base + RGA2_FBCIN_PAYL_BASE_OFFSET); ++ bRGA_FBCIN_OFF = (u32 *) (base + RGA2_FBCIN_OFF_OFFSET); ++ bRGA_FBCIN_HEAD_VIR_INFO = (u32 *) (base + RGA2_FBCIN_HEAD_VIR_INFO_OFFSET); + + { + rotate_mode = msg->rotate_mode & 0x3; @@ -1898031,21 +1898418,21 @@ index 000000000..d2e379fa9 + } + + if (sw > dw) -+ scale_w_flag = 1; ++ scale_w_flag = RGA2_SCALE_DOWN; + else if (sw < dw) -+ scale_w_flag = 2; ++ scale_w_flag = RGA2_SCALE_UP; + else { -+ scale_w_flag = 0; ++ scale_w_flag = RGA2_SCALE_BYPASS; + if (msg->rotate_mode >> 6) + scale_w_flag = 3; + } + + if (sh > dh) -+ scale_h_flag = 1; ++ scale_h_flag = RGA2_SCALE_DOWN; + else if (sh < dh) -+ scale_h_flag = 2; ++ scale_h_flag = RGA2_SCALE_UP; + else { -+ scale_h_flag = 0; ++ scale_h_flag = RGA2_SCALE_BYPASS; + if (msg->rotate_mode >> 6) + scale_h_flag = 3; + } @@ -1898055,16 +1898442,68 @@ index 000000000..d2e379fa9 + 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; ++ if (scale_h_flag == RGA2_SCALE_UP) { ++ switch (msg->interp.verti) { ++ case RGA_INTERP_BICUBIC: ++ /* ++ * VSP scale mode select, HSD > VSD > VSP > HSP ++ * After HSD, VSP needs to check dst_width. ++ */ ++ if (((scale_w_flag == RGA2_SCALE_DOWN) && (dw < RGA2_VSP_BICUBIC_LIMIT)) || ++ (sw < RGA2_VSP_BICUBIC_LIMIT)) { ++ vsp_scale_mode = 0x0; ++ } else { ++ /* force select bi-linear */ ++ rga_err("Horizontal scaling will be forcibly switched to bilinear.\n"); ++ vsp_scale_mode = 0x1; ++ } ++ break; ++ case RGA_INTERP_LINEAR: ++ vsp_scale_mode = 1; ++ break; ++ case RGA_INTERP_DEFAULT: ++ if (((scale_w_flag == RGA2_SCALE_DOWN) && (dw < RGA2_VSP_BICUBIC_LIMIT)) || ++ (sw < RGA2_VSP_BICUBIC_LIMIT)) { ++ vsp_scale_mode = 0x0; ++ } else { ++ vsp_scale_mode = 0x1; ++ } ++ break; ++ } ++ ++ } else if (scale_h_flag == RGA2_SCALE_DOWN) { ++ switch (msg->interp.verti) { ++ case RGA_INTERP_AVERAGE: ++ case RGA_INTERP_DEFAULT: ++ vsd_scale_mode = 0; ++ break; ++ case RGA_INTERP_LINEAR: ++ vsd_scale_mode = 1; ++ ++ break; ++ } ++ } ++ ++ if (scale_w_flag == RGA2_SCALE_UP) { ++ switch (msg->interp.horiz) { ++ case RGA_INTERP_BICUBIC: ++ case RGA_INTERP_DEFAULT: ++ hsp_scale_mode = 0; ++ break; ++ case RGA_INTERP_LINEAR: ++ hsp_scale_mode = 1; ++ break; ++ } ++ } else if (scale_w_flag == RGA2_SCALE_DOWN) { ++ switch (msg->interp.horiz) { ++ case RGA_INTERP_AVERAGE: ++ case RGA_INTERP_DEFAULT: ++ hsd_scale_mode = 0; ++ break; ++ case RGA_INTERP_LINEAR: ++ hsd_scale_mode = 1; ++ break; ++ } + } + + switch (msg->src.format) { @@ -1898104,30 +1898543,12 @@ index 000000000..d2e379fa9 + 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 */ + /* @@ -1898161,23 +1898582,19 @@ index 000000000..d2e379fa9 + 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; + @@ -1898208,44 +1898625,52 @@ index 000000000..d2e379fa9 + + case RGA_FORMAT_YCbCr_422_SP: + src0_format = 0x8; -+ xdiv = 1; ++ plane_width = 2; ++ xdiv = 2; + ydiv = 1; + break; + case RGA_FORMAT_YCbCr_422_P: + src0_format = 0x9; ++ plane_width = 1; + xdiv = 2; + ydiv = 1; + break; + case RGA_FORMAT_YCbCr_420_SP: + src0_format = 0xa; -+ xdiv = 1; ++ plane_width = 2; ++ xdiv = 2; + ydiv = 2; + break; + case RGA_FORMAT_YCbCr_420_P: + src0_format = 0xb; ++ plane_width = 1; + xdiv = 2; + ydiv = 2; + break; + case RGA_FORMAT_YCrCb_422_SP: + src0_format = 0x8; -+ xdiv = 1; ++ plane_width = 2; ++ xdiv = 2; + ydiv = 1; + src0_cbcr_swp = 1; + break; + case RGA_FORMAT_YCrCb_422_P: + src0_format = 0x9; ++ plane_width = 1; + xdiv = 2; + ydiv = 1; + src0_cbcr_swp = 1; + break; + case RGA_FORMAT_YCrCb_420_SP: + src0_format = 0xa; -+ xdiv = 1; ++ plane_width = 2; ++ xdiv = 2; + ydiv = 2; + src0_cbcr_swp = 1; + break; + case RGA_FORMAT_YCrCb_420_P: + src0_format = 0xb; ++ plane_width = 1; + xdiv = 2; + ydiv = 2; + src0_cbcr_swp = 1; @@ -1898253,26 +1898678,34 @@ index 000000000..d2e379fa9 + + case RGA_FORMAT_YCbCr_420_SP_10B: + src0_format = 0xa; -+ xdiv = 1; ++ plane_width = 2; ++ pixel_depth = 10; ++ xdiv = 2; + ydiv = 2; + yuv10 = 1; + break; + case RGA_FORMAT_YCrCb_420_SP_10B: + src0_format = 0xa; -+ xdiv = 1; ++ plane_width = 2; ++ pixel_depth = 10; ++ xdiv = 2; + ydiv = 2; + src0_cbcr_swp = 1; + yuv10 = 1; + break; + case RGA_FORMAT_YCbCr_422_SP_10B: + src0_format = 0x8; -+ xdiv = 1; ++ plane_width = 2; ++ pixel_depth = 10; ++ xdiv = 2; + ydiv = 1; + yuv10 = 1; + break; + case RGA_FORMAT_YCrCb_422_SP_10B: + src0_format = 0x8; -+ xdiv = 1; ++ plane_width = 2; ++ pixel_depth = 10; ++ xdiv = 2; + ydiv = 1; + src0_cbcr_swp = 1; + yuv10 = 1; @@ -1898285,38 +1898718,180 @@ index 000000000..d2e379fa9 + xdiv = 1; + ydiv = 1; + break; ++ ++ case RGA_FORMAT_YCbCr_444_SP: ++ src0_format = 0x3; ++ plane_width = 2; ++ xdiv = 1; ++ ydiv = 1; ++ break; ++ case RGA_FORMAT_YCrCb_444_SP: ++ src0_format = 0x3; ++ plane_width = 2; ++ xdiv = 1; ++ ydiv = 1; ++ src0_cbcr_swp = 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))); ++ switch (msg->src.rd_mode) { ++ case RGA_RASTER_MODE: ++ if (msg->src.format == RGA_FORMAT_YCbCr_420_SP_10B || ++ msg->src.format == RGA_FORMAT_YCrCb_420_SP_10B || ++ msg->src.format == RGA_FORMAT_YCbCr_422_SP_10B || ++ msg->src.format == RGA_FORMAT_YCrCb_422_SP_10B) ++ /* ++ * Legacy: implicit semantics exist here, 10bit format ++ * width_stride equals byte_stride. ++ */ ++ byte_stride = msg->src.vir_w; ++ else ++ byte_stride = msg->src.vir_w * pixel_width * pixel_depth / 8; + -+ 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))); ++ stride = ALIGN(byte_stride, 4); ++ uv_stride = ALIGN(msg->src.vir_w / xdiv * plane_width, 4); + -+ reg = -+ ((reg & (~m_RGA2_SRC_INFO_SW_SW_SRC_CSC_MODE)) | -+ (s_RGA2_SRC_INFO_SW_SW_SRC_CSC_MODE(msg->yuv2rgb_mode))); ++ yrgb_offset = msg->src.y_offset * stride + ++ msg->src.x_offset * pixel_width * pixel_depth / 8; ++ uv_offset = (msg->src.y_offset / ydiv) * uv_stride + ++ (msg->src.x_offset / xdiv * plane_width * pixel_depth / 8); ++ v_offset = uv_offset; + -+ 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)) | ++ break; ++ ++ case RGA_TILE4x4_MODE: ++ switch (msg->src.format) { ++ case RGA_FORMAT_YCbCr_400: ++ tile_block_size = 16; ++ break; ++ case RGA_FORMAT_YCbCr_420_SP: ++ case RGA_FORMAT_YCrCb_420_SP: ++ tile_block_size = 24; ++ break; ++ case RGA_FORMAT_YCbCr_422_SP: ++ case RGA_FORMAT_YCrCb_422_SP: ++ tile_block_size = 32; ++ break; ++ case RGA_FORMAT_YCbCr_444_SP: ++ case RGA_FORMAT_YCrCb_444_SP: ++ tile_block_size = 48; ++ break; ++ case RGA_FORMAT_YCbCr_420_SP_10B: ++ case RGA_FORMAT_YCrCb_420_SP_10B: ++ tile_block_size = 30; ++ break; ++ case RGA_FORMAT_YCbCr_422_SP_10B: ++ case RGA_FORMAT_YCrCb_422_SP_10B: ++ tile_block_size = 40; ++ break; ++ default: ++ tile_block_size = 16; ++ break; ++ } ++ ++ stride = ALIGN((u32)((msg->src.vir_w * pixel_width) * (tile_block_size / 4)), 4); ++ ++ yrgb_offset = (u32)((msg->src.y_offset / 4) * stride + ++ (msg->src.x_offset / 4) * pixel_width * tile_block_size); ++ uv_offset = 0; ++ v_offset = 0; ++ ++ tile_x_offset = (msg->src.x_offset % 4) & 0x3; ++ tile_y_offset = (msg->src.y_offset % 4) & 0x3; ++ ++ break; ++ ++ case RGA_RKFBC_MODE: ++ switch (msg->src.format) { ++ case RGA_FORMAT_YCbCr_420_SP: ++ case RGA_FORMAT_YCrCb_420_SP: ++ case RGA_FORMAT_YCbCr_420_SP_10B: ++ case RGA_FORMAT_YCrCb_420_SP_10B: ++ fbc_fmt = 0x0; ++ break; ++ case RGA_FORMAT_YCbCr_422_SP: ++ case RGA_FORMAT_YCrCb_422_SP: ++ case RGA_FORMAT_YCbCr_422_SP_10B: ++ case RGA_FORMAT_YCrCb_422_SP_10B: ++ fbc_fmt = 0x1; ++ break; ++ case RGA_FORMAT_YCbCr_444_SP: ++ case RGA_FORMAT_YCrCb_444_SP: ++ fbc_fmt = 0x2; ++ break; ++ } ++ ++ fbc_mode = 0x0; ++ head_base_addr = msg->src.yrgb_addr; ++ payload_base_addr = head_base_addr; ++ stride = ALIGN(msg->src.vir_w, 64) / 64 * 4; ++ ++ break; ++ ++ case RGA_AFBC32x8_MODE: ++ switch (msg->src.format) { ++ case RGA_FORMAT_RGBA_8888: ++ case RGA_FORMAT_BGRA_8888: ++ case RGA_FORMAT_ARGB_8888: ++ case RGA_FORMAT_ABGR_8888: ++ case RGA_FORMAT_RGBX_8888: ++ case RGA_FORMAT_BGRX_8888: ++ case RGA_FORMAT_XRGB_8888: ++ case RGA_FORMAT_XBGR_8888: ++ fbc_fmt = 0x0; ++ break; ++ case RGA_FORMAT_RGB_888: ++ case RGA_FORMAT_BGR_888: ++ fbc_fmt = 0x1; ++ break; ++ } ++ ++ fbc_mode = 0x1; ++ head_base_addr = msg->src.yrgb_addr; ++ payload_base_addr = head_base_addr; ++ stride = ALIGN(msg->src.vir_w, 32) / 32 * 4; ++ ++ break; ++ } ++ ++ if (msg->src.rd_mode == RGA_RKFBC_MODE || msg->src.rd_mode == RGA_AFBC32x8_MODE) { ++ reg = ((reg & (~m_RGA2_SRC_INFO_SW_FBCIN_MODE)) | ++ (s_RGA2_SRC_INFO_SW_FBCIN_MODE(fbc_mode))); ++ ++ reg = ((reg & (~m_RGA2_SRC_INFO_SW_FBCIN_FMT)) | ++ (s_RGA2_SRC_INFO_SW_FBCIN_FMT(fbc_fmt))); ++ } else { ++ 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)) | @@ -1898345,54 +1898920,49 @@ index 000000000..d2e379fa9 + reg = + ((reg & (~m_RGA2_SRC_INFO_SW_SW_YUV10_ROUND_E)) | + (s_RGA2_SRC_INFO_SW_SW_YUV10_ROUND_E((yuv10)))); ++ reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_VSD_MODE_SEL)) | ++ (s_RGA2_SRC_INFO_SW_SW_VSD_MODE_SEL((vsd_scale_mode)))); ++ reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_HSP_MODE_SEL)) | ++ (s_RGA2_SRC_INFO_SW_SW_HSP_MODE_SEL((hsp_scale_mode)))); ++ reg = ((reg & (~m_RGA2_SRC_INFO_SW_SW_HSD_MODE_SEL)) | ++ (s_RGA2_SRC_INFO_SW_SW_HSD_MODE_SEL((hsd_scale_mode)))); + -+ 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_INFO = reg; ++ if (msg->src.rd_mode == RGA_RKFBC_MODE || msg->src.rd_mode == RGA_AFBC32x8_MODE) { ++ *bRGA_FBCIN_HEAD_BASE = head_base_addr; ++ *bRGA_FBCIN_PAYL_BASE = payload_base_addr; ++ *bRGA_FBCIN_HEAD_VIR_INFO = stride; ++ *bRGA_FBCIN_OFF = msg->src.x_offset | (msg->src.y_offset << 16); ++ *bRGA_SRC_ACT_INFO = (msg->src.act_w - 1) | ((msg->src.act_h - 1) << 16); ++ } else { ++ *bRGA_SRC_BASE0 = (u32)(msg->src.yrgb_addr + yrgb_offset); ++ 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_BASE1 = *bRGA_SRC_BASE0; ++ *bRGA_SRC_BASE2 = *bRGA_SRC_BASE0; ++ } else { ++ *bRGA_SRC_BASE1 = (u32)(msg->src.uv_addr + uv_offset); ++ *bRGA_SRC_BASE2 = (u32)(msg->src.v_addr + v_offset); ++ } + -+ *bRGA_SRC_VIR_INFO = stride | (mask_stride << 16); ++ //mask_stride = ((msg->src0_act.width + 31) & ~31) >> 5; ++ mask_stride = msg->rop_mask_stride; ++ *bRGA_SRC_VIR_INFO = (stride >> 2) | (mask_stride << 16); + -+ *bRGA_SRC_ACT_INFO = -+ (msg->src.act_w - 1) | ((msg->src.act_h - 1) << 16); ++ *bRGA_SRC_ACT_INFO = ++ (msg->src.act_w - 1) | ((msg->src.act_h - 1) << 16) | ++ tile_x_offset << 14 | tile_y_offset << 30; + -+ *bRGA_MASK_ADDR = (u32) msg->rop_mask_addr; ++ *bRGA_MASK_ADDR = (u32) msg->rop_mask_addr; ++ } + -+ *bRGA_SRC_INFO = reg; ++ RGA2_reg_get_param(base, msg); + + *bRGA_SRC_TR_COLOR0 = msg->color_key_min; + *bRGA_SRC_TR_COLOR1 = msg->color_key_max; @@ -1898400,9 +1898970,12 @@ index 000000000..d2e379fa9 + +static void RGA2_set_reg_dst_info(u8 *base, struct rga2_req *msg) +{ ++ u32 *bRGA_SRC_FG_COLOR; ++ u32 *bRGA_SRC_BG_COLOR; + u32 *bRGA_DST_INFO; + u32 *bRGA_DST_BASE0, *bRGA_DST_BASE1, *bRGA_DST_BASE2, + *bRGA_SRC_BASE3; ++ u32 *bRGA_TILE4x4_OUT_BASE; + u32 *bRGA_DST_VIR_INFO; + u32 *bRGA_DST_ACT_INFO; + @@ -1898426,28 +1898999,38 @@ index 000000000..d2e379fa9 + + u8 dst_fmt_yuv400_en = 0; + u8 dst_fmt_y4_en = 0; ++ u8 dst_fmt_y4_lut_en = 0; + u8 dst_nn_quantize_en = 0; + + u32 reg = 0; + u8 spw, dpw; ++ u8 plane_width = 0; + u8 bbp_shift = 0; -+ u32 s_stride, d_stride; ++ u32 s_stride = 0, d_stride = 0; + 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; ++ u32 y_lt_addr = 0, y_ld_addr = 0, y_rt_addr = 0, y_rd_addr = 0; ++ u32 u_lt_addr = 0, u_ld_addr = 0, u_rt_addr = 0, u_rd_addr = 0; ++ u32 v_lt_addr = 0, v_ld_addr = 0, v_rt_addr = 0, v_rd_addr = 0; ++ u32 yrgb_offset = 0, uv_offset = 0, v_offset = 0; ++ u32 tile_x_offset = 0; ++ u32 tile_y_offset = 0; ++ u32 tile_block_size; + + dpw = 1; + x_div = y_div = 1; + + dst_nn_quantize_en = (msg->alpha_rop_flag >> 8) & 0x1; + ++ bRGA_SRC_FG_COLOR = (u32 *) (base + RGA2_SRC_FG_COLOR_OFFSET); ++ bRGA_SRC_BG_COLOR = (u32 *) (base + RGA2_SRC_BG_COLOR_OFFSET); ++ + 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_TILE4x4_OUT_BASE = (u32 *) (base + RGA2_TILE4x4_OUT_BASE_OFFSET); + + bRGA_SRC_BASE3 = (u32 *) (base + RGA2_SRC_BASE3_OFFSET); + @@ -1898493,29 +1899076,11 @@ index 000000000..d2e379fa9 + 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: @@ -1898543,23 +1899108,19 @@ index 000000000..d2e379fa9 + 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: @@ -1898569,6 +1899130,10 @@ index 000000000..d2e379fa9 + bbp_shift = 2; + src1_alpha_swp = msg->osd_info.bpp2_info.ac_swap; + break; ++ case RGA_FORMAT_A8: ++ src1_format = 0x3; ++ spw = 1; ++ break; + default: + spw = 4; + break; @@ -1898584,6 +1899149,14 @@ index 000000000..d2e379fa9 + ((reg & (~m_RGA2_DST_INFO_SW_SRC1_ALPHA_SWP)) | + (s_RGA2_DST_INFO_SW_SRC1_ALPHA_SWP(src1_alpha_swp))); + ++ if (msg->rgba5551_alpha.flags & 0x1) { ++ reg = ((reg & (~m_RGA2_DST_INFO_SW_SRC1_A1555_ACONFIG_EN)) | ++ (s_RGA2_DST_INFO_SW_SRC1_A1555_ACONFIG_EN(1))); ++ ++ *bRGA_SRC_FG_COLOR = (msg->rgba5551_alpha.alpha1 & 0xff) << 24; ++ *bRGA_SRC_BG_COLOR = (msg->rgba5551_alpha.alpha0 & 0xff) << 24; ++ } ++ + switch (msg->dst.format) { + case RGA_FORMAT_RGBA_8888: + dst_format = 0x0; @@ -1898688,45 +1899261,53 @@ index 000000000..d2e379fa9 + + case RGA_FORMAT_YCbCr_422_SP: + dst_format = 0x8; -+ x_div = 1; ++ plane_width = 2; ++ x_div = 2; + y_div = 1; + break; + case RGA_FORMAT_YCbCr_422_P: + dst_format = 0x9; ++ plane_width = 1; + x_div = 2; + y_div = 1; + break; + case RGA_FORMAT_YCbCr_420_SP: + dst_format = 0xa; -+ x_div = 1; ++ plane_width = 2; ++ x_div = 2; + y_div = 2; + break; + case RGA_FORMAT_YCbCr_420_P: + dst_format = 0xb; + dst_cbcr_swp = 1; ++ plane_width = 1; + x_div = 2; + y_div = 2; + break; + case RGA_FORMAT_YCrCb_422_SP: + dst_format = 0x8; + dst_cbcr_swp = 1; -+ x_div = 1; ++ plane_width = 2; ++ x_div = 2; + y_div = 1; + break; + case RGA_FORMAT_YCrCb_422_P: + dst_format = 0x9; + dst_cbcr_swp = 1; ++ plane_width = 1; + x_div = 2; + y_div = 1; + break; + case RGA_FORMAT_YCrCb_420_SP: + dst_format = 0xa; + dst_cbcr_swp = 1; -+ x_div = 1; ++ plane_width = 2; ++ x_div = 2; + y_div = 2; + break; + case RGA_FORMAT_YCrCb_420_P: + dst_format = 0xb; ++ plane_width = 1; + x_div = 2; + y_div = 2; + break; @@ -1898740,6 +1899321,15 @@ index 000000000..d2e379fa9 + case RGA_FORMAT_Y4: + dst_format = 0x8; + dst_fmt_y4_en = 1; ++ dst_fmt_y4_lut_en = 1; ++ dst_fmt_yuv400_en = 1; ++ x_div = 1; ++ y_div = 1; ++ break; ++ ++ case RGA_FORMAT_Y8: ++ dst_format = 0x8; ++ dst_fmt_y4_lut_en = 1; + dst_fmt_yuv400_en = 1; + x_div = 1; + y_div = 1; @@ -1898781,6 +1899371,20 @@ index 000000000..d2e379fa9 + dst_format = 0xd; + dpw = 2; + break; ++ ++ case RGA_FORMAT_YCbCr_444_SP: ++ dst_format = 0x3; ++ plane_width = 2; ++ x_div = 1; ++ y_div = 1; ++ break; ++ case RGA_FORMAT_YCrCb_444_SP: ++ dst_format = 0x3; ++ plane_width = 2; ++ x_div = 1; ++ y_div = 1; ++ dst_cbcr_swp = 1; ++ break; + }; + + reg = @@ -1898841,37 +1899445,14 @@ index 000000000..d2e379fa9 + 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) ++ ydither_en = (msg->dst.format == RGA_FORMAT_Y4 || ++ msg->dst.format == RGA_FORMAT_Y8) + && ((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)) { ++ ((msg->rotate_mode & 0xf) == 1)) { + x_mirr = 0; + y_mirr = 0; + } else { @@ -1898885,22 +1899466,22 @@ index 000000000..d2e379fa9 + + if (ydither_en) { + if (x_mirr && y_mirr) { -+ pr_err("ydither mode do not support rotate x_mirr=%d,y_mirr=%d\n", ++ rga_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"); ++ rga_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"); ++ rga_err("ydither mode do not support y dir scale\n"); + } + -+ if (dst_fmt_y4_en) { ++ if (dst_fmt_y4_lut_en) { + *RGA_DST_Y4MAP_LUT0 = (msg->gr_color.gr_x_r & 0xffff) | -+ (msg->gr_color.gr_x_g << 16); ++ (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); ++ (msg->gr_color.gr_y_g << 16); + } + + if (dst_nn_quantize_en) { @@ -1898912,67 +1899493,143 @@ index 000000000..d2e379fa9 + (msg->gr_color.gr_y_b << 20); + } + ++ s_stride = (((msg->src1.vir_w * spw >> bbp_shift) + 3) & ~3); ++ + 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; ++ /* Warning */ ++ line_width_real = dst_fmt_y4_en ? ((msg->dst.act_w) >> 1) : msg->dst.act_w; + -+ y_lt_addr = yrgb_addr; -+ u_lt_addr = u_addr; -+ v_lt_addr = v_addr; ++ switch (msg->dst.rd_mode) { ++ case RGA_RASTER_MODE: ++ d_stride = ALIGN(msg->dst.vir_w * dpw, 4); ++ /* Y4 output will HALF */ ++ if (dst_fmt_y4_en) ++ d_stride = ALIGN(d_stride, 2) >> 1; ++ d_uv_stride = ALIGN(d_stride / x_div * plane_width, 4); + -+ /* Warning */ -+ line_width_real = -+ dst_fmt_y4_en ? ((msg->dst.act_w) >> 1) : msg->dst.act_w; ++ yrgb_offset = msg->dst.y_offset * d_stride + msg->dst.x_offset * dpw; ++ uv_offset = (msg->dst.y_offset / y_div) * d_uv_stride + ++ (msg->dst.x_offset / x_div * plane_width); ++ v_offset = uv_offset; + -+ /* -+ * 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; -+ } ++ yrgb_addr = (u32)msg->dst.yrgb_addr + yrgb_offset; ++ u_addr = (u32)msg->dst.uv_addr + uv_offset; ++ v_addr = (u32)msg->dst.v_addr + v_offset; + -+ 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); ++ y_lt_addr = yrgb_addr; ++ u_lt_addr = u_addr; ++ v_lt_addr = v_addr; + -+ u_rt_addr = u_addr + (msg->dst.act_w / x_div) - 1; -+ v_rt_addr = v_addr + (msg->dst.act_w / x_div) - 1; ++ /* ++ * 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_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; ++ 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 * plane_width) - 1; ++ v_rt_addr = v_addr + (msg->dst.act_w / x_div * plane_width) - 1; ++ ++ u_rd_addr = u_ld_addr + (msg->dst.act_w / x_div * plane_width) - 1; ++ v_rd_addr = v_ld_addr + (msg->dst.act_w / x_div * plane_width) - 1; ++ ++ break; ++ ++ case RGA_TILE4x4_MODE: ++ switch (msg->dst.format) { ++ case RGA_FORMAT_YCbCr_400: ++ tile_block_size = 16; ++ break; ++ case RGA_FORMAT_YCbCr_420_SP: ++ case RGA_FORMAT_YCrCb_420_SP: ++ tile_block_size = 24; ++ break; ++ case RGA_FORMAT_YCbCr_422_SP: ++ case RGA_FORMAT_YCrCb_422_SP: ++ tile_block_size = 32; ++ break; ++ case RGA_FORMAT_YCbCr_444_SP: ++ case RGA_FORMAT_YCrCb_444_SP: ++ tile_block_size = 48; ++ break; ++ case RGA_FORMAT_YCbCr_420_SP_10B: ++ case RGA_FORMAT_YCrCb_420_SP_10B: ++ tile_block_size = 30; ++ break; ++ case RGA_FORMAT_YCbCr_422_SP_10B: ++ case RGA_FORMAT_YCrCb_422_SP_10B: ++ tile_block_size = 40; ++ break; ++ default: ++ tile_block_size = 16; ++ break; ++ } ++ ++ d_stride = ALIGN((u32)((msg->dst.vir_w * dpw) * (tile_block_size / 4)), 4); ++ ++ yrgb_offset = (u32)((msg->dst.y_offset / 4) * d_stride + ++ (msg->dst.x_offset / 4) * dpw * tile_block_size); ++ ++ tile_x_offset = (msg->dst.x_offset % 4) & 0x3; ++ tile_y_offset = (msg->dst.y_offset % 4) & 0x3; ++ ++ y_lt_addr = (u32)msg->dst.yrgb_addr + yrgb_offset; ++ y_ld_addr = y_lt_addr + ++ (msg->dst.act_h / 4 - ((msg->dst.act_h % 4 == 0) ? 1 : 0)) * d_stride; ++ y_rt_addr = y_lt_addr + ++ (line_width_real / 4 - ((msg->dst.act_w % 4 == 0) ? 0 : 1)) * dpw * ++ tile_block_size; ++ y_rd_addr = y_rt_addr + ++ (msg->dst.act_h / 4 - ((msg->dst.act_h % 4 == 0) ? 1 : 0)) * d_stride; ++ ++ u_lt_addr = 0; ++ u_ld_addr = 0; ++ u_rt_addr = 0; ++ u_rd_addr = 0; ++ ++ v_lt_addr = 0; ++ v_ld_addr = 0; ++ v_rt_addr = 0; ++ v_rd_addr = 0; ++ ++ break; ++ } ++ ++ *bRGA_DST_VIR_INFO = (d_stride >> 2) | ((s_stride >> 2) << 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) | ++ tile_x_offset << 14 | tile_y_offset << 30; ++ else ++ *bRGA_DST_ACT_INFO = ++ (msg->dst.act_w - 1) | ((msg->dst.act_h - 1) << 16) | ++ tile_x_offset << 14 | tile_y_offset << 30; + + if (rot_90_flag == 0) { + if (y_mirr == 1) { @@ -1899022,18 +1899679,45 @@ index 000000000..d2e379fa9 + + *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; ++ switch (msg->dst.rd_mode) { ++ case RGA_RASTER_MODE: ++ 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; + } -+ } else { -+ *bRGA_DST_BASE1 = (u32) u_addr; -+ *bRGA_DST_BASE2 = (u32) v_addr; ++ ++ break; ++ case RGA_TILE4x4_MODE: ++ *bRGA_TILE4x4_OUT_BASE = yrgb_addr; ++ ++ break; ++ } ++ ++ if (rot_90_flag == 1) { ++ if (y_mirr == 1) { ++ msg->iommu_prefetch.y_threshold = y_lt_addr >> 16 ? ++ RGA2_IOMMU_PREFETCH_ALIGN_DOWN(y_lt_addr) : ++ RGA2_IOMMU_PREFETCH_THRESHOLD_MIN; ++ msg->iommu_prefetch.uv_threshold = u_lt_addr >> 16 ? ++ RGA2_IOMMU_PREFETCH_ALIGN_DOWN(u_lt_addr) : ++ RGA2_IOMMU_PREFETCH_THRESHOLD_MIN; ++ } else { ++ msg->iommu_prefetch.y_threshold = (y_rd_addr >> 16) == 0xffff ? ++ RGA2_IOMMU_PREFETCH_THRESHOLD_MAX : ++ RGA2_IOMMU_PREFETCH_ALIGN(y_rd_addr); ++ msg->iommu_prefetch.uv_threshold = (u_rd_addr >> 16) == 0xffff ? ++ RGA2_IOMMU_PREFETCH_THRESHOLD_MAX : ++ RGA2_IOMMU_PREFETCH_ALIGN(u_rd_addr); ++ } + } +} + @@ -1899344,6 +1900028,50 @@ index 000000000..d2e379fa9 + *bRGA_MOSAIC_MODE = (u32)(msg->mosaic_info.mode & 0x7); +} + ++static int RGA_set_reg_gauss(u8 *base, struct rga2_req *msg) ++{ ++ uint32_t *bRGA_GAUSS_COE; ++ uint32_t reg = 0; ++ uint32_t *coe; ++ ++ bRGA_GAUSS_COE = (u32 *)(base + RGA2_GAUSS_COE_OFFSET); ++ ++ if (msg->gauss_config.size != 3) { ++ rga_err("Gaussian blur only support 3x3\n"); ++ return -EINVAL; ++ } ++ ++ coe = kmalloc(sizeof(uint32_t) * msg->gauss_config.size, GFP_KERNEL); ++ if (coe == NULL) { ++ rga_err("Gaussian blur alloc coe buffer error!\n"); ++ return -ENOMEM; ++ } ++ ++ if (unlikely(copy_from_user(coe, ++ u64_to_user_ptr(msg->gauss_config.coe_ptr), ++ sizeof(uint32_t) * msg->gauss_config.size))) { ++ rga_err("Gaussian blur coe copy_from_user failed\n"); ++ ++ kfree(coe); ++ return -EFAULT; ++ } ++ ++ reg = ((reg & (~m_RGA2_GAUSS_COE_SW_COE0)) | ++ (s_RGA2_GAUSS_COE_SW_COE0(coe[0]))); ++ ++ reg = ((reg & (~m_RGA2_GAUSS_COE_SW_COE1)) | ++ (s_RGA2_GAUSS_COE_SW_COE1(coe[1]))); ++ ++ reg = ((reg & (~m_RGA2_GAUSS_COE_SW_COE2)) | ++ (s_RGA2_GAUSS_COE_SW_COE2(coe[2]))); ++ ++ *bRGA_GAUSS_COE = reg; ++ ++ kfree(coe); ++ ++ return 0; ++} ++ +static void RGA2_set_reg_osd(u8 *base, struct rga2_req *msg) +{ + u32 *bRGA_OSD_CTRL0; @@ -1899608,36 +1900336,52 @@ index 000000000..d2e379fa9 + *bRGA_FADING_CTRL = (num << 8) | offset; +} + -+static void RGA2_set_mmu_reg_info(u8 *base, struct rga2_req *msg) ++static void RGA2_set_mmu_reg_info(struct rga_scheduler_t *scheduler, 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 *RGA_PREFETCH_ADDR_TH; + + 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); ++ switch (scheduler->data->mmu) { ++ case RGA_MMU: ++ 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); + -+ 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; ++ ++ break; ++ case RGA_IOMMU: ++ RGA_PREFETCH_ADDR_TH = (u32 *)(base + RGA2_PREFETCH_ADDR_TH_OFFSET); + -+ *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; ++ *RGA_PREFETCH_ADDR_TH = ++ (msg->iommu_prefetch.y_threshold >> RGA2_IOMMU_PREFETCH_SHIFT) | ++ ((msg->iommu_prefetch.uv_threshold >> RGA2_IOMMU_PREFETCH_SHIFT) << 16); ++ break; ++ default: ++ break; ++ } +} + -+static int rga2_gen_reg_info(u8 *base, struct rga2_req *msg) ++static int rga2_gen_reg_info(struct rga_scheduler_t *scheduler, u8 *base, struct rga2_req *msg) +{ ++ int ret; + u8 dst_nn_quantize_en = 0; + + RGA2_set_mode_ctrl(base, msg); @@ -1899650,20 +1900394,37 @@ index 000000000..d2e379fa9 + 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)) { ++ if ((msg->dst.format != RGA_FORMAT_Y4) && ++ (msg->dst.format != RGA_FORMAT_Y8)) { + RGA2_set_reg_alpha_info(base, msg); -+ RGA2_set_reg_rop_info(base, msg); ++ if (msg->rgba5551_alpha.flags != 1) ++ 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); -+ ++ if (msg->gauss_config.size > 0) { ++ ret = RGA_set_reg_gauss(base, msg); ++ if (ret < 0) ++ return ret; ++ } ++ + break; + case COLOR_FILL_MODE: + RGA2_set_reg_color_fill(base, msg); ++ /* tile4x4 need a fake input */ ++ if (msg->dst.rd_mode == RGA_TILE4x4_MODE) { ++ msg->src.act_w = msg->dst.act_w; ++ msg->src.act_h = msg->dst.act_h; ++ msg->src.vir_w = msg->dst.vir_w; ++ msg->src.vir_h = msg->dst.vir_h; ++ msg->src.format = RGA_FORMAT_RGBA_8888; ++ msg->src.rd_mode = RGA_RASTER_MODE; ++ ++ RGA2_set_reg_src_info(base, msg); ++ } + RGA2_set_reg_dst_info(base, msg); + RGA2_set_reg_alpha_info(base, msg); + break; @@ -1899678,11 +1900439,11 @@ index 000000000..d2e379fa9 + RGA2_set_reg_update_patten_buff(base, msg); + break; + default: -+ pr_err("ERROR msg render mode %d\n", msg->render_mode); -+ break; ++ rga_err("ERROR msg render mode %d\n", msg->render_mode); ++ return -EINVAL; + } + -+ RGA2_set_mmu_reg_info(base, msg); ++ RGA2_set_mmu_reg_info(scheduler, base, msg); + + return 0; +} @@ -1899767,6 +1900528,27 @@ index 000000000..d2e379fa9 + break; + } + ++ if ((req->src.act_w == req->dst.act_w) && ++ (req->src.act_h == req->dst.act_h) && ++ (req->rotate_mode == 0)) { ++ if (req->src.format == RGA_FORMAT_YCbCr_420_SP_10B || ++ req->src.format == RGA_FORMAT_YCrCb_420_SP_10B || ++ req->src.format == RGA_FORMAT_YCbCr_444_SP || ++ req->src.format == RGA_FORMAT_YCrCb_444_SP || ++ req->dst.format == RGA_FORMAT_YCbCr_444_SP || ++ req->dst.format == RGA_FORMAT_YCrCb_444_SP) ++ /* force select to tile mode */ ++ req->rotate_mode = 1 << 6; ++ } ++ ++ if (req->src.rd_mode == RGA_TILE4x4_MODE || ++ req->dst.rd_mode == RGA_TILE4x4_MODE || ++ req->src.rd_mode == RGA_RKFBC_MODE || ++ req->src.rd_mode == RGA_AFBC32x8_MODE) ++ /* force select to tile mode */ ++ req->rotate_mode |= 1 << 6; ++ ++ req->interp = req_rga->interp; + req->LUT_addr = req_rga->LUT_addr; + req->rop_mask_addr = req_rga->rop_mask_addr; + @@ -1899820,6 +1900602,8 @@ index 000000000..d2e379fa9 + /* RGA2 1106 add */ + memcpy(&req->mosaic_info, &req_rga->mosaic_info, sizeof(req_rga->mosaic_info)); + ++ memcpy(&req->gauss_config, &req_rga->gauss_config, sizeof(req_rga->gauss_config)); ++ + if ((scheduler->data->feature & RGA_YIN_YOUT) && + rga_is_only_y_format(req->src.format) && + rga_is_only_y_format(req->dst.format)) @@ -1899830,6 +1900614,8 @@ index 000000000..d2e379fa9 + + memcpy(&req->osd_info, &req_rga->osd_info, sizeof(req_rga->osd_info)); + ++ memcpy(&req->rgba5551_alpha, &req_rga->rgba5551_alpha, sizeof(req_rga->rgba5551_alpha)); ++ + if (((req_rga->alpha_rop_flag) & 1)) { + if ((req_rga->alpha_rop_flag >> 3) & 1) { + req->alpha_config.enable = true; @@ -1899873,12 +1900659,19 @@ index 000000000..d2e379fa9 + req->alpha_config.bg_global_alpha_value = 0xff; + } + } else { -+ req->alpha_config.fg_global_alpha_value = 0xff; ++ req->alpha_config.bg_global_alpha_value = 0xff; + req->alpha_config.bg_global_alpha_value = 0xff; + } + + req->alpha_config.mode = req_rga->PD_mode; + } ++ } else if (req_rga->gauss_config.size > 0) { ++ if (req_rga->feature.global_alpha_en) { ++ req->alpha_config.fg_global_alpha_en = true; ++ req->alpha_config.fg_global_alpha_value = req_rga->fg_global_alpha; ++ } else { ++ req->alpha_config.fg_global_alpha_value = 0xff; ++ } + } + + if (req_rga->mmu_info.mmu_en && (req_rga->mmu_info.mmu_flag & 1) == 1) { @@ -1899920,7 +1900713,7 @@ index 000000000..d2e379fa9 + } +} + -+static void rga2_soft_reset(struct rga_scheduler_t *scheduler) ++static int rga2_soft_reset(struct rga_scheduler_t *scheduler) +{ + u32 i; + u32 reg; @@ -1899949,53 +1900742,63 @@ index 000000000..d2e379fa9 + 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); ++ return i; ++} ++ ++static void rga2_soft_reset_print(struct rga_scheduler_t *scheduler) ++{ ++ int ret; + ++ ret = rga2_soft_reset(scheduler); ++ if (ret >= RGA_RESET_TIMEOUT) ++ rga_err("%s[%#x] soft reset timeout.\n", ++ rga_get_core_name(scheduler->core), scheduler->core); ++ else ++ rga_log("%s[%#x] soft reset complete.\n", ++ rga_get_core_name(scheduler->core), scheduler->core); +} + -+static int rga2_check_param(const struct rga_hw_data *data, const struct rga2_req *req) ++static int rga2_check_param(struct rga_job *job, ++ 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", ++ rga_job_err(job, "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", ++ rga_job_err(job, "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", ++ rga_job_err(job, "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", ++ rga_job_err(job, "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", ++ rga_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", ++ rga_err("invalid dst_vir_w act_h = %d, vir_h = %d\n", + req->dst.act_w, req->dst.vir_w); + return -EINVAL; + } @@ -1900004,83 +1900807,79 @@ index 000000000..d2e379fa9 + return 0; +} + -+static int rga2_align_check(struct rga2_req *req) ++static int rga2_align_check(struct rga_job *job, 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 ((req->src.x_offset % 2) || (req->src.y_offset % 2) || ++ (req->src.act_w % 2) || (req->src.act_w % 2)) ++ rga_job_log(job, "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 ((req->dst.x_offset % 2) || (req->dst.y_offset % 2) || ++ (req->dst.act_w % 2) || (req->dst.act_w % 2)) ++ rga_job_log(job, "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 ((req->src.x_offset % 2) || (req->src.y_offset % 2) || ++ (req->src.act_w % 2) || (req->src.act_w % 2)) ++ rga_job_log(job, "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"); ++ if ((req->dst.x_offset % 2) || (req->dst.y_offset % 2) || ++ (req->dst.act_w % 2) || (req->dst.act_w % 2)) ++ rga_job_log(job, "err dst wstride, 8bit yuv\n"); + + return 0; +} + -+static void print_debug_info(struct rga2_req *req) ++static void print_debug_info(struct rga_job *job, struct rga2_req *req) +{ -+ pr_info("render_mode:%s,bitblit_mode=%d,rotate_mode:%s\n", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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); ++ rga_job_log(job, "yuv2rgb mode is %x\n", req->yuv2rgb_mode); +} + +static int rga2_init_reg(struct rga_job *job) @@ -1900092,7 +1900891,7 @@ index 000000000..d2e379fa9 + + scheduler = job->scheduler; + if (unlikely(scheduler == NULL)) { -+ pr_err("failed to get scheduler, %s(%d)\n", __func__, __LINE__); ++ rga_job_err(job, "failed to get scheduler, %s(%d)\n", __func__, __LINE__); + return -EINVAL; + } + @@ -1900120,34 +1900919,34 @@ index 000000000..d2e379fa9 + memcpy(&job->pre_intr_info, &job->rga_command_base.pre_intr_info, + sizeof(job->pre_intr_info)); + ++ /* for debug */ ++ if (DEBUGGER_EN(MSG)) ++ print_debug_info(job, &req); ++ + /* check value if legal */ -+ ret = rga2_check_param(scheduler->data, &req); ++ ret = rga2_check_param(job, scheduler->data, &req); + if (ret == -EINVAL) { -+ pr_err("req argument is inval\n"); ++ rga_job_err(job, "req argument is inval\n"); + return ret; + } + -+ rga2_align_check(&req); -+ -+ /* for debug */ -+ if (DEBUGGER_EN(MSG)) -+ print_debug_info(&req); ++ rga2_align_check(job, &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); ++ rga_job_err(job, "core[%d] has no MMU, please use physically contiguous memory.\n", ++ scheduler->core); ++ rga_job_err(job, "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__, ++ rga_job_err(job, "%s, [%d] set mmu info error\n", __func__, + __LINE__); + return -EFAULT; + } @@ -1900157,19 +1900956,20 @@ index 000000000..d2e379fa9 + 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"); ++ ret = rga2_gen_reg_info(scheduler, (uint8_t *)job->cmd_buf->vaddr, &req); ++ if (ret < 0) { ++ rga_job_err(job, "gen reg info error\n"); + return -EINVAL; + } + + if (DEBUGGER_EN(TIME)) -+ pr_info("request[%d], generate register cost time %lld us\n", -+ job->request_id, ktime_us_delta(ktime_get(), timestamp)); ++ rga_job_log(job, "generate register cost time %lld us\n", ++ ktime_us_delta(ktime_get(), timestamp)); + + return ret; +} + -+static void rga2_dump_read_back_sys_reg(struct rga_scheduler_t *scheduler) ++static void rga2_dump_read_back_sys_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) +{ + int i; + unsigned long flags; @@ -1900182,15 +1900982,15 @@ index 000000000..d2e379fa9 + + spin_unlock_irqrestore(&scheduler->irq_lock, flags); + -+ pr_info("SYS_READ_BACK_REG\n"); ++ rga_job_log(job, "SYS_READ_BACK_REG\n"); + for (i = 0; i < 6; i++) -+ pr_info("0x%04x : %.8x %.8x %.8x %.8x\n", ++ rga_job_log(job, "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) ++static void rga2_dump_read_back_csc_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) +{ + int i; + unsigned long flags; @@ -1900203,15 +1901003,36 @@ index 000000000..d2e379fa9 + + spin_unlock_irqrestore(&scheduler->irq_lock, flags); + -+ pr_info("CSC_READ_BACK_REG\n"); ++ rga_job_log(job, "CSC_READ_BACK_REG\n"); + for (i = 0; i < 3; i++) -+ pr_info("0x%04x : %.8x %.8x %.8x %.8x\n", ++ rga_job_log(job, "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) ++static void rga2_dump_read_back_other_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) ++{ ++ int i; ++ unsigned long flags; ++ uint32_t other_reg[4] = {0}; ++ ++ spin_lock_irqsave(&scheduler->irq_lock, flags); ++ ++ for (i = 0; i < 4; i++) ++ other_reg[i] = rga_read(RGA2_OTHER_REG_BASE + i * 4, scheduler); ++ ++ spin_unlock_irqrestore(&scheduler->irq_lock, flags); ++ ++ rga_job_log(job, "OTHER_READ_BACK_REG\n"); ++ for (i = 0; i < 1; i++) ++ rga_job_log(job, "0x%04x : %.8x %.8x %.8x %.8x\n", ++ RGA2_OTHER_REG_BASE + i * 0x10, ++ other_reg[0 + i * 4], other_reg[1 + i * 4], ++ other_reg[2 + i * 4], other_reg[3 + i * 4]); ++} ++ ++static void rga2_dump_read_back_cmd_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) +{ + int i; + unsigned long flags; @@ -1900224,19 +1901045,43 @@ index 000000000..d2e379fa9 + + spin_unlock_irqrestore(&scheduler->irq_lock, flags); + -+ pr_info("CMD_READ_BACK_REG\n"); ++ rga_job_log(job, "CMD_READ_BACK_REG\n"); + for (i = 0; i < 8; i++) -+ pr_info("0x%04x : %.8x %.8x %.8x %.8x\n", ++ rga_job_log(job, "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) ++static void rga2_dump_read_back_iommu_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) ++{ ++ int i; ++ unsigned long flags; ++ uint32_t cmd_reg[12] = {0}; ++ ++ spin_lock_irqsave(&scheduler->irq_lock, flags); ++ ++ for (i = 0; i < 12; i++) ++ cmd_reg[i] = rga_read(RGA2_IOMMU_REG_BASE + i * 4, scheduler); ++ ++ spin_unlock_irqrestore(&scheduler->irq_lock, flags); ++ ++ rga_job_log(job, "IOMMU_READ_BACK_REG\n"); ++ for (i = 0; i < 3; i++) ++ rga_job_log(job, "0x%04x : %.8x %.8x %.8x %.8x\n", ++ RGA2_IOMMU_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_job *job, 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); ++ rga2_dump_read_back_sys_reg(job, scheduler); ++ rga2_dump_read_back_csc_reg(job, scheduler); ++ if (scheduler->data->version > 0) ++ rga2_dump_read_back_other_reg(job, scheduler); ++ rga2_dump_read_back_cmd_reg(job, scheduler); ++ rga2_dump_read_back_iommu_reg(job, scheduler); +} + +static void rga2_set_pre_intr_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) @@ -1900300,8 +1901145,12 @@ index 000000000..d2e379fa9 + int i; + bool master_mode_en; + uint32_t sys_ctrl; ++ uint32_t *cmd; ++ unsigned long flags; + ktime_t now = ktime_get(); + ++ cmd = job->cmd_buf->vaddr; ++ + /* + * Currently there is no iova allocated for storing cmd for the IOMMU device, + * so the iommu device needs to use the slave mode. @@ -1900311,72 +1901160,82 @@ index 000000000..d2e379fa9 + else + master_mode_en = false; + -+ if (job->pre_intr_info.enable) -+ rga2_set_pre_intr_reg(job, scheduler); ++ if (DEBUGGER_EN(REG)) { ++ rga2_dump_read_back_sys_reg(job, scheduler); ++ rga2_dump_read_back_csc_reg(job, scheduler); ++ if (scheduler->data->version > 0) ++ rga2_dump_read_back_other_reg(job, scheduler); + -+ if (job->full_csc.flag) -+ rga2_set_reg_full_csc(job, scheduler); ++ rga_job_log(job, "CMD_REG\n"); ++ for (i = 0; i < 8; i++) ++ rga_job_log(job, "0x%04x : %.8x %.8x %.8x %.8x\n", ++ RGA2_CMD_REG_BASE + i * 0x10, ++ cmd[0 + i * 4], cmd[1 + i * 4], ++ cmd[2 + i * 4], cmd[3 + i * 4]); ++ } + -+ if (DEBUGGER_EN(REG)) { -+ uint32_t *p; ++ spin_lock_irqsave(&scheduler->irq_lock, flags); + -+ rga2_dump_read_back_sys_reg(scheduler); -+ rga2_dump_read_back_csc_reg(scheduler); ++ /* sys_reg init */ ++ sys_ctrl = m_RGA2_SYS_CTRL_AUTO_CKG; + -+ 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]); ++ /* RV1106 need disables these optimizations */ ++ if (scheduler->data == &rga2e_1106_data) ++ sys_ctrl |= m_RGA2_SYS_CTRL_DST_WR_OPT_DIS | m_RGA2_SRC0_YUV420SP_RD_OPT_DIS; ++ ++ if (rga_hw_has_issue(scheduler, RGA_HW_ISSUE_DIS_AUTO_RST)) { ++ /* disable all_finish & cur_finish intr_en */ ++ rga_write(0, RGA2_INT, scheduler); ++ rga_write(0, RGA2_CMD_REG_BASE + RGA2_MODE_CTRL_OFFSET, scheduler); ++ /* replace auto_rst */ ++ rga2_soft_reset(scheduler); ++ } else { ++ sys_ctrl |= m_RGA2_SYS_CTRL_AUTO_RST; + } + ++ 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); ++ + /* 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(job->cmd_buf->dma_addr, 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); ++ rga_write(rga_read(RGA2_CMD_CTRL, scheduler) | 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(cmd[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)); ++ spin_unlock_irqrestore(&scheduler->irq_lock, flags); + + if (DEBUGGER_EN(TIME)) -+ pr_info("request[%d], set register cost time %lld us\n", -+ job->request_id, ktime_us_delta(now, job->timestamp)); ++ rga_job_log(job, "set register cost time %lld us\n", ++ ktime_us_delta(ktime_get(), now)); + -+ job->hw_running_time = now; -+ job->hw_recoder_time = now; ++ job->timestamp.hw_execute = now; ++ job->timestamp.hw_recode = now; ++ job->session->last_active = now; + + if (DEBUGGER_EN(REG)) -+ rga2_dump_read_back_reg(scheduler); ++ rga2_dump_read_back_reg(job, scheduler); + + return 0; +} @@ -1900387,7 +1901246,7 @@ index 000000000..d2e379fa9 + u32 reg_version; + + if (!scheduler) { -+ pr_err("scheduler is null\n"); ++ rga_err("scheduler is null\n"); + return -EINVAL; + } + @@ -1900416,51 +1901275,83 @@ index 000000000..d2e379fa9 +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); ++ if (scheduler->data->version == 0) { ++ 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); ++ } else { ++ job->rga_command_base.osd_info.cur_flags0 = ++ rga_read(RGA2_FIXED_OSD_CUR_FLAGS0, scheduler); ++ job->rga_command_base.osd_info.cur_flags1 = ++ rga_read(RGA2_FIXED_OSD_CUR_FLAGS1, scheduler); ++ } + } + + return 0; +} + ++static int rga2_read_status(struct rga_job *job, struct rga_scheduler_t *scheduler) ++{ ++ job->intr_status = rga_read(RGA2_INT, scheduler); ++ job->hw_status = rga_read(RGA2_STATUS2, scheduler); ++ job->cmd_status = rga_read(RGA2_STATUS1, scheduler); ++ job->work_cycle = rga_read(RGA2_WORK_CNT, scheduler); ++ ++ return 0; ++} ++ ++static void rga2_clear_intr(struct rga_scheduler_t *scheduler) ++{ ++ 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); ++} ++ +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) ++ if (job == NULL) { ++ rga2_clear_intr(scheduler); ++ rga_err("core[%d], invalid job, INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x], WORK_CYCLE[0x%x(%d)]\n", ++ scheduler->core, rga_read(RGA2_INT, scheduler), ++ rga_read(RGA2_STATUS2, scheduler), rga_read(RGA2_STATUS1, scheduler), ++ rga_read(RGA2_WORK_CNT, scheduler), rga_read(RGA2_WORK_CNT, scheduler)); ++ + return IRQ_HANDLED; ++ } ++ ++ if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) { ++ rga2_clear_intr(scheduler); + -+ 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); ++ scheduler->ops->read_status(job, 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); ++ rga_job_log(job, "irq handler, INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x], WORK_CYCLE[0x%x(%d)]\n", ++ job->intr_status, job->hw_status, job->cmd_status, ++ job->work_cycle, job->work_cycle); + -+ 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) { ++ 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); ++ rga_job_err(job, "irq handler err! INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x], WORK_CYCLE[0x%x(%d)]\n", ++ job->intr_status, job->hw_status, job->cmd_status, ++ job->work_cycle, job->work_cycle); ++ + scheduler->ops->soft_reset(scheduler); ++ } else 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); + } + -+ /*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); ++ rga2_clear_intr(scheduler); + + return IRQ_WAKE_THREAD; +} @@ -1900468,27 +1901359,33 @@ index 000000000..d2e379fa9 +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_job_log(job, "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"); ++ rga_job_err(job, "RGA current status: rpp error!\n"); + if (job->hw_status & m_RGA2_STATUS2_BUS_ERROR) -+ pr_err("RGA current status: bus error!\n"); ++ rga_job_err(job, "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"); ++ rga_job_err(job, "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"); ++ rga_job_err(job, "mmu failed, please check size of the buffer or whether the buffer has been freed.\n"); ++ job->ret = -EACCES; ++ } else if (job->intr_status & m_RGA2_INT_SCL_ERROR_INTR) { ++ rga_job_err(job, "scale failed, check scale config or formula.\n"); ++ job->ret = -EACCES; ++ } else if (job->intr_status & m_RGA2_INT_FBCIN_DEC_ERROR) { ++ rga_job_err(job, "FBC decode failed, please check if the source data is FBC data.\n"); + job->ret = -EACCES; + } + + if (job->ret == 0) { -+ pr_err("rga intr error[0x%x]!\n", job->intr_status); ++ rga_job_err(job, "rga intr error[0x%x]!\n", job->intr_status); + job->ret = -EFAULT; + } + } @@ -1900500,17 +1901397,18 @@ index 000000000..d2e379fa9 + .get_version = rga2_get_version, + .set_reg = rga2_set_reg, + .init_reg = rga2_init_reg, -+ .soft_reset = rga2_soft_reset, ++ .soft_reset = rga2_soft_reset_print, + .read_back_reg = rga2_read_back_reg, ++ .read_status = rga2_read_status, + .irq = rga2_irq, + .isr_thread = rga2_isr_thread, +}; diff --git a/drivers/video/rockchip/rga3/rga3_reg_info.c b/drivers/video/rockchip/rga3/rga3_reg_info.c new file mode 100644 -index 000000000..4091892e0 +index 000000000..c0ce4a3ff --- /dev/null +++ b/drivers/video/rockchip/rga3/rga3_reg_info.c -@@ -0,0 +1,2191 @@ +@@ -0,0 +1,2269 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1900518,8 +1901416,6 @@ index 000000000..4091892e0 + * Author: Huang Lee + */ + -+#define pr_fmt(fmt) "rga3_reg: " fmt -+ +#include "rga3_reg_info.h" +#include "rga_dma_buf.h" +#include "rga_iommu.h" @@ -1900658,11 +1901554,13 @@ index 000000000..4091892e0 + + switch (msg->win0.format) { + case RGA_FORMAT_RGBA_8888: ++ case RGA_FORMAT_RGBX_8888: + win_format = 0x8; + pixel_width = 4; + win_interleaved = 2; + break; + case RGA_FORMAT_BGRA_8888: ++ case RGA_FORMAT_BGRX_8888: + win_format = 0x6; + pixel_width = 4; + win_interleaved = 2; @@ -1901041,11 +1901939,13 @@ index 000000000..4091892e0 + + switch (msg->win1.format) { + case RGA_FORMAT_RGBA_8888: ++ case RGA_FORMAT_RGBX_8888: + win_format = 0x8; + pixel_width = 4; + win_interleaved = 2; + break; + case RGA_FORMAT_BGRA_8888: ++ case RGA_FORMAT_BGRX_8888: + win_format = 0x6; + pixel_width = 4; + win_interleaved = 2; @@ -1901332,12 +1902232,14 @@ index 000000000..4091892e0 + + switch (msg->wr.format) { + case RGA_FORMAT_RGBA_8888: ++ case RGA_FORMAT_RGBX_8888: + wr_format = 0x6; + pixel_width = 4; + wr_interleaved = 2; + wr_pix_swp = 1; + break; + case RGA_FORMAT_BGRA_8888: ++ case RGA_FORMAT_BGRX_8888: + wr_format = 0x6; + pixel_width = 4; + wr_interleaved = 2; @@ -1901759,21 +1902661,25 @@ index 000000000..4091892e0 + break; + } + -+ if (!config->enable && msg->abb_alpha_pass) { ++ if (!config->enable) { + /* + * enabled by default bot_blend_m1 && bot_alpha_cal_m1 for src channel(win0) + * In ABB mode, the number will be fetched according to 16*16, so it needs to + * be enabled top_blend_m1 && top_alpha_cal_m1 for dst channel(wr). + */ -+ top_color_ctrl.bits.color_mode = RGA_ALPHA_PRE_MULTIPLIED; ++ if (msg->fg_alpha_pass) { ++ top_color_ctrl.bits.color_mode = RGA_ALPHA_PRE_MULTIPLIED; + -+ top_alpha_ctrl.bits.blend_mode = RGA_ALPHA_PER_PIXEL; -+ top_alpha_ctrl.bits.alpha_cal_mode = RGA_ALPHA_NO_SATURATION; ++ top_alpha_ctrl.bits.blend_mode = RGA_ALPHA_PER_PIXEL; ++ top_alpha_ctrl.bits.alpha_cal_mode = RGA_ALPHA_NO_SATURATION; ++ } + -+ bottom_color_ctrl.bits.color_mode = RGA_ALPHA_PRE_MULTIPLIED; ++ if (msg->bg_alpha_pass) { ++ bottom_color_ctrl.bits.color_mode = RGA_ALPHA_PRE_MULTIPLIED; + -+ bottom_alpha_ctrl.bits.blend_mode = RGA_ALPHA_PER_PIXEL; -+ bottom_alpha_ctrl.bits.alpha_cal_mode = RGA_ALPHA_NO_SATURATION; ++ bottom_alpha_ctrl.bits.blend_mode = RGA_ALPHA_PER_PIXEL; ++ bottom_alpha_ctrl.bits.alpha_cal_mode = RGA_ALPHA_NO_SATURATION; ++ } + } else { + top_color_ctrl.bits.color_mode = + config->fg_pre_multiplied ? @@ -1901851,7 +1902757,7 @@ index 000000000..4091892e0 + RGA3_set_reg_wr_info(base, msg); + break; + default: -+ pr_err("error msg render mode %d\n", msg->render_mode); ++ rga_err("error msg render mode %d\n", msg->render_mode); + break; + } + @@ -1901982,18 +1902888,6 @@ index 000000000..4091892e0 + break; + } + -+ req->win0_a_global_val = req_rga->alpha_global_value; -+ req->win1_a_global_val = req_rga->alpha_global_value; -+ -+ /* fixup yuv/rgb convert to rgba missing alpha channel */ -+ if (!(req_rga->alpha_rop_flag & 1)) { -+ if (!rga_is_alpha_format(req_rga->src.format) && -+ rga_is_alpha_format(req_rga->dst.format)) { -+ req->alpha_config.fg_global_alpha_value = 0xff; -+ req->alpha_config.bg_global_alpha_value = 0xff; -+ } -+ } -+ + /* simple win can not support dst offset */ + if ((!((req_rga->alpha_rop_flag) & 1)) && + (req_rga->dst.x_offset == 0 && req_rga->dst.y_offset == 0) && @@ -1902004,14 +1902898,6 @@ index 000000000..4091892e0 + * dst => wr + */ + -+ /* -+ * enabled by default bot_blend_m1 && bot_alpha_cal_m1 for src channel(win0) -+ * In ABB mode, the number will be fetched according to 16*16, so it needs to -+ * be enabled top_blend_m1 && top_alpha_cal_m1 for dst channel(wr). -+ */ -+ if (rga_is_alpha_format(req_rga->src.format)) -+ req->abb_alpha_pass = true; -+ + set_win_info(&req->win0, &req_rga->src); + + /* enable win0 rotate */ @@ -1902034,14 +1902920,6 @@ index 000000000..4091892e0 + * dst => wr + */ + -+ /* -+ * enabled by default top_blend_m1 && top_alpha_cal_m1 for src channel(win1) -+ * In ABB mode, the number will be fetched according to 16*16, so it needs to -+ * be enabled bot_blend_m1 && bot_alpha_cal_m1 for src1/dst channel(win0). -+ */ -+ if (rga_is_alpha_format(req_rga->src.format)) -+ req->abb_alpha_pass = true; -+ + if (req_rga->pat.yrgb_addr != 0) { + if (req_rga->src.yrgb_addr == req_rga->dst.yrgb_addr) { + /* Convert ABC mode to ABB mode. */ @@ -1902175,12 +1903053,37 @@ index 000000000..4091892e0 + req->alpha_config.bg_global_alpha_value = 0xff; + } + } else { -+ req->alpha_config.fg_global_alpha_value = 0xff; ++ req->alpha_config.bg_global_alpha_value = 0xff; + req->alpha_config.bg_global_alpha_value = 0xff; + } + + req->alpha_config.mode = req_rga->PD_mode; + } ++ } else { ++ /* ++ * top/bottom Layer binding: ++ * top/fg => win1/wr ++ * bottom/bg => win0 ++ * The alpha channel of RGA3 is controlled by the overlap register, choosing ++ * to use globalAlpha or perpixelAlpha. ++ * When the input/output format does not have alpha, need to use globalAlpha to ++ * control the output alpha to '0xff'. ++ */ ++ if (req->win1.enable) { ++ req->bg_alpha_pass = true; ++ ++ if (rga_is_alpha_format(req->win1.format) && ++ rga_is_alpha_format(req->wr.format)) ++ req->fg_alpha_pass = true; ++ else ++ req->alpha_config.fg_global_alpha_value = 0xff; ++ } else { ++ if (rga_is_alpha_format(req->win0.format) && ++ rga_is_alpha_format(req->wr.format)) ++ req->bg_alpha_pass = true; ++ else ++ req->alpha_config.bg_global_alpha_value = 0xff; ++ } + } + + /* yuv to rgb */ @@ -1902256,44 +1903159,85 @@ index 000000000..4091892e0 + } + + if (i == RGA_RESET_TIMEOUT) -+ pr_err("RGA3 core[%d] soft reset timeout. SYS_CTRL[0x%x], RO_SRST[0x%x]\n", -+ scheduler->core, rga_read(RGA3_SYS_CTRL, scheduler), -+ rga_read(RGA3_RO_SRST, scheduler)); ++ rga_err("%s[%#x] soft reset timeout. SYS_CTRL[0x%x], RO_SRST[0x%x]\n", ++ rga_get_core_name(scheduler->core), scheduler->core, ++ rga_read(RGA3_SYS_CTRL, scheduler), ++ rga_read(RGA3_RO_SRST, scheduler)); + else -+ pr_info("RGA3 core[%d] soft reset complete.\n", scheduler->core); ++ rga_log("%s[%#x] soft reset complete.\n", ++ rga_get_core_name(scheduler->core), scheduler->core); +} + -+static int rga3_scale_check(const struct rga3_req *req) ++static int rga3_scale_check(struct rga_job *job, const struct rga3_req *req) +{ + u32 win0_saw, win0_sah, win0_daw, win0_dah; + u32 win1_saw, win1_sah, win1_daw, win1_dah; + -+ win0_saw = req->win0.src_act_w; -+ win0_sah = req->win0.src_act_h; -+ win0_daw = req->win0.dst_act_w; -+ win0_dah = req->win0.dst_act_h; ++ if (req->rotate_mode & RGA3_ROT_BIT_ROT_90) { ++ if (req->win1.yrgb_addr != 0) { ++ /* ABB */ ++ if (req->win0.yrgb_addr == req->wr.yrgb_addr) { ++ /* win0 do not need rotate, but net equal to wr */ ++ win0_saw = req->win0.src_act_h; ++ win0_sah = req->win0.src_act_w; ++ win0_daw = req->win0.dst_act_h; ++ win0_dah = req->win0.dst_act_w; ++ ++ win1_saw = req->win1.src_act_w; ++ win1_sah = req->win1.src_act_h; ++ win1_daw = req->win1.dst_act_h; ++ win1_dah = req->win1.dst_act_w; ++ } else { ++ win0_saw = req->win0.src_act_w; ++ win0_sah = req->win0.src_act_h; ++ win0_daw = req->win0.dst_act_w; ++ win0_dah = req->win0.dst_act_h; ++ ++ win1_saw = req->win1.src_act_w; ++ win1_sah = req->win1.src_act_h; ++ win1_daw = req->win1.dst_act_w; ++ win1_dah = req->win1.dst_act_h; ++ } ++ } else { ++ win0_saw = req->win0.src_act_w; ++ win0_sah = req->win0.src_act_h; ++ win0_daw = req->win0.dst_act_h; ++ win0_dah = req->win0.dst_act_w; ++ } ++ } else { ++ win0_saw = req->win0.src_act_w; ++ win0_sah = req->win0.src_act_h; ++ win0_daw = req->win0.dst_act_w; ++ win0_dah = req->win0.dst_act_h; ++ ++ if (req->win1.yrgb_addr != 0) { ++ win1_saw = req->win1.src_act_w; ++ win1_sah = req->win1.src_act_h; ++ win1_daw = req->win1.dst_act_w; ++ win1_dah = req->win1.dst_act_h; ++ } ++ } + + if (((win0_saw >> 3) > win0_daw) || ((win0_sah >> 3) > win0_dah)) { -+ pr_info("win0 unsupported to scaling less than 1/8 times.\n"); ++ rga_job_log(job, "win0 unsupported to scaling less than 1/8 times. src[%d, %d], dst[%d, %d]\n", ++ win0_saw, win0_sah, win0_daw, win0_dah); + return -EINVAL; + } + if (((win0_daw >> 3) > win0_saw) || ((win0_dah >> 3) > win0_sah)) { -+ pr_info("win0 unsupported to scaling more than 8 times.\n"); ++ rga_job_log(job, "win0 unsupported to scaling more than 8 times. src[%d, %d], dst[%d, %d]\n", ++ win0_saw, win0_sah, win0_daw, win0_dah); + return -EINVAL; + } + + if (req->win1.yrgb_addr != 0) { -+ win1_saw = req->win1.src_act_w; -+ win1_sah = req->win1.src_act_h; -+ win1_daw = req->win1.dst_act_w; -+ win1_dah = req->win1.dst_act_h; -+ + if (((win1_saw >> 3) > win1_daw) || ((win1_sah >> 3) > win1_dah)) { -+ pr_info("win1 unsupported to scaling less than 1/8 times.\n"); ++ rga_job_log(job, "win1 unsupported to scaling less than 1/8 times. src[%d, %d], dst[%d, %d]\n", ++ win1_saw, win1_sah, win1_daw, win1_dah); + return -EINVAL; + } + if (((win1_daw >> 3) > win1_saw) || ((win1_dah >> 3) > win1_sah)) { -+ pr_info("win1 unsupported to scaling more than 8 times.\n"); ++ rga_job_log(job, "win1 unsupported to scaling more than 8 times. src[%d, %d], dst[%d, %d]\n", ++ win1_saw, win1_sah, win1_daw, win1_dah); + return -EINVAL; + } + } @@ -1902301,7 +1903245,8 @@ index 000000000..4091892e0 + return 0; +} + -+static int rga3_check_param(const struct rga_hw_data *data, const struct rga3_req *req) ++static int rga3_check_param(struct rga_job *job, const struct rga_hw_data *data, ++ const struct rga3_req *req) +{ + if (unlikely(rga_hw_out_of_range(&(data->input_range), + req->win0.src_act_w, req->win0.src_act_h) || @@ -1902310,32 +1903255,32 @@ index 000000000..4091892e0 + rga_hw_out_of_range(&(data->input_range), + req->win0.src_act_w + req->win0.x_offset, + req->win0.src_act_h + req->win0.y_offset))) { -+ pr_err("invalid win0, src[w,h] = [%d, %d], dst[w,h] = [%d, %d], off[x,y] = [%d,%d]\n", -+ req->win0.src_act_w, req->win0.src_act_h, -+ req->win0.dst_act_w, req->win0.dst_act_h, -+ req->win0.x_offset, req->win0.y_offset); ++ rga_job_err(job, "invalid win0, src[w,h] = [%d, %d], dst[w,h] = [%d, %d], off[x,y] = [%d,%d]\n", ++ req->win0.src_act_w, req->win0.src_act_h, ++ req->win0.dst_act_w, req->win0.dst_act_h, ++ req->win0.x_offset, req->win0.y_offset); + return -EINVAL; + } + + if (unlikely(req->win0.vir_w * rga_get_pixel_stride_from_format(req->win0.format) > + data->max_byte_stride * 8)) { -+ pr_err("invalid win0 stride, stride = %d, pixel_stride = %d, max_byte_stride = %d\n", -+ req->win0.vir_w, rga_get_pixel_stride_from_format(req->win0.format), -+ data->max_byte_stride); ++ rga_job_err(job, "invalid win0 stride, stride = %d, pixel_stride = %d, max_byte_stride = %d\n", ++ req->win0.vir_w, rga_get_pixel_stride_from_format(req->win0.format), ++ data->max_byte_stride); + return -EINVAL; + } + + if (unlikely(rga_hw_out_of_range(&(data->output_range), + req->wr.dst_act_w, req->wr.dst_act_h))) { -+ pr_err("invalid wr, [w,h] = [%d, %d]\n", req->wr.dst_act_w, req->wr.dst_act_h); ++ rga_job_err(job, "invalid wr, [w,h] = [%d, %d]\n", req->wr.dst_act_w, req->wr.dst_act_h); + return -EINVAL; + } + + if (unlikely(req->wr.vir_w * rga_get_pixel_stride_from_format(req->wr.format) > + data->max_byte_stride * 8)) { -+ pr_err("invalid wr stride, stride = %d, pixel_stride = %d, max_byte_stride = %d\n", -+ req->wr.vir_w, rga_get_pixel_stride_from_format(req->wr.format), -+ data->max_byte_stride); ++ rga_job_err(job, "invalid wr stride, stride = %d, pixel_stride = %d, max_byte_stride = %d\n", ++ req->wr.vir_w, rga_get_pixel_stride_from_format(req->wr.format), ++ data->max_byte_stride); + return -EINVAL; + } + @@ -1902347,18 +1903292,18 @@ index 000000000..4091892e0 + rga_hw_out_of_range(&(data->input_range), + req->win1.src_act_w + req->win1.x_offset, + req->win1.src_act_h + req->win1.y_offset))) { -+ pr_err("invalid win1, src[w,h] = [%d, %d], dst[w,h] = [%d, %d], off[x,y] = [%d,%d]\n", -+ req->win1.src_act_w, req->win1.src_act_h, -+ req->win1.dst_act_w, req->win1.dst_act_h, -+ req->win1.x_offset, req->win1.y_offset); ++ rga_job_err(job, "invalid win1, src[w,h] = [%d, %d], dst[w,h] = [%d, %d], off[x,y] = [%d,%d]\n", ++ req->win1.src_act_w, req->win1.src_act_h, ++ req->win1.dst_act_w, req->win1.dst_act_h, ++ req->win1.x_offset, req->win1.y_offset); + return -EINVAL; + } + + if (unlikely(req->win1.vir_w * rga_get_pixel_stride_from_format(req->win1.format) > + data->max_byte_stride * 8)) { -+ pr_err("invalid win1 stride, stride = %d, pixel_stride = %d, max_byte_stride = %d\n", -+ req->win1.vir_w, rga_get_pixel_stride_from_format(req->win1.format), -+ data->max_byte_stride); ++ rga_job_err(job, "invalid win1 stride, stride = %d, pixel_stride = %d, max_byte_stride = %d\n", ++ req->win1.vir_w, rga_get_pixel_stride_from_format(req->win1.format), ++ data->max_byte_stride); + return -EINVAL; + } + @@ -1902367,99 +1903312,95 @@ index 000000000..4091892e0 + /* check win0 dst size > win1 dst size */ + if (unlikely((req->win1.dst_act_w > req->win0.dst_act_w) || + (req->win1.dst_act_h > req->win0.dst_act_h))) { -+ pr_err("invalid output param win0[w,h] = [%d, %d], win1[w,h] = [%d, %d]\n", -+ req->win0.dst_act_w, req->win0.dst_act_h, -+ req->win1.dst_act_w, req->win1.dst_act_h); ++ rga_job_err(job, "invalid output param win0[w,h] = [%d, %d], win1[w,h] = [%d, %d]\n", ++ req->win0.dst_act_w, req->win0.dst_act_h, ++ req->win1.dst_act_w, req->win1.dst_act_h); + return -EINVAL; + } + } + } + -+ if (rga3_scale_check(req) < 0) ++ if (rga3_scale_check(job, req) < 0) + return -EINVAL; + + return 0; +} + -+static void print_debug_info(struct rga3_req *req) ++static void print_debug_info(struct rga_job *job, struct rga3_req *req) +{ -+ pr_info("render_mode:%s, bitblit_mode=%d, rotate_mode:%x\n", ++ rga_job_log(job, "render_mode:%s, bitblit_mode=%d, rotate_mode:%x\n", + rga_get_render_mode_str(req->render_mode), req->bitblt_mode, + req->rotate_mode); -+ pr_info("win0: y = %lx uv = %lx v = %lx src_w = %d src_h = %d\n", -+ req->win0.yrgb_addr, req->win0.uv_addr, req->win0.v_addr, -+ req->win0.src_act_w, req->win0.src_act_h); -+ pr_info("win0: vw = %d vh = %d xoff = %d yoff = %d format = %s\n", -+ req->win0.vir_w, req->win0.vir_h, -+ req->win0.x_offset, req->win0.y_offset, -+ rga_get_format_name(req->win0.format)); -+ pr_info("win0: dst_w = %d, dst_h = %d, rd_mode = %d\n", -+ req->win0.dst_act_w, req->win0.dst_act_h, req->win0.rd_mode); -+ pr_info("win0: rot_mode = %d, en = %d, compact = %d, endian = %d\n", -+ req->win0.rotate_mode, req->win0.enable, -+ req->win0.is_10b_compact, req->win0.is_10b_endian); ++ rga_job_log(job, "win0: y = %lx uv = %lx v = %lx src_w = %d src_h = %d\n", ++ req->win0.yrgb_addr, req->win0.uv_addr, req->win0.v_addr, ++ req->win0.src_act_w, req->win0.src_act_h); ++ rga_job_log(job, "win0: vw = %d vh = %d xoff = %d yoff = %d format = %s\n", ++ req->win0.vir_w, req->win0.vir_h, ++ req->win0.x_offset, req->win0.y_offset, ++ rga_get_format_name(req->win0.format)); ++ rga_job_log(job, "win0: dst_w = %d, dst_h = %d, rd_mode = %d\n", ++ req->win0.dst_act_w, req->win0.dst_act_h, req->win0.rd_mode); ++ rga_job_log(job, "win0: rot_mode = %d, en = %d, compact = %d, endian = %d\n", ++ req->win0.rotate_mode, req->win0.enable, ++ req->win0.is_10b_compact, req->win0.is_10b_endian); + + if (req->win1.yrgb_addr != 0 || req->win1.uv_addr != 0 + || req->win1.v_addr != 0) { -+ pr_info("win1: y = %lx uv = %lx v = %lx src_w = %d src_h = %d\n", -+ req->win1.yrgb_addr, req->win1.uv_addr, -+ req->win1.v_addr, req->win1.src_act_w, -+ req->win1.src_act_h); -+ pr_info("win1: vw = %d vh = %d xoff = %d yoff = %d format = %s\n", -+ req->win1.vir_w, req->win1.vir_h, -+ req->win1.x_offset, req->win1.y_offset, -+ rga_get_format_name(req->win1.format)); -+ pr_info("win1: dst_w = %d, dst_h = %d, rd_mode = %d\n", -+ req->win1.dst_act_w, req->win1.dst_act_h, -+ req->win1.rd_mode); -+ pr_info("win1: rot_mode = %d, en = %d, compact = %d, endian = %d\n", -+ req->win1.rotate_mode, req->win1.enable, -+ req->win1.is_10b_compact, req->win1.is_10b_endian); -+ } -+ -+ pr_info("wr: y = %lx uv = %lx v = %lx vw = %d vh = %d\n", -+ req->wr.yrgb_addr, req->wr.uv_addr, req->wr.v_addr, -+ req->wr.vir_w, req->wr.vir_h); -+ pr_info("wr: ovlp_xoff = %d ovlp_yoff = %d format = %s rdmode = %d\n", -+ req->wr.x_offset, req->wr.y_offset, -+ rga_get_format_name(req->wr.format), req->wr.rd_mode); -+ -+ pr_info("mmu: win0 = %.2x win1 = %.2x wr = %.2x\n", ++ rga_job_log(job, "win1: y = %lx uv = %lx v = %lx src_w = %d src_h = %d\n", ++ req->win1.yrgb_addr, req->win1.uv_addr, ++ req->win1.v_addr, req->win1.src_act_w, ++ req->win1.src_act_h); ++ rga_job_log(job, "win1: vw = %d vh = %d xoff = %d yoff = %d format = %s\n", ++ req->win1.vir_w, req->win1.vir_h, ++ req->win1.x_offset, req->win1.y_offset, ++ rga_get_format_name(req->win1.format)); ++ rga_job_log(job, "win1: dst_w = %d, dst_h = %d, rd_mode = %d\n", ++ req->win1.dst_act_w, req->win1.dst_act_h, ++ req->win1.rd_mode); ++ rga_job_log(job, "win1: rot_mode = %d, en = %d, compact = %d, endian = %d\n", ++ req->win1.rotate_mode, req->win1.enable, ++ req->win1.is_10b_compact, req->win1.is_10b_endian); ++ } ++ ++ rga_job_log(job, "wr: y = %lx uv = %lx v = %lx vw = %d vh = %d\n", ++ req->wr.yrgb_addr, req->wr.uv_addr, req->wr.v_addr, ++ req->wr.vir_w, req->wr.vir_h); ++ rga_job_log(job, "wr: ovlp_xoff = %d ovlp_yoff = %d format = %s rdmode = %d\n", ++ req->wr.x_offset, req->wr.y_offset, ++ rga_get_format_name(req->wr.format), req->wr.rd_mode); ++ ++ rga_job_log(job, "mmu: win0 = %.2x win1 = %.2x wr = %.2x\n", + req->mmu_info.src0_mmu_flag, req->mmu_info.src1_mmu_flag, + req->mmu_info.dst_mmu_flag); -+ pr_info("alpha: flag %x mode=%s\n", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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", ++ rga_job_log(job, "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); ++ rga_job_log(job, "yuv2rgb mode is %x\n", req->yuv2rgb_mode); +} + -+static int rga3_align_check(struct rga3_req *req) ++static int rga3_align_check(struct rga_job *job, struct rga3_req *req) +{ + if (rga_is_yuv10bit_format(req->win0.format)) -+ if ((req->win0.vir_w % 64) || (req->win0.x_offset % 4) || -+ (req->win0.src_act_w % 4) || (req->win0.y_offset % 4) || -+ (req->win0.src_act_h % 4) || (req->win0.vir_h % 2)) -+ pr_info("yuv10bit err win0 wstride is not align\n"); ++ if ((req->win0.x_offset % 4) || (req->win0.y_offset % 2) || ++ (req->win0.src_act_w % 4) || (req->win0.src_act_h % 2)) ++ rga_job_log(job, "yuv10bit err win0 wstride is not align\n"); + if (rga_is_yuv10bit_format(req->win1.format)) -+ if ((req->win1.vir_w % 64) || (req->win1.x_offset % 4) || -+ (req->win1.src_act_w % 4) || (req->win1.y_offset % 4) || -+ (req->win1.src_act_h % 4) || (req->win1.vir_h % 2)) -+ pr_info("yuv10bit err win1 wstride is not align\n"); ++ if ((req->win1.x_offset % 4) || (req->win1.y_offset % 2) || ++ (req->win1.src_act_w % 4) || (req->win1.src_act_h % 2)) ++ rga_job_log(job, "yuv10bit err win1 wstride is not align\n"); + if (rga_is_yuv8bit_format(req->win0.format)) -+ if ((req->win0.vir_w % 16) || (req->win0.x_offset % 2) || -+ (req->win0.src_act_w % 2) || (req->win0.y_offset % 2) || -+ (req->win0.src_act_h % 2) || (req->win0.vir_h % 2)) -+ pr_info("yuv8bit err win0 wstride is not align\n"); ++ if ((req->win0.x_offset % 2) || (req->win0.y_offset % 2) || ++ (req->win0.src_act_w % 2) || (req->win0.src_act_h % 2)) ++ rga_job_log(job, "yuv8bit err win0 wstride is not align\n"); + if (rga_is_yuv8bit_format(req->win1.format)) -+ if ((req->win1.vir_w % 16) || (req->win1.x_offset % 2) || -+ (req->win1.src_act_w % 2) || (req->win1.y_offset % 2) || -+ (req->win1.src_act_h % 2) || (req->win1.vir_h % 2)) -+ pr_info("yuv8bit err win1 wstride is not align\n"); ++ if ((req->win1.x_offset % 2) || (req->win1.y_offset % 2) || ++ (req->win1.src_act_w % 2) || (req->win1.src_act_h % 2)) ++ rga_job_log(job, "yuv8bit err win1 wstride is not align\n"); + return 0; +} + @@ -1902472,7 +1903413,7 @@ index 000000000..4091892e0 + + scheduler = job->scheduler; + if (unlikely(scheduler == NULL)) { -+ pr_err("failed to get scheduler, %s(%d)\n", __func__, __LINE__); ++ rga_job_err(job, "failed to get scheduler, %s(%d)\n", __func__, __LINE__); + return -EINVAL; + } + @@ -1902480,32 +1903421,53 @@ index 000000000..4091892e0 + + rga_cmd_to_rga3_cmd(&job->rga_command_base, &req); + ++ /* for debug */ ++ if (DEBUGGER_EN(MSG)) ++ print_debug_info(job, &req); ++ + /* check value if legal */ -+ ret = rga3_check_param(scheduler->data, &req); ++ ret = rga3_check_param(job, scheduler->data, &req); + if (ret == -EINVAL) { -+ pr_err("req argument is inval\n"); ++ rga_job_err(job, "req argument is inval\n"); + return ret; + } + -+ rga3_align_check(&req); -+ -+ /* for debug */ -+ if (DEBUGGER_EN(MSG)) -+ print_debug_info(&req); ++ rga3_align_check(job, &req); + -+ if (rga3_gen_reg_info((uint8_t *) job->cmd_reg, &req) == -1) { -+ pr_err("RKA: gen reg info error\n"); ++ if (rga3_gen_reg_info((uint8_t *) job->cmd_buf->vaddr, &req) == -1) { ++ rga_job_err(job, "RKA: gen reg info error\n"); + return -EINVAL; + } + + if (DEBUGGER_EN(TIME)) -+ pr_info("request[%d], generate register cost time %lld us\n", -+ job->request_id, ktime_us_delta(ktime_get(), timestamp)); ++ rga_job_log(job, "generate register cost time %lld us\n", ++ ktime_us_delta(ktime_get(), timestamp)); + + return ret; +} + -+static void rga3_dump_read_back_reg(struct rga_scheduler_t *scheduler) ++static void rga3_dump_read_back_sys_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) ++{ ++ int i; ++ unsigned long flags; ++ uint32_t sys_reg[20] = {0}; ++ ++ spin_lock_irqsave(&scheduler->irq_lock, flags); ++ ++ for (i = 0; i < 20; i++) ++ sys_reg[i] = rga_read(RGA3_SYS_REG_BASE + i * 4, scheduler); ++ ++ spin_unlock_irqrestore(&scheduler->irq_lock, flags); ++ ++ rga_job_log(job, "SYS_READ_BACK_REG\n"); ++ for (i = 0; i < 5; i++) ++ rga_job_log(job, "0x%04x : %.8x %.8x %.8x %.8x\n", ++ RGA3_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 rga3_dump_read_back_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) +{ + int i; + unsigned long flags; @@ -1902514,13 +1903476,14 @@ index 000000000..4091892e0 + spin_lock_irqsave(&scheduler->irq_lock, flags); + + for (i = 0; i < 48; i++) -+ cmd_reg[i] = rga_read(0x100 + i * 4, scheduler); ++ cmd_reg[i] = rga_read(RGA3_CMD_REG_BASE + i * 4, scheduler); + + spin_unlock_irqrestore(&scheduler->irq_lock, flags); + -+ pr_info("CMD_READ_BACK_REG\n"); ++ rga_job_log(job, "CMD_READ_BACK_REG\n"); + for (i = 0; i < 12; i++) -+ pr_info("i = %x : %.8x %.8x %.8x %.8x\n", i, ++ rga_job_log(job, "0x%04x : %.8x %.8x %.8x %.8x\n", ++ RGA3_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]); +} @@ -1902530,8 +1903493,11 @@ index 000000000..4091892e0 + int i; + bool master_mode_en; + uint32_t sys_ctrl; ++ uint32_t *cmd; + ktime_t now = ktime_get(); + ++ cmd = job->cmd_buf->vaddr; ++ + /* + * Currently there is no iova allocated for storing cmd for the IOMMU device, + * so the iommu device needs to use the slave mode. @@ -1902542,14 +1903508,14 @@ index 000000000..4091892e0 + master_mode_en = false; + + if (DEBUGGER_EN(REG)) { -+ uint32_t *p; ++ rga3_dump_read_back_sys_reg(job, scheduler); + -+ p = job->cmd_reg; -+ pr_info("CMD_REG\n"); ++ rga_job_log(job, "CMD_REG\n"); + for (i = 0; i < 12; 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]); ++ rga_job_log(job, "0x%04x : %.8x %.8x %.8x %.8x\n", ++ RGA3_CMD_REG_BASE + i * 0x10, ++ cmd[0 + i * 4], cmd[1 + i * 4], ++ cmd[2 + i * 4], cmd[3 + i * 4]); + } + + /* All CMD finish int */ @@ -1902560,10 +1903526,7 @@ index 000000000..4091892e0 + /* master mode */ + sys_ctrl = s_RGA3_SYS_CTRL_CMD_MODE(1); + -+ /* cmd buffer flush cache to ddr */ -+ rga_dma_sync_flush_range(&job->cmd_reg[0], &job->cmd_reg[50], scheduler); -+ -+ rga_write(virt_to_phys(job->cmd_reg), RGA3_CMD_ADDR, scheduler); ++ rga_write(job->cmd_buf->dma_addr, RGA3_CMD_ADDR, scheduler); + rga_write(sys_ctrl, RGA3_SYS_CTRL, scheduler); + rga_write(m_RGA3_CMD_CTRL_CMD_LINE_ST_P, RGA3_CMD_CTRL, scheduler); + } else { @@ -1902571,31 +1903534,23 @@ index 000000000..4091892e0 + sys_ctrl = s_RGA3_SYS_CTRL_CMD_MODE(0) | m_RGA3_SYS_CTRL_RGA_SART; + + for (i = 0; i <= 50; i++) -+ rga_write(job->cmd_reg[i], 0x100 + i * 4, scheduler); ++ rga_write(cmd[i], 0x100 + i * 4, scheduler); + + rga_write(sys_ctrl, RGA3_SYS_CTRL, scheduler); + } + -+ if (DEBUGGER_EN(REG)) { -+ pr_info("sys_ctrl = 0x%x, int_en = 0x%x, int_raw = 0x%x\n", -+ rga_read(RGA3_SYS_CTRL, scheduler), -+ rga_read(RGA3_INT_EN, scheduler), -+ rga_read(RGA3_INT_RAW, scheduler)); -+ -+ pr_info("hw_status = 0x%x, cmd_status = 0x%x\n", -+ rga_read(RGA3_STATUS0, scheduler), -+ rga_read(RGA3_CMD_STATE, scheduler)); -+ } -+ + if (DEBUGGER_EN(TIME)) -+ pr_info("request[%d], set register cost time %lld us\n", -+ job->request_id, ktime_us_delta(now, job->timestamp)); ++ rga_job_log(job, "set register cost time %lld us\n", ++ ktime_us_delta(ktime_get(), now)); + -+ job->hw_running_time = now; -+ job->hw_recoder_time = now; ++ job->timestamp.hw_execute = now; ++ job->timestamp.hw_recode = now; ++ job->session->last_active = now; + -+ if (DEBUGGER_EN(REG)) -+ rga3_dump_read_back_reg(scheduler); ++ if (DEBUGGER_EN(REG)) { ++ rga3_dump_read_back_sys_reg(job, scheduler); ++ rga3_dump_read_back_reg(job, scheduler); ++ } + + return 0; +} @@ -1902606,7 +1903561,7 @@ index 000000000..4091892e0 + u32 reg_version; + + if (!scheduler) { -+ pr_err("scheduler is null\n"); ++ rga_err("scheduler is null\n"); + return -EINVAL; + } + @@ -1902626,22 +1903581,44 @@ index 000000000..4091892e0 + return 0; +} + ++static int rga3_read_status(struct rga_job *job, struct rga_scheduler_t *scheduler) ++{ ++ job->intr_status = rga_read(RGA3_INT_RAW, scheduler); ++ job->hw_status = rga_read(RGA3_STATUS0, scheduler); ++ job->cmd_status = rga_read(RGA3_CMD_STATE, scheduler); ++ job->work_cycle = 0; ++ ++ return 0; ++} ++ ++static void rga3_clear_intr(struct rga_scheduler_t *scheduler) ++{ ++ rga_write(m_RGA3_INT_FRM_DONE | m_RGA3_INT_CMD_LINE_FINISH | m_RGA3_INT_ERROR_MASK, ++ RGA3_INT_CLR, scheduler); ++} ++ +static int rga3_irq(struct rga_scheduler_t *scheduler) +{ + struct rga_job *job = scheduler->running_job; + -+ if (job == NULL) ++ if (job == NULL) { ++ rga3_clear_intr(scheduler); ++ rga_err("core[%d], invalid job, INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x]\n", ++ scheduler->core, rga_read(RGA3_INT_RAW, scheduler), ++ rga_read(RGA3_STATUS0, scheduler), rga_read(RGA3_CMD_STATE, scheduler)); ++ + return IRQ_HANDLED; ++ } + -+ if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) ++ if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) { ++ rga3_clear_intr(scheduler); + return IRQ_WAKE_THREAD; ++ } + -+ job->intr_status = rga_read(RGA3_INT_RAW, scheduler); -+ job->hw_status = rga_read(RGA3_STATUS0, scheduler); -+ job->cmd_status = rga_read(RGA3_CMD_STATE, scheduler); ++ scheduler->ops->read_status(job, scheduler); + + if (DEBUGGER_EN(INT_FLAG)) -+ pr_info("irq handler, INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x]\n", ++ rga_job_log(job, "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_RGA3_INT_FRM_DONE | m_RGA3_INT_CMD_LINE_FINISH)) { @@ -1902649,14 +1903626,12 @@ index 000000000..4091892e0 + } else if (job->intr_status & m_RGA3_INT_ERROR_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", ++ rga_job_err(job, "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(m_RGA3_INT_FRM_DONE | m_RGA3_INT_CMD_LINE_FINISH | m_RGA3_INT_ERROR_MASK, -+ RGA3_INT_CLR, scheduler); ++ rga3_clear_intr(scheduler); + + return IRQ_WAKE_THREAD; +} @@ -1902664,28 +1903639,28 @@ index 000000000..4091892e0 +static int rga3_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_job_log(job, "isr thread, INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x]\n", + rga_read(RGA3_INT_RAW, scheduler), + rga_read(RGA3_STATUS0, scheduler), + rga_read(RGA3_CMD_STATE, scheduler)); + + if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) { + if (job->intr_status & m_RGA3_INT_RAG_MI_RD_BUS_ERR) { -+ pr_err("DMA read bus error, please check size of the input_buffer or whether the buffer has been freed.\n"); ++ rga_job_err(job, "DMA read bus error, please check size of the input_buffer or whether the buffer has been freed.\n"); + job->ret = -EFAULT; + } else if (job->intr_status & m_RGA3_INT_WIN0_FBCD_DEC_ERR) { -+ pr_err("win0 FBC decoder error, please check the fbc image of the source.\n"); ++ rga_job_err(job, "win0 FBC decoder error, please check the fbc image of the source.\n"); + job->ret = -EFAULT; + } else if (job->intr_status & m_RGA3_INT_WIN1_FBCD_DEC_ERR) { -+ pr_err("win1 FBC decoder error, please check the fbc image of the source.\n"); ++ rga_job_err(job, "win1 FBC decoder error, please check the fbc image of the source.\n"); + job->ret = -EFAULT; + } else if (job->intr_status & m_RGA3_INT_RGA_MI_WR_BUS_ERR) { -+ pr_err("wr buss error, please check size of the output_buffer or whether the buffer has been freed.\n"); ++ rga_job_err(job, "wr buss error, please check size of the output_buffer or whether the buffer has been freed.\n"); + job->ret = -EFAULT; + } + + if (job->ret == 0) { -+ pr_err("rga intr error[0x%x]!\n", job->intr_status); ++ rga_job_err(job, "rga intr error[0x%x]!\n", job->intr_status); + job->ret = -EFAULT; + } + } @@ -1902699,15 +1903674,16 @@ index 000000000..4091892e0 + .init_reg = rga3_init_reg, + .soft_reset = rga3_soft_reset, + .read_back_reg = NULL, ++ .read_status = rga3_read_status, + .irq = rga3_irq, + .isr_thread = rga3_isr_thread, +}; diff --git a/drivers/video/rockchip/rga3/rga_common.c b/drivers/video/rockchip/rga3/rga_common.c new file mode 100644 -index 000000000..80d4821fb +index 000000000..1563583dd --- /dev/null +++ b/drivers/video/rockchip/rga3/rga_common.c -@@ -0,0 +1,772 @@ +@@ -0,0 +1,951 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1902715,8 +1903691,6 @@ index 000000000..80d4821fb + * Author: Cerf Yu + */ + -+#define pr_fmt(fmt) "rga_common: " fmt -+ +#include "rga.h" +#include "rga_common.h" + @@ -1902753,6 +1903727,7 @@ index 000000000..80d4821fb +{ + switch (format) { + case RGA_FORMAT_Y4: ++ case RGA_FORMAT_Y8: + case RGA_FORMAT_YCbCr_400: + + case RGA_FORMAT_YCbCr_422_SP: @@ -1902777,6 +1903752,9 @@ index 000000000..80d4821fb + case RGA_FORMAT_YCrCb_420_SP_10B: + case RGA_FORMAT_YCbCr_422_SP_10B: + case RGA_FORMAT_YCrCb_422_SP_10B: ++ ++ case RGA_FORMAT_YCbCr_444_SP: ++ case RGA_FORMAT_YCrCb_444_SP: + return true; + default: + return false; @@ -1902798,6 +1903776,8 @@ index 000000000..80d4821fb + case RGA_FORMAT_ABGR_8888: + case RGA_FORMAT_ABGR_5551: + case RGA_FORMAT_ABGR_4444: ++ ++ case RGA_FORMAT_A8: + return true; + default: + return false; @@ -1902882,6 +1903862,7 @@ index 000000000..80d4821fb +{ + switch (format) { + case RGA_FORMAT_Y4: ++ case RGA_FORMAT_Y8: + case RGA_FORMAT_YCbCr_400: + + case RGA_FORMAT_YCbCr_422_SP: @@ -1902901,6 +1903882,9 @@ index 000000000..80d4821fb + case RGA_FORMAT_YUYV_420: + case RGA_FORMAT_UYVY_422: + case RGA_FORMAT_UYVY_420: ++ ++ case RGA_FORMAT_YCbCr_444_SP: ++ case RGA_FORMAT_YCrCb_444_SP: + return true; + default: + return false; @@ -1902936,6 +1903920,7 @@ index 000000000..80d4821fb + switch (format) { + case RGA_FORMAT_YCbCr_400: + case RGA_FORMAT_Y4: ++ case RGA_FORMAT_Y8: + return true; + default: + return false; @@ -1903023,7 +1904008,7 @@ index 000000000..80d4821fb + case RGA_FORMAT_YCbCr_400: + return "YCbCr400"; + case RGA_FORMAT_Y4: -+ return "y4"; ++ return "Y4"; + + case RGA_FORMAT_ARGB_8888: + return "ARGB8888"; @@ -1903045,6 +1904030,16 @@ index 000000000..80d4821fb + case RGA_FORMAT_RGBA_2BPP: + return "RGBA2BPP"; + ++ case RGA_FORMAT_A8: ++ return "alpha-8"; ++ case RGA_FORMAT_YCbCr_444_SP: ++ return "YCbCr444SP"; ++ case RGA_FORMAT_YCrCb_444_SP: ++ return "YCrCb444SP"; ++ ++ case RGA_FORMAT_Y8: ++ return "Y8"; ++ + default: + return "UNF"; + } @@ -1903067,6 +1904062,8 @@ index 000000000..80d4821fb + break; + case RGA_FORMAT_RGB_888: + case RGA_FORMAT_BGR_888: ++ case RGA_FORMAT_YCbCr_444_SP: ++ case RGA_FORMAT_YCrCb_444_SP: + bits = 24; + break; + case RGA_FORMAT_RGB_565: @@ -1903108,6 +1904105,8 @@ index 000000000..80d4821fb + break; + case RGA_FORMAT_YCbCr_400: + case RGA_FORMAT_BPP8: ++ case RGA_FORMAT_A8: ++ case RGA_FORMAT_Y8: + bits = 8; + break; + case RGA_FORMAT_Y4: @@ -1903121,7 +1904120,7 @@ index 000000000..80d4821fb + bits = 1; + break; + default: -+ pr_err("unknown format [0x%x]\n", format); ++ rga_err("unknown format [0x%x]\n", format); + return -1; + } + @@ -1903145,6 +1904144,8 @@ index 000000000..80d4821fb + break; + case RGA_FORMAT_RGB_888: + case RGA_FORMAT_BGR_888: ++ case RGA_FORMAT_YCbCr_444_SP: ++ case RGA_FORMAT_YCrCb_444_SP: + pixel_stride = 24; + break; + case RGA_FORMAT_RGB_565: @@ -1903178,6 +1904179,7 @@ index 000000000..80d4821fb + case RGA_FORMAT_BPP4: + case RGA_FORMAT_BPP8: + case RGA_FORMAT_YCbCr_400: ++ case RGA_FORMAT_A8: + case RGA_FORMAT_YCbCr_420_SP: + case RGA_FORMAT_YCbCr_420_P: + case RGA_FORMAT_YCrCb_420_SP: @@ -1903186,13 +1904188,14 @@ index 000000000..80d4821fb + case RGA_FORMAT_YCbCr_422_P: + case RGA_FORMAT_YCrCb_422_SP: + case RGA_FORMAT_YCrCb_422_P: ++ case RGA_FORMAT_Y8: + pixel_stride = 8; + break; + case RGA_FORMAT_Y4: + pixel_stride = 4; + break; + default: -+ pr_err("unknown format [0x%x]\n", format); ++ rga_err("unknown format [0x%x]\n", format); + return -1; + } + @@ -1903217,11 +1904220,47 @@ index 000000000..80d4821fb + } +} + -+const char *rga_get_rotate_mode_str(uint8_t mode) ++const char *rga_get_store_mode_str(uint32_t mode) +{ + switch (mode) { -+ case 0x0: -+ return "0"; ++ case RGA_RASTER_MODE: ++ return "raster"; ++ case RGA_FBC_MODE: ++ return "afbc16x16"; ++ case RGA_TILE_MODE: ++ return "tile8x8"; ++ case RGA_TILE4x4_MODE: ++ return "tile4x4"; ++ case RGA_RKFBC_MODE: ++ return "rkfbc64x4"; ++ case RGA_AFBC32x8_MODE: ++ return "afbc32x8"; ++ default: ++ return "unknown"; ++ } ++} ++ ++const char *rga_get_interp_str(uint8_t interp) ++{ ++ switch (interp) { ++ case RGA_INTERP_DEFAULT: ++ return "default"; ++ case RGA_INTERP_LINEAR: ++ return "bi-linear"; ++ case RGA_INTERP_BICUBIC: ++ return "bi-cubic"; ++ case RGA_INTERP_AVERAGE: ++ return "average_filter"; ++ default: ++ return "unknown"; ++ } ++} ++ ++const char *rga_get_rotate_mode_str(uint8_t mode) ++{ ++ switch (mode) { ++ case 0x0: ++ return "0"; + case 0x1: + return "90 degree"; + case 0x2: @@ -1903314,15 +1904353,33 @@ index 000000000..80d4821fb + } +} + ++const char *rga_get_dma_data_direction_str(enum dma_data_direction dir) ++{ ++ switch (dir) { ++ case DMA_BIDIRECTIONAL: ++ return "bidirectional"; ++ case DMA_TO_DEVICE: ++ return "to_device"; ++ case DMA_FROM_DEVICE: ++ return "from_device"; ++ case DMA_NONE: ++ return "none"; ++ default: ++ return "unknown"; ++ } ++} ++ +const char *rga_get_core_name(enum RGA_SCHEDULER_CORE core) +{ + switch (core) { -+ case RGA_SCHEDULER_RGA3_CORE0: ++ case RGA3_SCHEDULER_CORE0: + return "RGA3_core0"; -+ case RGA_SCHEDULER_RGA3_CORE1: ++ case RGA3_SCHEDULER_CORE1: + return "RGA3_core1"; -+ case RGA_SCHEDULER_RGA2_CORE0: ++ case RGA2_SCHEDULER_CORE0: + return "RGA2_core0"; ++ case RGA2_SCHEDULER_CORE1: ++ return "RGA2_core1"; + default: + return "unknown_core"; + } @@ -1903418,6 +1904475,12 @@ index 000000000..80d4821fb + yrgb = w * h * 2; + break; + /* YUV FORMAT */ ++ case RGA_FORMAT_YCbCr_444_SP: ++ case RGA_FORMAT_YCrCb_444_SP: ++ yrgb = w * h; ++ uv = w * h; ++ v = w * h; ++ break; + case RGA_FORMAT_YCbCr_422_SP: + case RGA_FORMAT_YCrCb_422_SP: + /* 10bit format stride is externally configured. */ @@ -1903447,13 +1904510,15 @@ index 000000000..80d4821fb + v = uv; + break; + case RGA_FORMAT_YCbCr_400: ++ case RGA_FORMAT_A8: ++ case RGA_FORMAT_Y8: + yrgb = w * h; + break; + case RGA_FORMAT_Y4: + yrgb = (w * h) >> 1; + break; + default: -+ pr_err("Unsuport format [0x%x]\n", format); ++ rga_err("Unsuport format [0x%x]\n", format); + return -EFAULT; + } + @@ -1903469,23 +1904534,113 @@ index 000000000..80d4821fb + +void rga_dump_memory_parm(struct rga_memory_parm *parm) +{ -+ pr_info("memory param: w = %d, h = %d, f = %s(0x%x), size = %d\n", ++ rga_log("memory param: w = %d, h = %d, f = %s(0x%x), size = %d\n", + parm->width, parm->height, rga_get_format_name(parm->format), + parm->format, parm->size); +} + +void rga_dump_external_buffer(struct rga_external_buffer *buffer) +{ -+ pr_info("external: memory = 0x%lx, type = %s\n", ++ rga_log("external: memory = 0x%lx, type = %s\n", + (unsigned long)buffer->memory, rga_get_memory_type_str(buffer->type)); + rga_dump_memory_parm(&buffer->memory_parm); +} ++ ++static void rga_dump_image_info(struct rga_request *request, const char *name, ++ struct rga_img_info_t *img, uint8_t handle_flag, int need_mmu) ++{ ++ if (handle_flag) { ++ if (img->uv_addr && img->v_addr) ++ rga_req_log(request, "%s: handle[y,uv,v] = [%ld(%#lx), %ld(%#lx), %ld(%#lx)], mode = %s\n", ++ name, ++ (unsigned long)img->yrgb_addr, (unsigned long)img->yrgb_addr, ++ (unsigned long)img->uv_addr, (unsigned long)img->uv_addr, ++ (unsigned long)img->v_addr, (unsigned long)img->v_addr, ++ rga_get_store_mode_str(img->rd_mode)); ++ else if (img->uv_addr) ++ rga_req_log(request, "%s: handle[y,uv] = [%ld(%#lx), %ld(%#lx)], mode = %s\n", ++ name, ++ (unsigned long)img->yrgb_addr, (unsigned long)img->yrgb_addr, ++ (unsigned long)img->uv_addr, (unsigned long)img->uv_addr, ++ rga_get_store_mode_str(img->rd_mode)); ++ else ++ rga_req_log(request, "%s: handle = %ld(%#lx), mode = %s\n", ++ name, ++ (unsigned long)img->yrgb_addr, (unsigned long)img->yrgb_addr, ++ rga_get_store_mode_str(img->rd_mode)); ++ } else { ++ if (img->yrgb_addr) ++ rga_req_log(request, "%s: fd = %ld(%#lx), mode = %s\n", ++ name, ++ (unsigned long)img->yrgb_addr, (unsigned long)img->yrgb_addr, ++ rga_get_store_mode_str(img->rd_mode)); ++ else if (img->uv_addr) ++ rga_req_log(request, "%s: %s = %#lx, mode = %s\n", ++ name, ++ need_mmu ? "virt_addr" : "phys_addr", (unsigned long)img->uv_addr, ++ rga_get_store_mode_str(img->rd_mode)); ++ } ++ ++ rga_req_log(request, "%s: rect[x,y,w,h] = [%d, %d, %d, %d], stride[w,h] = [%d, %d], format = %s(%#x)\n", ++ name, ++ img->x_offset, img->y_offset, img->act_w, img->act_h, img->vir_w, img->vir_h, ++ rga_get_format_name(img->format), img->format); ++} ++ ++void rga_dump_req(struct rga_request *request, struct rga_req *req) ++{ ++ rga_req_log(request, "render_mode = %d, bitblit_mode = %d, rotate_mode = %d\n", ++ req->render_mode, req->bsfilter_flag, ++ req->rotate_mode); ++ ++ rga_dump_image_info(request, "src", &req->src, req->handle_flag, ++ (req->mmu_info.mmu_flag >> 8) & 1); ++ if (req->pat.yrgb_addr != 0 || req->pat.uv_addr != 0 || req->pat.v_addr != 0) ++ rga_dump_image_info(request, "pat", &req->pat, req->handle_flag, ++ (req->mmu_info.mmu_flag >> 9) & 1); ++ rga_dump_image_info(request, "dst", &req->dst, req->handle_flag, ++ (req->mmu_info.mmu_flag >> 10) & 1); ++ ++ rga_req_log(request, "mmu: mmu_flag = %#x en = %#x\n", ++ req->mmu_info.mmu_flag, req->mmu_info.mmu_en); ++ rga_req_log(request, "alpha: rop_mode = %#x\n", req->alpha_rop_mode); ++ rga_req_log(request, "csc = %#x\n", req->yuv2rgb_mode); ++ rga_req_log(request, "imterplotion: horiz = %s(%#x), verti = %s(%#x)\n", ++ rga_get_interp_str(req->interp.horiz), req->interp.horiz, ++ rga_get_interp_str(req->interp.verti), req->interp.verti); ++ rga_req_log(request, "core_mask = %#x, priority = %d, in_fence = %d(%#x)\n", ++ req->core, req->priority, req->in_fence_fd, req->in_fence_fd); ++} ++ ++unsigned long rga_get_free_pages(gfp_t gfp_mask, unsigned int *order, unsigned long size) ++{ ++ int cur_order, max_order; ++ unsigned long pages; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) ++ max_order = MAX_ORDER; ++#else ++ max_order = MAX_PAGE_ORDER; ++#endif ++ ++ cur_order = get_order(size); ++ if (cur_order > max_order) { ++ rga_err("Can not alloc pages with order[%d] for viraddr pages, max_order = %d\n", ++ cur_order, max_order); ++ return 0; ++ } ++ ++ pages = __get_free_pages(gfp_mask, cur_order); ++ *order = cur_order; ++ ++ return pages; ++} diff --git a/drivers/video/rockchip/rga3/rga_debugger.c b/drivers/video/rockchip/rga3/rga_debugger.c new file mode 100644 -index 000000000..fe2103147 +index 000000000..95cc80976 --- /dev/null +++ b/drivers/video/rockchip/rga3/rga_debugger.c -@@ -0,0 +1,970 @@ +@@ -0,0 +1,1004 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1903495,20 +1904650,21 @@ index 000000000..fe2103147 + * Huang Lee + */ + -+#define pr_fmt(fmt) "rga_debugger: " fmt -+ +#include +#include +#include ++#include +#include +#include +#include ++#include + +#include "rga.h" +#include "rga_debugger.h" +#include "rga_drv.h" +#include "rga_mm.h" +#include "rga_common.h" ++#include "rga_job.h" + +#define RGA_DEBUGGER_ROOT_NAME "rkrga" + @@ -1903520,6 +1904676,7 @@ index 000000000..fe2103147 +int RGA_DEBUG_INT_FLAG; +int RGA_DEBUG_MM; +int RGA_DEBUG_CHECK_MODE; ++int RGA_DEBUG_INTERNAL_MODE; +int RGA_DEBUG_NONUSE; +int RGA_DEBUG_DEBUG_MODE; +int RGA_DEBUG_DUMP_IMAGE; @@ -1903536,6 +1904693,7 @@ index 000000000..fe2103147 + "INT [%s]\n" + "MM [%s]\n" + "CHECK [%s]\n" ++ "INTL [%s]\n" + "STOP [%s]\n", + STR_ENABLE(RGA_DEBUG_REG), + STR_ENABLE(RGA_DEBUG_MSG), @@ -1903543,6 +1904701,7 @@ index 000000000..fe2103147 + STR_ENABLE(RGA_DEBUG_INT_FLAG), + STR_ENABLE(RGA_DEBUG_MM), + STR_ENABLE(RGA_DEBUG_CHECK_MODE), ++ STR_ENABLE(RGA_DEBUG_INTERNAL_MODE), + STR_ENABLE(RGA_DEBUG_NONUSE)); + + seq_puts(m, "\nhelp:\n"); @@ -1903552,6 +1904711,7 @@ index 000000000..fe2103147 + seq_puts(m, " 'echo int > debug' to enable/disable interruppt log printing.\n"); + seq_puts(m, " 'echo mm > debug' to enable/disable memory manager log printing.\n"); + seq_puts(m, " 'echo check > debug' to enable/disable check mode.\n"); ++ seq_puts(m, " 'echo intl > debug' to enable/disable internal mode.\n"); + seq_puts(m, " 'echo stop > debug' to enable/disable stop using hardware\n"); + + return 0; @@ -1903592,6 +1904752,14 @@ index 000000000..fe2103147 + RGA_DEBUG_TIME = 1; + pr_info("open rga test time!\n"); + } ++ } else if (strncmp(buf, "intl", 4) == 0) { ++ if (RGA_DEBUG_INTERNAL_MODE) { ++ RGA_DEBUG_INTERNAL_MODE = 0; ++ pr_info("close rga internal flag!\n"); ++ } else { ++ RGA_DEBUG_INTERNAL_MODE = 1; ++ pr_info("open rga internal flag!\n"); ++ } + } else if (strncmp(buf, "int", 3) == 0) { + if (RGA_DEBUG_INT_FLAG) { + RGA_DEBUG_INT_FLAG = 0; @@ -1903666,11 +1904834,12 @@ index 000000000..fe2103147 + int i; + int load; + u32 busy_time_total; ++ ktime_t now; + + session_manager = rga_drvdata->session_manager; + + seq_printf(m, "num of scheduler = %d\n", rga_drvdata->num_of_scheduler); -+ seq_printf(m, "================= load ==================\n"); ++ seq_puts(m, "================= load ==================\n"); + + for (i = 0; i < rga_drvdata->num_of_scheduler; i++) { + scheduler = rga_drvdata->scheduler[i]; @@ -1903689,13 +1904858,20 @@ index 000000000..fe2103147 + load = 100; + + seq_printf(m, "\t load = %d%%\n", load); -+ seq_printf(m, "-----------------------------------\n"); ++ seq_puts(m, "-----------------------------------\n"); + } + ++ seq_puts(m, "=========================================\n"); ++ seq_puts(m, " \n"); ++ + mutex_lock(&session_manager->lock); + ++ now = ktime_get(); + idr_for_each_entry(&session_manager->ctx_id_idr, session, id) -+ seq_printf(m, "\t process %d: pid = %d, name: %s\n", id, ++ seq_printf(m, "%-9d %-8s %-6d %-s\n", ++ session->id, ++ ktime_us_delta(now, session->last_active) < RGA_LOAD_ACTIVE_MAX_US ? ++ "active" : "idle", + session->tgid, session->pname); + + mutex_unlock(&session_manager->lock); @@ -1903754,7 +1904930,7 @@ index 000000000..fe2103147 + (unsigned long)dump_buffer->dma_buffer->iova, + dump_buffer->dma_buffer->sgt, + dump_buffer->dma_buffer->size, -+ dump_buffer->dma_buffer->scheduler->core); ++ dump_buffer->scheduler->core); + + if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) + seq_printf(m, "\t is contiguous, pa = 0x%lx\n", @@ -1903778,7 +1904954,7 @@ index 000000000..fe2103147 + (unsigned long)dump_buffer->dma_buffer->offset, + dump_buffer->dma_buffer->sgt, + dump_buffer->dma_buffer->size, -+ dump_buffer->dma_buffer->scheduler->core); ++ dump_buffer->scheduler->core); + + if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) + seq_printf(m, "\t is contiguous, pa = 0x%lx\n", @@ -1903950,6 +1905126,65 @@ index 000000000..fe2103147 + return 0; +} + ++static int rga_reset_show(struct seq_file *m, void *data) ++{ ++ struct rga_scheduler_t *scheduler = NULL; ++ int i; ++ ++ seq_puts(m, "help:\n"); ++ seq_puts(m, " 'echo > reset' to reset hardware.\n"); ++ ++ seq_puts(m, "core:\n"); ++ for (i = 0; i < rga_drvdata->num_of_scheduler; i++) { ++ scheduler = rga_drvdata->scheduler[i]; ++ ++ seq_printf(m, " %s core <%d>\n", ++ dev_driver_string(scheduler->dev), scheduler->core); ++ } ++ ++ return 0; ++} ++ ++static ssize_t rga_reset_write(struct file *file, const char __user *ubuf, ++ size_t len, loff_t *offp) ++{ ++ char buf[14]; ++ int i, ret; ++ int reset_core = 0; ++ int reset_done = false; ++ struct rga_scheduler_t *scheduler = NULL; ++ ++ if (len > sizeof(buf) - 1) ++ return -EINVAL; ++ if (copy_from_user(buf, ubuf, len)) ++ return -EFAULT; ++ buf[len - 1] = '\0'; ++ ++ ret = kstrtoint(buf, 10, &reset_core); ++ if (ret < 0 || reset_core <= 0) { ++ pr_err("invalid core! failed to reset hardware, data = %s len = %zu.\n", buf, len); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < rga_drvdata->num_of_scheduler; i++) { ++ scheduler = rga_drvdata->scheduler[i]; ++ ++ if (scheduler->core == reset_core) { ++ reset_done = true; ++ pr_info("reset hardware core[%d]!\n", reset_core); ++ ++ rga_request_scheduler_abort(scheduler); ++ ++ break; ++ } ++ } ++ ++ if (!reset_done) ++ pr_err("cannot find core[%d]\n", reset_core); ++ ++ return len; ++} ++ +static struct rga_debugger_list rga_debugger_root_list[] = { + {"debug", rga_debug_show, rga_debug_write, NULL}, + {"driver_version", rga_version_show, NULL, NULL}, @@ -1903962,6 +1905197,7 @@ index 000000000..fe2103147 + {"dump_image", rga_dump_image_show, rga_dump_image_write, NULL}, +#endif + {"hardware", rga_hardware_show, NULL, NULL}, ++ {"reset", rga_reset_show, rga_reset_write, NULL}, +}; + +static ssize_t rga_debugger_write(struct file *file, const char __user *ubuf, @@ -1904271,53 +1905507,6 @@ index 000000000..fe2103147 + req->core, req->priority, req->in_fence_fd); +} + -+void rga_cmd_print_debug_info(struct rga_req *req) -+{ -+ 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); -+} -+ +#ifdef CONFIG_NO_GKI +static int rga_dump_image_to_file(struct rga_internal_buffer *dump_buffer, + const char *channel_name, @@ -1904458,10 +1905647,10 @@ index 000000000..fe2103147 +#endif /* #ifdef CONFIG_NO_GKI */ diff --git a/drivers/video/rockchip/rga3/rga_dma_buf.c b/drivers/video/rockchip/rga3/rga_dma_buf.c new file mode 100644 -index 000000000..753348a00 +index 000000000..96609d078 --- /dev/null +++ b/drivers/video/rockchip/rga3/rga_dma_buf.c -@@ -0,0 +1,546 @@ +@@ -0,0 +1,482 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1904469,28 +1905658,12 @@ index 000000000..753348a00 + * Author: Huang Lee + */ + -+#define pr_fmt(fmt) "rga_dma_buf: " fmt -+ +#include "rga_dma_buf.h" +#include "rga.h" +#include "rga_common.h" +#include "rga_job.h" +#include "rga_debugger.h" + -+static int rga_dma_info_to_prot(enum dma_data_direction dir) -+{ -+ switch (dir) { -+ case DMA_BIDIRECTIONAL: -+ return IOMMU_READ | IOMMU_WRITE; -+ case DMA_TO_DEVICE: -+ return IOMMU_READ; -+ case DMA_FROM_DEVICE: -+ return IOMMU_WRITE; -+ default: -+ return 0; -+ } -+} -+ +int rga_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr, + unsigned long v_addr, int format, uint32_t w, + uint32_t h, unsigned long *StartAddr, unsigned long *size) @@ -1904597,6 +1905770,7 @@ index 000000000..753348a00 + pageCount = end - start; + break; + case RGA_FORMAT_YCbCr_400: ++ case RGA_FORMAT_Y8: + stride = (w + 3) & (~3); + size_yrgb = stride * h; + start = yrgb_addr >> PAGE_SHIFT; @@ -1904663,165 +1905837,6 @@ index 000000000..753348a00 + return pageCount; +} + -+static dma_addr_t rga_iommu_dma_alloc_iova(struct iommu_domain *domain, -+ size_t size, u64 dma_limit, -+ struct device *dev) -+{ -+ struct rga_iommu_dma_cookie *cookie = (void *)domain->iova_cookie; -+ struct iova_domain *iovad = &cookie->iovad; -+ unsigned long shift, iova_len, iova = 0; -+ -+ shift = iova_shift(iovad); -+ iova_len = size >> shift; -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)) -+ /* -+ * Freeing non-power-of-two-sized allocations back into the IOVA caches -+ * will come back to bite us badly, so we have to waste a bit of space -+ * rounding up anything cacheable to make sure that can't happen. The -+ * order of the unadjusted size will still match upon freeing. -+ */ -+ if (iova_len < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1))) -+ iova_len = roundup_pow_of_two(iova_len); -+#endif -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) -+ dma_limit = min_not_zero(dma_limit, dev->bus_dma_limit); -+#else -+ if (dev->bus_dma_mask) -+ dma_limit &= dev->bus_dma_mask; -+#endif -+ -+ if (domain->geometry.force_aperture) -+ dma_limit = min(dma_limit, (u64)domain->geometry.aperture_end); -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 19, 111) && \ -+ LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) -+ iova = alloc_iova_fast(iovad, iova_len, -+ min_t(dma_addr_t, dma_limit >> shift, iovad->end_pfn), -+ true); -+#else -+ iova = alloc_iova_fast(iovad, iova_len, dma_limit >> shift, true); -+#endif -+ -+ return (dma_addr_t)iova << shift; -+} -+ -+static void rga_iommu_dma_free_iova(struct iommu_domain *domain, -+ dma_addr_t iova, size_t size) -+{ -+ struct rga_iommu_dma_cookie *cookie = (void *)domain->iova_cookie; -+ struct iova_domain *iovad = &cookie->iovad; -+ -+ free_iova_fast(iovad, iova_pfn(iovad, iova), size >> iova_shift(iovad)); -+} -+ -+static inline struct iommu_domain *rga_iommu_get_dma_domain(struct device *dev) -+{ -+ return iommu_get_domain_for_dev(dev); -+} -+ -+void rga_iommu_unmap(struct rga_dma_buffer *buffer) -+{ -+ if (buffer == NULL) -+ return; -+ if (buffer->iova == 0) -+ return; -+ -+ iommu_unmap(buffer->domain, buffer->iova, buffer->size); -+ rga_iommu_dma_free_iova(buffer->domain, buffer->iova, buffer->size); -+} -+ -+int rga_iommu_map_sgt(struct sg_table *sgt, size_t size, -+ struct rga_dma_buffer *buffer, -+ struct device *rga_dev) -+{ -+ struct iommu_domain *domain = NULL; -+ struct rga_iommu_dma_cookie *cookie; -+ struct iova_domain *iovad; -+ dma_addr_t iova; -+ size_t map_size; -+ unsigned long align_size; -+ -+ if (sgt == NULL) { -+ pr_err("can not map iommu, because sgt is null!\n"); -+ return -EINVAL; -+ } -+ -+ domain = rga_iommu_get_dma_domain(rga_dev); -+ cookie = (void *)domain->iova_cookie; -+ iovad = &cookie->iovad; -+ align_size = iova_align(iovad, size); -+ -+ if (DEBUGGER_EN(MSG)) -+ pr_info("iova_align size = %ld", align_size); -+ -+ iova = rga_iommu_dma_alloc_iova(domain, align_size, rga_dev->coherent_dma_mask, rga_dev); -+ if (!iova) { -+ pr_err("rga_iommu_dma_alloc_iova failed"); -+ return -ENOMEM; -+ } -+ -+ map_size = iommu_map_sg(domain, iova, sgt->sgl, sgt->orig_nents, -+ rga_dma_info_to_prot(DMA_BIDIRECTIONAL)); -+ if (map_size < align_size) { -+ pr_err("iommu can not map sgt to iova"); -+ rga_iommu_dma_free_iova(domain, iova, align_size); -+ return -EINVAL; -+ } -+ -+ buffer->domain = domain; -+ buffer->iova = iova; -+ buffer->size = align_size; -+ -+ return 0; -+} -+ -+int rga_iommu_map(phys_addr_t paddr, size_t size, -+ struct rga_dma_buffer *buffer, -+ struct device *rga_dev) -+{ -+ int ret; -+ struct iommu_domain *domain = NULL; -+ struct rga_iommu_dma_cookie *cookie; -+ struct iova_domain *iovad; -+ dma_addr_t iova; -+ unsigned long align_size; -+ -+ if (paddr == 0) { -+ pr_err("can not map iommu, because phys_addr is 0!\n"); -+ return -EINVAL; -+ } -+ -+ domain = rga_iommu_get_dma_domain(rga_dev); -+ cookie = (void *)domain->iova_cookie; -+ iovad = &cookie->iovad; -+ align_size = iova_align(iovad, size); -+ -+ if (DEBUGGER_EN(MSG)) -+ pr_info("iova_align size = %ld", align_size); -+ -+ iova = rga_iommu_dma_alloc_iova(domain, align_size, rga_dev->coherent_dma_mask, rga_dev); -+ if (!iova) { -+ pr_err("rga_iommu_dma_alloc_iova failed"); -+ return -ENOMEM; -+ } -+ -+ ret = iommu_map(domain, iova, paddr, align_size, -+ rga_dma_info_to_prot(DMA_BIDIRECTIONAL)); -+ if (ret) { -+ pr_err("iommu can not map phys_addr to iova"); -+ rga_iommu_dma_free_iova(domain, iova, align_size); -+ return ret; -+ } -+ -+ buffer->domain = domain; -+ buffer->iova = iova; -+ buffer->size = align_size; -+ -+ return 0; -+} -+ +int rga_virtual_memory_check(void *vaddr, u32 w, u32 h, u32 format, int fd) +{ + int bits = 32; @@ -1904834,20 +1905849,20 @@ index 000000000..753348a00 + + one_line = kzalloc(w * 4, GFP_KERNEL); + if (!one_line) { -+ pr_err("kzalloc fail %s[%d]\n", __func__, __LINE__); ++ rga_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); ++ rga_log("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"); ++ rga_log("fd check ok\n"); + } else { -+ pr_info("vir addr memory check.\n"); ++ rga_log("vir addr memory check.\n"); + memcpy((void *)((char *)vaddr + temp_data), one_line, + w * bits >> 3); -+ pr_info("vir addr check ok.\n"); ++ rga_log("vir addr check ok.\n"); + } + + kfree(one_line); @@ -1904858,7 +1905873,7 @@ index 000000000..753348a00 +{ + int ret = 0; + void *vaddr; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) + struct iosys_map map; +#endif + struct dma_buf *dma_buf; @@ -1904866,7 +1905881,7 @@ index 000000000..753348a00 + dma_buf = rga_dma_buffer->dma_buf; + + if (!IS_ERR_OR_NULL(dma_buf)) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) + ret = dma_buf_vmap(dma_buf, &map); + vaddr = ret ? NULL : map.vaddr; +#else @@ -1904876,10 +1905891,10 @@ index 000000000..753348a00 + 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"); ++ rga_err("can't vmap the dma buffer!\n"); + return -EINVAL; + } -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) + dma_buf_vunmap(dma_buf, &map); +#else + dma_buf_vunmap(dma_buf, vaddr); @@ -1904889,8 +1905904,67 @@ index 000000000..753348a00 + return ret; +} + ++int rga_dma_map_phys_addr(phys_addr_t phys_addr, size_t size, struct rga_dma_buffer *buffer, ++ enum dma_data_direction dir, struct device *map_dev) ++{ ++ dma_addr_t addr; ++ ++ addr = dma_map_resource(map_dev, phys_addr, size, dir, 0); ++ if (addr == DMA_MAPPING_ERROR) { ++ rga_err("dma_map_resouce failed!\n"); ++ return -EINVAL; ++ } ++ ++ buffer->dma_addr = addr; ++ buffer->dir = dir; ++ buffer->size = size; ++ buffer->map_dev = map_dev; ++ ++ return 0; ++} ++ ++void rga_dma_unmap_phys_addr(struct rga_dma_buffer *buffer) ++{ ++ dma_unmap_resource(buffer->map_dev, buffer->dma_addr, buffer->size, buffer->dir, 0); ++} ++ ++int rga_dma_map_sgt(struct sg_table *sgt, struct rga_dma_buffer *buffer, ++ enum dma_data_direction dir, struct device *map_dev) ++{ ++ int i, ret = 0; ++ struct scatterlist *sg = NULL; ++ ++ ret = dma_map_sg(map_dev, sgt->sgl, sgt->orig_nents, dir); ++ if (ret <= 0) { ++ rga_err("dma_map_sg failed! ret = %d\n", ret); ++ return ret < 0 ? ret : -EINVAL; ++ } ++ sgt->nents = ret; ++ ++ buffer->sgt = sgt; ++ buffer->dma_addr = sg_dma_address(sgt->sgl); ++ buffer->dir = dir; ++ buffer->size = 0; ++ for_each_sgtable_sg(sgt, sg, i) ++ buffer->size += sg_dma_len(sg); ++ buffer->map_dev = map_dev; ++ ++ return 0; ++} ++ ++void rga_dma_unmap_sgt(struct rga_dma_buffer *buffer) ++{ ++ if (!buffer->sgt) ++ return; ++ ++ dma_unmap_sg(buffer->map_dev, ++ buffer->sgt->sgl, ++ buffer->sgt->orig_nents, ++ buffer->dir); ++} ++ +int rga_dma_map_buf(struct dma_buf *dma_buf, struct rga_dma_buffer *rga_dma_buffer, -+ enum dma_data_direction dir, struct device *rga_dev) ++ enum dma_data_direction dir, struct device *map_dev) +{ + struct dma_buf_attachment *attach = NULL; + struct sg_table *sgt = NULL; @@ -1904900,32 +1905974,33 @@ index 000000000..753348a00 + if (dma_buf != NULL) { + get_dma_buf(dma_buf); + } else { -+ pr_err("dma_buf is invalid[%p]\n", dma_buf); ++ rga_err("dma_buf is invalid[%p]\n", dma_buf); + return -EINVAL; + } + -+ attach = dma_buf_attach(dma_buf, rga_dev); ++ attach = dma_buf_attach(dma_buf, map_dev); + if (IS_ERR(attach)) { + ret = PTR_ERR(attach); -+ pr_err("Failed to attach dma_buf, ret[%d]\n", ret); ++ rga_err("Failed to attach dma_buf, ret[%d]\n", ret); + goto err_get_attach; + } + + sgt = dma_buf_map_attachment(attach, dir); + if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); -+ pr_err("Failed to map attachment, ret[%d]\n", ret); ++ rga_err("Failed to map attachment, ret[%d]\n", ret); + goto err_get_sgt; + } + + 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); ++ rga_dma_buffer->dma_addr = sg_dma_address(sgt->sgl); + rga_dma_buffer->dir = dir; + rga_dma_buffer->size = 0; + for_each_sgtable_sg(sgt, sg, i) + rga_dma_buffer->size += sg_dma_len(sg); ++ rga_dma_buffer->map_dev = map_dev; + + return ret; + @@ -1904940,7 +1906015,7 @@ index 000000000..753348a00 +} + +int rga_dma_map_fd(int fd, struct rga_dma_buffer *rga_dma_buffer, -+ enum dma_data_direction dir, struct device *rga_dev) ++ enum dma_data_direction dir, struct device *map_dev) +{ + struct dma_buf *dma_buf = NULL; + struct dma_buf_attachment *attach = NULL; @@ -1904951,32 +1906026,33 @@ index 000000000..753348a00 + dma_buf = dma_buf_get(fd); + if (IS_ERR(dma_buf)) { + ret = PTR_ERR(dma_buf); -+ pr_err("Fail to get dma_buf from fd[%d], ret[%d]\n", fd, ret); ++ rga_err("Fail to get dma_buf from fd[%d], ret[%d]\n", fd, ret); + return ret; + } + -+ attach = dma_buf_attach(dma_buf, rga_dev); ++ attach = dma_buf_attach(dma_buf, map_dev); + if (IS_ERR(attach)) { + ret = PTR_ERR(attach); -+ pr_err("Failed to attach dma_buf, ret[%d]\n", ret); ++ rga_err("Failed to attach dma_buf, ret[%d]\n", ret); + goto err_get_attach; + } + + sgt = dma_buf_map_attachment(attach, dir); + if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); -+ pr_err("Failed to map attachment, ret[%d]\n", ret); ++ rga_err("Failed to map attachment, ret[%d]\n", ret); + goto err_get_sgt; + } + + 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); ++ rga_dma_buffer->dma_addr = sg_dma_address(sgt->sgl); + rga_dma_buffer->dir = dir; + rga_dma_buffer->size = 0; + for_each_sgtable_sg(sgt, sg, i) + rga_dma_buffer->size += sg_dma_len(sg); ++ rga_dma_buffer->map_dev = map_dev; + + return ret; + @@ -1905008,12 +1906084,61 @@ index 000000000..753348a00 + dma_sync_single_for_device(scheduler->dev, virt_to_phys(pstart), + pend - pstart, DMA_TO_DEVICE); +} ++ ++int rga_dma_free(struct rga_dma_buffer *buffer) ++{ ++ if (buffer == NULL) { ++ rga_err("rga_dma_buffer is NULL.\n"); ++ return -EINVAL; ++ } ++ ++ dma_free_coherent(buffer->map_dev, buffer->size, buffer->vaddr, buffer->dma_addr); ++ buffer->vaddr = NULL; ++ buffer->dma_addr = 0; ++ buffer->iova = 0; ++ buffer->size = 0; ++ buffer->map_dev = NULL; ++ ++ kfree(buffer); ++ ++ return 0; ++} ++ ++struct rga_dma_buffer *rga_dma_alloc_coherent(struct rga_scheduler_t *scheduler, ++ int size) ++{ ++ size_t align_size; ++ dma_addr_t dma_addr; ++ struct rga_dma_buffer *buffer; ++ ++ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); ++ if (!buffer) ++ return NULL; ++ ++ align_size = PAGE_ALIGN(size); ++ buffer->vaddr = dma_alloc_coherent(scheduler->dev, align_size, &dma_addr, GFP_KERNEL); ++ if (!buffer->vaddr) ++ goto fail_dma_alloc; ++ ++ buffer->size = align_size; ++ buffer->dma_addr = dma_addr; ++ buffer->map_dev = scheduler->dev; ++ if (scheduler->data->mmu == RGA_IOMMU) ++ buffer->iova = buffer->dma_addr; ++ ++ return buffer; ++ ++fail_dma_alloc: ++ kfree(buffer); ++ ++ return NULL; ++} diff --git a/drivers/video/rockchip/rga3/rga_drv.c b/drivers/video/rockchip/rga3/rga_drv.c new file mode 100644 -index 000000000..2d80c8089 +index 000000000..9ef013bb6 --- /dev/null +++ b/drivers/video/rockchip/rga3/rga_drv.c -@@ -0,0 +1,1615 @@ +@@ -0,0 +1,1678 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1905021,8 +1906146,6 @@ index 000000000..2d80c8089 + * Author: Huang Lee + */ + -+#define pr_fmt(fmt) "rga: " fmt -+ +#include "rga2_reg_info.h" +#include "rga3_reg_info.h" +#include "rga_dma_buf.h" @@ -1905043,7 +1906166,6 @@ index 000000000..2d80c8089 +static ktime_t kt; + +static struct rga_session *rga_session_init(void); -+static int rga_session_deinit(struct rga_session *session); + +static int rga_mpi_set_channel_buffer(struct dma_buf *dma_buf, + struct rga_img_info_t *channel_info, @@ -1905060,7 +1906182,7 @@ index 000000000..2d80c8089 + + buffer.handle = rga_mm_import_buffer(&buffer, session); + if (buffer.handle == 0) { -+ pr_err("can not import dma_buf %p\n", dma_buf); ++ rga_err("can not import dma_buf %p\n", dma_buf); + return -EFAULT; + } + channel_info->yrgb_addr = buffer.handle; @@ -1905131,25 +1906253,28 @@ index 000000000..2d80c8089 + mutex_lock(&request_manager->lock); + request = rga_request_lookup(request_manager, mpi_job->ctx_id); + if (IS_ERR_OR_NULL(request)) { -+ pr_err("can not find request from id[%d]", mpi_job->ctx_id); ++ rga_err("can not find request from id[%d]", mpi_job->ctx_id); + mutex_unlock(&request_manager->lock); + return -EINVAL; + } + + if (request->task_count > 1) { + /* TODO */ -+ pr_err("Currently request does not support multiple tasks!"); ++ rga_req_err(request, "Currently request does not support multiple tasks!"); + mutex_unlock(&request_manager->lock); + return -EINVAL; + } + -+ /* -+ * The mpi commit will use the request repeatedly, so an additional -+ * get() is added here. -+ */ + rga_request_get(request); + mutex_unlock(&request_manager->lock); + ++ down_read(&request->session->release_rwsem); ++ if (request->session->release) { ++ rga_req_err(request, "current session has been release\n"); ++ ret = -EFAULT; ++ goto err_release_rwsem; ++ } ++ + spin_lock_irqsave(&request->lock, flags); + + /* TODO: batch mode need mpi async mode */ @@ -1905188,7 +1906313,7 @@ index 000000000..2d80c8089 + &mpi_cmd.src, + request->session); + if (ret < 0) { -+ pr_err("src channel set buffer handle failed!\n"); ++ rga_req_err(request, "src channel set buffer handle failed!\n"); + goto err_put_request; + } + } @@ -1905198,7 +1906323,7 @@ index 000000000..2d80c8089 + &mpi_cmd.pat, + request->session); + if (ret < 0) { -+ pr_err("src1 channel set buffer handle failed!\n"); ++ rga_req_err(request, "src1 channel set buffer handle failed!\n"); + goto err_put_request; + } + } @@ -1905208,7 +1906333,7 @@ index 000000000..2d80c8089 + &mpi_cmd.dst, + request->session); + if (ret < 0) { -+ pr_err("dst channel set buffer handle failed!\n"); ++ rga_req_err(request, "dst channel set buffer handle failed!\n"); + goto err_put_request; + } + } @@ -1905218,28 +1906343,21 @@ index 000000000..2d80c8089 + mpi_cmd.mmu_info.mmu_flag = 0; + + if (DEBUGGER_EN(MSG)) -+ rga_cmd_print_debug_info(&mpi_cmd); ++ rga_dump_req(request, &mpi_cmd); + + ret = rga_request_mpi_submit(&mpi_cmd, request); + if (ret < 0) { + if (ret == -ERESTARTSYS) { + if (DEBUGGER_EN(MSG)) -+ pr_err("%s, commit mpi job failed, by a software interrupt.\n", ++ rga_req_err(request, "%s, commit mpi job failed, by a software interrupt.\n", + __func__); + } else { -+ pr_err("%s, commit mpi job failed\n", __func__); ++ rga_req_err(request, "%s, commit mpi job failed\n", __func__); + } + + goto err_put_request; + } + -+ if ((mpi_job->dma_buf_src0 != NULL) && (mpi_cmd.src.yrgb_addr > 0)) -+ rga_mm_release_buffer(mpi_cmd.src.yrgb_addr); -+ if ((mpi_job->dma_buf_src1 != NULL) && (mpi_cmd.pat.yrgb_addr > 0)) -+ rga_mm_release_buffer(mpi_cmd.pat.yrgb_addr); -+ if ((mpi_job->dma_buf_dst != NULL) && (mpi_cmd.dst.yrgb_addr > 0)) -+ rga_mm_release_buffer(mpi_cmd.dst.yrgb_addr); -+ + /* copy dst info to mpi job for next node */ + if (mpi_job->output != NULL) { + mpi_job->output->x_offset = mpi_cmd.dst.x_offset; @@ -1905252,9 +1906370,17 @@ index 000000000..2d80c8089 + mpi_job->output->format = mpi_cmd.dst.format; + } + -+ return 0; -+ +err_put_request: ++ if ((mpi_job->dma_buf_src0 != NULL) && (mpi_cmd.src.yrgb_addr > 0)) ++ rga_mm_release_buffer(mpi_cmd.src.yrgb_addr); ++ if ((mpi_job->dma_buf_src1 != NULL) && (mpi_cmd.pat.yrgb_addr > 0)) ++ rga_mm_release_buffer(mpi_cmd.pat.yrgb_addr); ++ if ((mpi_job->dma_buf_dst != NULL) && (mpi_cmd.dst.yrgb_addr > 0)) ++ rga_mm_release_buffer(mpi_cmd.dst.yrgb_addr); ++ ++err_release_rwsem: ++ up_read(&request->session->release_rwsem); ++ + mutex_lock(&request_manager->lock); + rga_request_put(request); + mutex_unlock(&request_manager->lock); @@ -1905276,11 +1906402,13 @@ index 000000000..2d80c8089 + if (IS_ERR(session)) + return PTR_ERR(session); + ++ down_read(&session->release_rwsem); ++ + request_id = rga_request_alloc(0, session); + if (request_id < 0) { -+ pr_err("request alloc error!\n"); ++ rga_err("request alloc error!\n"); + ret = request_id; -+ return ret; ++ goto err_put_session; + } + + memset(&kernel_request, 0, sizeof(kernel_request)); @@ -1905291,51 +1906419,48 @@ index 000000000..2d80c8089 + + ret = rga_request_check(&kernel_request); + if (ret < 0) { -+ pr_err("user request check error!\n"); -+ goto err_free_request_by_id; ++ rga_err("ID[%d]: user request check error!\n", kernel_request.id); ++ goto err_put_request; + } + + request = rga_request_kernel_config(&kernel_request); + if (IS_ERR(request)) { -+ pr_err("request[%d] config failed!\n", kernel_request.id); ++ rga_err("ID[%d]: config failed!\n", kernel_request.id); + ret = -EFAULT; -+ goto err_free_request_by_id; ++ goto err_put_request; + } + + if (DEBUGGER_EN(MSG)) { -+ pr_info("kernel blit mode: request id = %d", kernel_request.id); -+ rga_cmd_print_debug_info(cmd); ++ rga_req_log(request, "kernel blit mode:\n"); ++ rga_dump_req(request, cmd); + } + + ret = rga_request_submit(request); -+ if (ret < 0) { -+ pr_err("request[%d] submit failed!\n", kernel_request.id); -+ goto err_put_request; -+ } ++ if (ret < 0) ++ rga_req_err(request, "submit failed!\n"); + +err_put_request: + mutex_lock(&request_manager->lock); -+ rga_request_put(request); -+ mutex_unlock(&request_manager->lock); -+ -+ rga_session_deinit(session); -+ -+ return ret; + -+err_free_request_by_id: -+ mutex_lock(&request_manager->lock); ++ if (request == NULL) { ++ request = rga_request_lookup(request_manager, request_id); ++ if (IS_ERR_OR_NULL(request)) { ++ rga_err("can not find request from id[%d]", request_id); + -+ request = rga_request_lookup(request_manager, request_id); -+ if (IS_ERR_OR_NULL(request)) { -+ pr_err("can not find request from id[%d]", request_id); -+ mutex_unlock(&request_manager->lock); -+ return -EINVAL; ++ mutex_unlock(&request_manager->lock); ++ ret = -EINVAL; ++ goto err_put_session; ++ } + } + -+ rga_request_free(request); ++ rga_request_put(request); + + mutex_unlock(&request_manager->lock); + ++err_put_session: ++ up_read(&session->release_rwsem); ++ rga_session_put(session); ++ + return ret; +} +EXPORT_SYMBOL_GPL(rga_kernel_commit); @@ -1905358,8 +1906483,8 @@ index 000000000..2d80c8089 + /* if timer action on job running */ + job = scheduler->running_job; + if (job) { -+ scheduler->timer.busy_time += ktime_us_delta(now, job->hw_recoder_time); -+ job->hw_recoder_time = now; ++ scheduler->timer.busy_time += ktime_us_delta(now, job->timestamp.hw_recode); ++ job->timestamp.hw_recode = now; + } + + scheduler->timer.busy_time_record = scheduler->timer.busy_time; @@ -1905391,19 +1906516,14 @@ index 000000000..2d80c8089 +int rga_power_enable(struct rga_scheduler_t *scheduler) +{ + int ret = -EINVAL; -+ int i; + unsigned long flags; + + pm_runtime_get_sync(scheduler->dev); + pm_stay_awake(scheduler->dev); + -+ for (i = 0; i < scheduler->num_clks; i++) { -+ if (!IS_ERR(scheduler->clks[i])) { -+ ret = clk_prepare_enable(scheduler->clks[i]); -+ if (ret < 0) -+ goto err_enable_clk; -+ } -+ } ++ ret = clk_bulk_prepare_enable(scheduler->num_clks, scheduler->clks); ++ if (ret < 0) ++ goto err_enable_clk; + + spin_lock_irqsave(&scheduler->irq_lock, flags); + @@ -1905416,10 +1906536,6 @@ index 000000000..2d80c8089 + return 0; + +err_enable_clk: -+ for (--i; i >= 0; --i) -+ if (!IS_ERR(scheduler->clks[i])) -+ clk_disable_unprepare(scheduler->clks[i]); -+ + pm_relax(scheduler->dev); + pm_runtime_put_sync_suspend(scheduler->dev); + @@ -1905428,7 +1906544,6 @@ index 000000000..2d80c8089 + +int rga_power_disable(struct rga_scheduler_t *scheduler) +{ -+ int i; + unsigned long flags; + + spin_lock_irqsave(&scheduler->irq_lock, flags); @@ -1905446,9 +1906561,7 @@ index 000000000..2d80c8089 + + spin_unlock_irqrestore(&scheduler->irq_lock, flags); + -+ for (i = scheduler->num_clks - 1; i >= 0; i--) -+ if (!IS_ERR(scheduler->clks[i])) -+ clk_disable_unprepare(scheduler->clks[i]); ++ clk_bulk_disable_unprepare(scheduler->num_clks, scheduler->clks); + + pm_relax(scheduler->dev); + pm_runtime_put_sync_suspend(scheduler->dev); @@ -1905466,7 +1906579,7 @@ index 000000000..2d80c8089 + scheduler = rga_drvdata->scheduler[i]; + ret = rga_power_enable(scheduler); + if (ret < 0) -+ pr_err("power enable failed"); ++ rga_err("power enable failed"); + } +} + @@ -1905571,13 +1906684,13 @@ index 000000000..2d80c8089 + + session_manager = rga_drvdata->session_manager; + if (session_manager == NULL) { -+ pr_err("rga_session_manager is null!\n"); ++ rga_err("rga_session_manager is null!\n"); + return ERR_PTR(-EFAULT); + } + + session = kzalloc(sizeof(*session), GFP_KERNEL); + if (!session) { -+ pr_err("rga_session alloc failed\n"); ++ rga_err("rga_session alloc failed\n"); + return ERR_PTR(-ENOMEM); + } + @@ -1905589,7 +1906702,7 @@ index 000000000..2d80c8089 + if (new_id < 0) { + mutex_unlock(&session_manager->lock); + -+ pr_err("rga_session alloc id failed!\n"); ++ rga_err("rga_session alloc id failed!\n"); + kfree(session); + return ERR_PTR(new_id); + } @@ -1905602,20 +1906715,34 @@ index 000000000..2d80c8089 + session->tgid = current->tgid; + session->pname = kstrdup_quotable_cmdline(current, GFP_KERNEL); + ++ session->last_active = ktime_get(); ++ session->release = false; ++ init_rwsem(&session->release_rwsem); ++ kref_init(&session->refcount); ++ + return session; +} + -+static int rga_session_deinit(struct rga_session *session) ++static void rga_session_kref_release(struct kref *ref) +{ -+ rga_request_session_destroy_abort(session); -+ rga_mm_session_release_buffer(session); ++ struct rga_session *session; ++ ++ session = container_of(ref, struct rga_session, refcount); + + rga_session_free_remove_idr(session); + + kfree(session->pname); + kfree(session); ++} + -+ return 0; ++int rga_session_put(struct rga_session *session) ++{ ++ return kref_put(&session->refcount, rga_session_kref_release); ++} ++ ++void rga_session_get(struct rga_session *session) ++{ ++ kref_get(&session->refcount); +} + +static long rga_ioctl_import_buffer(unsigned long arg, struct rga_session *session) @@ -1905628,32 +1906755,32 @@ index 000000000..2d80c8089 + if (unlikely(copy_from_user(&buffer_pool, + (struct rga_buffer_pool *)arg, + sizeof(buffer_pool)))) { -+ pr_err("rga_buffer_pool copy_from_user failed!\n"); ++ rga_err("rga_buffer_pool copy_from_user failed!\n"); + return -EFAULT; + } + + if (buffer_pool.size > RGA_BUFFER_POOL_SIZE_MAX) { -+ pr_err("Cannot import more than %d buffers at a time!\n", ++ rga_err("Cannot import more than %d buffers at a time!\n", + RGA_BUFFER_POOL_SIZE_MAX); + return -EFBIG; + } + + if (buffer_pool.buffers_ptr == 0) { -+ pr_err("Import buffers is NULL!\n"); ++ rga_err("Import buffers is NULL!\n"); + return -EFAULT; + } + + external_buffer = kmalloc(sizeof(struct rga_external_buffer) * buffer_pool.size, + GFP_KERNEL); + if (external_buffer == NULL) { -+ pr_err("external buffer list alloc error!\n"); ++ rga_err("external buffer list alloc error!\n"); + return -ENOMEM; + } + + if (unlikely(copy_from_user(external_buffer, + u64_to_user_ptr(buffer_pool.buffers_ptr), + sizeof(struct rga_external_buffer) * buffer_pool.size))) { -+ pr_err("rga_buffer_pool external_buffer list copy_from_user failed\n"); ++ rga_err("rga_buffer_pool external_buffer list copy_from_user failed\n"); + ret = -EFAULT; + + goto err_free_external_buffer; @@ -1905661,13 +1906788,13 @@ index 000000000..2d80c8089 + + for (i = 0; i < buffer_pool.size; i++) { + if (DEBUGGER_EN(MSG)) { -+ pr_info("import buffer info:\n"); ++ rga_log("import buffer info:\n"); + rga_dump_external_buffer(&external_buffer[i]); + } + + ret = rga_mm_import_buffer(&external_buffer[i], session); + if (ret <= 0) { -+ pr_err("buffer[%d] mm import buffer failed! memory = 0x%lx, type = %s(0x%x)\n", ++ rga_err("buffer[%d] mm import buffer failed! memory = 0x%lx, type = %s(0x%x)\n", + i, (unsigned long)external_buffer[i].memory, + rga_get_memory_type_str(external_buffer[i].type), + external_buffer[i].type); @@ -1905681,7 +1906808,7 @@ index 000000000..2d80c8089 + if (unlikely(copy_to_user(u64_to_user_ptr(buffer_pool.buffers_ptr), + external_buffer, + sizeof(struct rga_external_buffer) * buffer_pool.size))) { -+ pr_err("rga_buffer_pool external_buffer list copy_to_user failed\n"); ++ rga_err("rga_buffer_pool external_buffer list copy_to_user failed\n"); + ret = -EFAULT; + + goto err_free_external_buffer; @@ -1905702,32 +1906829,32 @@ index 000000000..2d80c8089 + if (unlikely(copy_from_user(&buffer_pool, + (struct rga_buffer_pool *)arg, + sizeof(buffer_pool)))) { -+ pr_err("rga_buffer_pool copy_from_user failed!\n"); ++ rga_err("rga_buffer_pool copy_from_user failed!\n"); + return -EFAULT; + } + + if (buffer_pool.size > RGA_BUFFER_POOL_SIZE_MAX) { -+ pr_err("Cannot release more than %d buffers at a time!\n", ++ rga_err("Cannot release more than %d buffers at a time!\n", + RGA_BUFFER_POOL_SIZE_MAX); + return -EFBIG; + } + + if (buffer_pool.buffers_ptr == 0) { -+ pr_err("Release buffers is NULL!\n"); ++ rga_err("Release buffers is NULL!\n"); + return -EFAULT; + } + + external_buffer = kmalloc(sizeof(struct rga_external_buffer) * buffer_pool.size, + GFP_KERNEL); + if (external_buffer == NULL) { -+ pr_err("external buffer list alloc error!\n"); ++ rga_err("external buffer list alloc error!\n"); + return -ENOMEM; + } + + if (unlikely(copy_from_user(external_buffer, + u64_to_user_ptr(buffer_pool.buffers_ptr), + sizeof(struct rga_external_buffer) * buffer_pool.size))) { -+ pr_err("rga_buffer_pool external_buffer list copy_from_user failed\n"); ++ rga_err("rga_buffer_pool external_buffer list copy_from_user failed\n"); + ret = -EFAULT; + + goto err_free_external_buffer; @@ -1905735,11 +1906862,11 @@ index 000000000..2d80c8089 + + for (i = 0; i < buffer_pool.size; i++) { + if (DEBUGGER_EN(MSG)) -+ pr_info("release buffer handle[%d]\n", external_buffer[i].handle); ++ rga_log("release buffer handle[%d]\n", external_buffer[i].handle); + + ret = rga_mm_release_buffer(external_buffer[i].handle); + if (ret < 0) { -+ pr_err("buffer[%d] mm release buffer failed! handle = %d\n", ++ rga_err("buffer[%d] mm release buffer failed! handle = %d\n", + i, external_buffer[i].handle); + + goto err_free_external_buffer; @@ -1905757,14 +1906884,14 @@ index 000000000..2d80c8089 + uint32_t flags; + + if (copy_from_user(&flags, (void *)arg, sizeof(uint32_t))) { -+ pr_err("%s failed to copy from usrer!\n", __func__); ++ rga_err("%s failed to copy from user!\n", __func__); + return -EFAULT; + } + + id = rga_request_alloc(flags, session); + + if (copy_to_user((void *)arg, &id, sizeof(uint32_t))) { -+ pr_err("%s failed to copy to usrer!\n", __func__); ++ rga_err("%s failed to copy to user!\n", __func__); + return -EFAULT; + } + @@ -1905783,29 +1906910,29 @@ index 000000000..2d80c8089 + if (unlikely(copy_from_user(&user_request, + (struct rga_user_request *)arg, + sizeof(user_request)))) { -+ pr_err("%s copy_from_user failed!\n", __func__); ++ rga_err("%s copy_from_user failed!\n", __func__); + return -EFAULT; + } + + ret = rga_request_check(&user_request); + if (ret < 0) { -+ pr_err("user request check error!\n"); ++ rga_err("user request check error!\n"); + return ret; + } + + if (DEBUGGER_EN(MSG)) -+ pr_info("config request id = %d", user_request.id); ++ rga_log("config request id = %d", user_request.id); + + request = rga_request_config(&user_request); + if (IS_ERR_OR_NULL(request)) { -+ pr_err("request[%d] config failed!\n", user_request.id); ++ rga_err("request[%d] config failed!\n", user_request.id); + return -EFAULT; + } + + if (run_enbale) { + ret = rga_request_submit(request); + if (ret < 0) { -+ pr_err("request[%d] submit failed!\n", user_request.id); ++ rga_err("request[%d] submit failed!\n", user_request.id); + return -EFAULT; + } + @@ -1905813,7 +1906940,7 @@ index 000000000..2d80c8089 + user_request.release_fence_fd = request->release_fence_fd; + if (copy_to_user((struct rga_req *)arg, + &user_request, sizeof(user_request))) { -+ pr_err("copy_to_user failed\n"); ++ rga_err("copy_to_user failed\n"); + return -EFAULT; + } + } @@ -1905834,23 +1906961,23 @@ index 000000000..2d80c8089 + + request_manager = rga_drvdata->pend_request_manager; + if (request_manager == NULL) { -+ pr_err("rga_pending_request_manager is null!\n"); ++ rga_err("rga_pending_request_manager is null!\n"); + return -EFAULT; + } + + if (unlikely(copy_from_user(&id, (uint32_t *)arg, sizeof(uint32_t)))) { -+ pr_err("request id copy_from_user failed!\n"); ++ rga_err("request id copy_from_user failed!\n"); + return -EFAULT; + } + + if (DEBUGGER_EN(MSG)) -+ pr_info("config cancel request id = %d", id); ++ rga_log("config cancel request id = %d", id); + + mutex_lock(&request_manager->lock); + + request = rga_request_lookup(request_manager, id); + if (IS_ERR_OR_NULL(request)) { -+ pr_err("can not find request from id[%d]", id); ++ rga_err("can not find request from id[%d]", id); + mutex_unlock(&request_manager->lock); + return -EINVAL; + } @@ -1905873,7 +1907000,7 @@ index 000000000..2d80c8089 + + request_id = rga_request_alloc(0, session); + if (request_id < 0) { -+ pr_err("request alloc error!\n"); ++ rga_err("request alloc error!\n"); + ret = request_id; + return ret; + } @@ -1905886,13 +1907013,13 @@ index 000000000..2d80c8089 + + ret = rga_request_check(&user_request); + if (ret < 0) { -+ pr_err("user request check error!\n"); ++ rga_err("ID[%d]: user request check error!\n", user_request.id); + goto err_free_request_by_id; + } + + request = rga_request_config(&user_request); + if (IS_ERR(request)) { -+ pr_err("request[%d] config failed!\n", user_request.id); ++ rga_err("ID[%d]: config failed!\n", user_request.id); + ret = -EFAULT; + goto err_free_request_by_id; + } @@ -1905903,14 +1907030,14 @@ index 000000000..2d80c8089 + + ret = rga_request_submit(request); + if (ret < 0) { -+ pr_err("request[%d] submit failed!\n", user_request.id); ++ rga_req_err(request, "submit failed!\n"); + goto err_put_request; + } + + if (request->sync_mode == RGA_BLIT_ASYNC) { + rga_req->out_fence_fd = request->release_fence_fd; + if (copy_to_user((struct rga_req *)arg, rga_req, sizeof(struct rga_req))) { -+ pr_err("copy_to_user failed\n"); ++ rga_req_err(request, "copy_to_user failed\n"); + ret = -EFAULT; + goto err_put_request; + } @@ -1905928,7 +1907055,7 @@ index 000000000..2d80c8089 + + request = rga_request_lookup(request_manager, request_id); + if (IS_ERR_OR_NULL(request)) { -+ pr_err("can not find request from id[%d]", request_id); ++ rga_err("can not find request from id[%d]", request_id); + mutex_unlock(&request_manager->lock); + return -EINVAL; + } @@ -1905952,13 +1907079,34 @@ index 000000000..2d80c8089 + struct rga_session *session = file->private_data; + + if (!rga) { -+ pr_err("rga_drvdata is null, rga is not init\n"); ++ rga_err("rga_drvdata is null, rga is not init\n"); + return -ENODEV; + } + + if (DEBUGGER_EN(NONUSE)) + return 0; + ++ if (cmd == RGA_BLIT_ASYNC && !IS_ENABLED(CONFIG_ROCKCHIP_RGA_ASYNC)) { ++ rga_log("The current driver does not support asynchronous mode, please enable CONFIG_ROCKCHIP_RGA_ASYNC.\n"); ++ ++ return -EINVAL; ++ } ++ ++ down_read(&session->release_rwsem); ++ down_read(&rga_drvdata->rwsem); ++ ++ if (rga_drvdata->shutdown || session->release) { ++ up_read(&rga_drvdata->rwsem); ++ up_read(&session->release_rwsem); ++ ++ if (rga_drvdata->shutdown) ++ rga_log("driver has been shutdown\n"); ++ else if (session->release) ++ rga_log("current session has been release\n"); ++ ++ return -EBUSY; ++ } ++ + switch (cmd) { + case RGA_BLIT_SYNC: + case RGA_BLIT_ASYNC: @@ -1906080,11 +1907228,14 @@ index 000000000..2d80c8089 + case RGA_IMPORT_DMA: + case RGA_RELEASE_DMA: + default: -+ pr_err("unknown ioctl cmd!\n"); ++ rga_err("unknown ioctl cmd!\n"); + ret = -EINVAL; + break; + } + ++ up_read(&rga_drvdata->rwsem); ++ up_read(&session->release_rwsem); ++ + return ret; +} + @@ -1906146,7 +1907297,18 @@ index 000000000..2d80c8089 +{ + struct rga_session *session = file->private_data; + -+ rga_session_deinit(session); ++ down_write(&session->release_rwsem); ++ ++ session->release = true; ++ ++ rga_request_session_destroy_abort(session); ++ rga_mm_session_release_buffer(session); ++ ++ up_write(&session->release_rwsem); ++ ++ rga_session_put(session); ++ ++ file->private_data = NULL; + + return 0; +} @@ -1906155,9 +1907317,26 @@ index 000000000..2d80c8089 +{ + irqreturn_t irq_ret = IRQ_NONE; + struct rga_scheduler_t *scheduler = data; ++ ktime_t timestamp = ktime_get(); + -+ if (scheduler->ops->irq) ++ spin_lock(&scheduler->irq_lock); ++ ++ if (scheduler->ops->irq) { + irq_ret = scheduler->ops->irq(scheduler); ++ if (irq_ret == IRQ_HANDLED) { ++ spin_unlock(&scheduler->irq_lock); ++ return irq_ret; ++ } ++ } ++ ++ if (scheduler->running_job == NULL) { ++ spin_unlock(&scheduler->irq_lock); ++ return IRQ_HANDLED; ++ } ++ ++ scheduler->running_job->timestamp.hw_done = timestamp; ++ ++ spin_unlock(&scheduler->irq_lock); + + return irq_ret; +} @@ -1906170,7 +1907349,7 @@ index 000000000..2d80c8089 + + job = rga_job_done(scheduler); + if (job == NULL) { -+ pr_err("isr thread invalid job!\n"); ++ rga_err("isr thread invalid job!\n"); + return IRQ_HANDLED; + } + @@ -1906202,103 +1907381,97 @@ index 000000000..2d80c8089 + .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_match_data_t old_rga2_match_data = { -+ .clks = old_rga2_clks, -+ .num_clks = ARRAY_SIZE(old_rga2_clks), -+}; -+ -+static const struct rga_match_data_t rk3588_rga2_match_data = { -+ .clks = rk3588_rga2_clks, -+ .num_clks = ARRAY_SIZE(rk3588_rga2_clks), -+}; -+ -+static const struct rga_match_data_t rga3_core0_match_data = { -+ .clks = rga3_core_0_clks, -+ .num_clks = ARRAY_SIZE(rga3_core_0_clks), ++static const struct rga_match_data_t rga2_match_data = { ++ .device_type = RGA_DEVICE_RGA2, ++ .ops = &rga2_ops, +}; + -+static const struct rga_match_data_t rga3_core1_match_data = { -+ .clks = rga3_core_1_clks, -+ .num_clks = ARRAY_SIZE(rga3_core_1_clks), ++static const struct rga_match_data_t rga3_match_data = { ++ .device_type = RGA_DEVICE_RGA3, ++ .ops = &rga3_ops, +}; + -+static const struct of_device_id rga3_core0_dt_ids[] = { ++static const struct of_device_id rga3_dt_ids[] = { ++ { ++ .compatible = "rockchip,rga3", ++ .data = &rga3_match_data, ++ }, ++ /* legacy */ + { + .compatible = "rockchip,rga3_core0", -+ .data = &rga3_core0_match_data, ++ .data = &rga3_match_data, + }, -+ {}, -+}; -+ -+static const struct of_device_id rga3_core1_dt_ids[] = { + { + .compatible = "rockchip,rga3_core1", -+ .data = &rga3_core1_match_data, ++ .data = &rga3_match_data, + }, + {}, +}; + +static const struct of_device_id rga2_dt_ids[] = { + { -+ .compatible = "rockchip,rga2_core0", -+ .data = &rk3588_rga2_match_data, ++ .compatible = "rockchip,rga2", ++ .data = &rga2_match_data, + }, ++ /* legacy */ + { -+ .compatible = "rockchip,rga2", -+ .data = &old_rga2_match_data, ++ .compatible = "rockchip,rga2_core0", ++ .data = &rga2_match_data, + }, + {}, +}; + -+static void init_scheduler(struct rga_scheduler_t *scheduler, -+ const char *name) ++static int init_scheduler(struct rga_scheduler_t *scheduler, ++ struct device *dev, ++ const struct rga_match_data_t *match_data, ++ struct rga_drvdata_t *drv_data) +{ ++ switch (match_data->device_type) { ++ case RGA_DEVICE_RGA2: ++ switch (drv_data->device_count[match_data->device_type]) { ++ case 0: ++ scheduler->core = RGA2_SCHEDULER_CORE0; ++ break; ++ case 1: ++ scheduler->core = RGA2_SCHEDULER_CORE1; ++ break; ++ default: ++ pr_err("scheduler failed to match RGA2\n"); ++ return -EINVAL; ++ } ++ ++ break; ++ case RGA_DEVICE_RGA3: ++ switch (drv_data->device_count[match_data->device_type]) { ++ case 0: ++ scheduler->core = RGA3_SCHEDULER_CORE0; ++ break; ++ case 1: ++ scheduler->core = RGA3_SCHEDULER_CORE1; ++ break; ++ default: ++ pr_err("scheduler failed to match RGA2\n"); ++ return -EINVAL; ++ } ++ ++ break; ++ default: ++ ++ return -EINVAL; ++ } ++ ++ scheduler->ops = match_data->ops; ++ scheduler->dev = dev; ++ + spin_lock_init(&scheduler->irq_lock); + INIT_LIST_HEAD(&scheduler->todo_list); + init_waitqueue_head(&scheduler->job_done_wq); + -+ if (!strcmp(name, "rga3_core0")) { -+ scheduler->ops = &rga3_ops; -+ /* TODO: get by hw version */ -+ scheduler->core = RGA3_SCHEDULER_CORE0; -+ } else if (!strcmp(name, "rga3_core1")) { -+ scheduler->ops = &rga3_ops; -+ scheduler->core = RGA3_SCHEDULER_CORE1; -+ } else if (!strcmp(name, "rga2")) { -+ scheduler->ops = &rga2_ops; -+ scheduler->core = RGA2_SCHEDULER_CORE0; -+ } ++ return 0; +} + +static int rga_drv_probe(struct platform_device *pdev) +{ -+#ifndef RGA_DISABLE_PM -+ int i; -+#endif + int ret = 0; + int irq; + struct resource *res; @@ -1906311,80 +1907484,73 @@ index 000000000..2d80c8089 + if (!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); ++ if (!strcmp(dev_driver_string(dev), "rga3")) ++ match = of_match_device(rga3_dt_ids, dev); + else if (!strcmp(dev_driver_string(dev), "rga2")) + match = of_match_device(rga2_dt_ids, dev); + else + match = NULL; -+ + if (!match) { -+ dev_err(dev, "%s missing DT entry!\n", dev_driver_string(dev)); ++ dev_err(dev, "missing DT entry!\n"); + return -EINVAL; + } + + scheduler = devm_kzalloc(dev, sizeof(struct rga_scheduler_t), GFP_KERNEL); + if (scheduler == NULL) { -+ pr_err("failed to allocate scheduler. dev name = %s\n", dev_driver_string(dev)); ++ dev_err(dev, "failed to allocate scheduler.\n"); + return -ENOMEM; + } + -+ init_scheduler(scheduler, dev_driver_string(dev)); -+ -+ scheduler->dev = dev; ++ match_data = match->data; ++ ret = init_scheduler(scheduler, dev, match_data, data); ++ if (ret < 0) { ++ dev_err(dev, "init scheduler failed!\n"); ++ return ret; ++ } + + /* map the registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { -+ pr_err("get memory resource failed.\n"); ++ dev_err(dev, "get memory resource failed.\n"); + return -ENXIO; + } + + scheduler->rga_base = devm_ioremap(dev, res->start, resource_size(res)); + if (!scheduler->rga_base) { -+ pr_err("ioremap failed\n"); ++ dev_err(dev, "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", dev_driver_string(dev)); ++ dev_err(dev, "no irq in dts\n"); + return irq; + } + + scheduler->irq = irq; + -+ pr_info("%s, irq = %d, match scheduler\n", dev_driver_string(dev), irq); -+ + ret = devm_request_threaded_irq(dev, irq, + rga_irq_handler, + rga_isr_thread, + IRQF_SHARED, + dev_driver_string(dev), scheduler); + if (ret < 0) { -+ pr_err("request irq name: %s failed: %d\n", dev_driver_string(dev), ret); ++ dev_err(dev, "request irq failed: %d\n", ret); + return ret; + } + + +#ifndef RGA_DISABLE_PM + /* clk init */ -+ 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]); -+ -+ scheduler->clks[i] = clk; ++ ret = devm_clk_bulk_get_all(dev, &scheduler->clks); ++ if (ret < 1) { ++ dev_err(dev, "failed to get clk\n"); ++ return ret < 0 ? ret : -EINVAL; + } -+ scheduler->num_clks = match_data->num_clks; ++ scheduler->num_clks = ret; + + /* PM init */ + device_init_wakeup(dev, true); @@ -1906392,47 +1907558,52 @@ index 000000000..2d80c8089 + + ret = pm_runtime_get_sync(scheduler->dev); + if (ret < 0) { -+ pr_err("failed to get pm runtime, ret = %d\n", ret); ++ dev_err(dev, "failed to get pm runtime, ret = %d\n", ret); + goto pm_disable; + } + -+ for (i = 0; i < scheduler->num_clks; i++) { -+ if (!IS_ERR(scheduler->clks[i])) { -+ ret = clk_prepare_enable(scheduler->clks[i]); -+ if (ret < 0) { -+ pr_err("failed to enable clk\n"); -+ goto pm_disable; -+ } -+ } ++ ret = clk_bulk_prepare_enable(scheduler->num_clks, scheduler->clks); ++ if (ret < 0) { ++ dev_err(dev, "failed to enable clk\n"); ++ goto pm_disable; + } +#endif /* #ifndef RGA_DISABLE_PM */ + + scheduler->ops->get_version(scheduler); -+ pr_info("%s hardware loaded successfully, hw_version:%s.\n", -+ dev_driver_string(dev), scheduler->version.str); + + /* TODO: get by hw version, Currently only supports judgment 1106. */ + if (scheduler->core == RGA3_SCHEDULER_CORE0 || + scheduler->core == RGA3_SCHEDULER_CORE1) { + scheduler->data = &rga3_data; -+ } else if (scheduler->core == RGA2_SCHEDULER_CORE0) { -+ if (!strcmp(scheduler->version.str, "3.3.87975")) ++ } else if (scheduler->core == RGA2_SCHEDULER_CORE0 || ++ scheduler->core == RGA2_SCHEDULER_CORE1) { ++ if (!strcmp(scheduler->version.str, "3.3.87975")) { + scheduler->data = &rga2e_1106_data; -+ else if (!strcmp(scheduler->version.str, "3.6.92812") || -+ !strcmp(scheduler->version.str, "3.7.93215")) ++ } else if (!strcmp(scheduler->version.str, "3.6.92812") || ++ !strcmp(scheduler->version.str, "3.7.93215")) { + scheduler->data = &rga2e_iommu_data; -+ else ++ } else if (!strcmp(scheduler->version.str, "3.a.07135")) { ++ scheduler->data = &rga2e_3506_data; ++ } else if (!strcmp(scheduler->version.str, "3.e.19357")) { ++ scheduler->data = &rga2p_iommu_data; ++ rga_hw_set_issue_mask(scheduler, RGA_HW_ISSUE_DIS_AUTO_RST); ++ } else if (!strcmp(scheduler->version.str, "3.f.23690")) { ++ scheduler->data = &rga2p_lite_1103b_data; ++ } else if (scheduler->version.major == 0x4 && ++ scheduler->version.minor == 0x1 && ++ scheduler->version.revision == 0x34669) { ++ scheduler->data = &rga2p_iommu_non_fbc_data; ++ } else { + scheduler->data = &rga2e_data; ++ } + } + + data->scheduler[data->num_of_scheduler] = scheduler; -+ + data->num_of_scheduler++; ++ data->device_count[match_data->device_type]++; + +#ifndef RGA_DISABLE_PM -+ for (i = scheduler->num_clks - 1; i >= 0; i--) -+ if (!IS_ERR(scheduler->clks[i])) -+ clk_disable_unprepare(scheduler->clks[i]); ++ clk_bulk_disable_unprepare(scheduler->num_clks, scheduler->clks); + + pm_runtime_put_sync(dev); +#endif /* #ifndef RGA_DISABLE_PM */ @@ -1906443,11 +1907614,18 @@ index 000000000..2d80c8089 + dev_err(dev, "failed to attach iommu\n"); + scheduler->iommu_info = NULL; + } ++ ++ dma_set_mask(dev, DMA_BIT_MASK(40)); ++ dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); ++ } else { ++ dma_set_mask(dev, DMA_BIT_MASK(32)); ++ dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); + } + + platform_set_drvdata(pdev, scheduler); + -+ pr_info("%s probe successfully\n", dev_driver_string(dev)); ++ dev_info(dev, "probe successfully, irq = %d, hw_version:%s\n", ++ scheduler->irq, scheduler->version.str); + + return 0; + @@ -1906460,37 +1907638,56 @@ index 000000000..2d80c8089 + return ret; +} + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0) +static int rga_drv_remove(struct platform_device *pdev) ++#else ++static void rga_drv_remove(struct platform_device *pdev) ++#endif +{ ++ struct rga_scheduler_t *scheduler = NULL; ++ ++ down_write(&rga_drvdata->rwsem); ++ rga_drvdata->shutdown = true; ++ ++ scheduler = (struct rga_scheduler_t *)platform_get_drvdata(pdev); ++ if (scheduler) ++ rga_request_scheduler_shutdown(scheduler); ++ +#ifndef RGA_DISABLE_PM + device_init_wakeup(&pdev->dev, false); + pm_runtime_disable(&pdev->dev); +#endif /* #ifndef RGA_DISABLE_PM */ + ++ up_write(&rga_drvdata->rwsem); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0) + return 0; ++#endif +} + -+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 void rga_drv_shutdown(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ ++ rga_drv_remove(pdev); ++ ++ dev_info(dev, "shutdown success\n"); ++} + -+static struct platform_driver rga3_core1_driver = { ++static struct platform_driver rga3_driver = { + .probe = rga_drv_probe, + .remove = rga_drv_remove, ++ .shutdown = rga_drv_shutdown, + .driver = { -+ .name = "rga3_core1", -+ .of_match_table = of_match_ptr(rga3_core1_dt_ids), ++ .name = "rga3", ++ .of_match_table = of_match_ptr(rga3_dt_ids), + }, +}; + +static struct platform_driver rga2_driver = { + .probe = rga_drv_probe, + .remove = rga_drv_remove, ++ .shutdown = rga_drv_shutdown, + .driver = { + .name = "rga2", + .of_match_table = of_match_ptr(rga2_dt_ids), @@ -1906508,23 +1907705,18 @@ index 000000000..2d80c8089 + } + + mutex_init(&rga_drvdata->lock); ++ init_rwsem(&rga_drvdata->rwsem); ++ rga_drvdata->shutdown = false; + -+ ret = platform_driver_register(&rga3_core0_driver); ++ ret = platform_driver_register(&rga3_driver); + if (ret != 0) { -+ pr_err("Platform device rga3_core0_driver register failed (%d).\n", ret); ++ pr_err("Platform device rga3_driver register failed (%d).\n", ret); + goto err_free_drvdata; + } -+ -+ ret = platform_driver_register(&rga3_core1_driver); -+ if (ret != 0) { -+ pr_err("Platform device rga3_core1_driver register failed (%d).\n", ret); -+ goto err_unregister_rga3_core0; -+ } -+ + ret = platform_driver_register(&rga2_driver); + if (ret != 0) { + pr_err("Platform device rga2_driver register failed (%d).\n", ret); -+ goto err_unregister_rga3_core1; ++ goto err_unregister_rga3; + } + + ret = rga_iommu_bind(); @@ -1906565,11 +1907757,8 @@ index 000000000..2d80c8089 +err_unregister_rga2: + platform_driver_unregister(&rga2_driver); + -+err_unregister_rga3_core1: -+ platform_driver_unregister(&rga3_core1_driver); -+ -+err_unregister_rga3_core0: -+ platform_driver_unregister(&rga3_core0_driver); ++err_unregister_rga3: ++ platform_driver_unregister(&rga3_driver); + +err_free_drvdata: + kfree(rga_drvdata); @@ -1906597,8 +1907786,7 @@ index 000000000..2d80c8089 + + rga_iommu_unbind(); + -+ platform_driver_unregister(&rga3_core0_driver); -+ platform_driver_unregister(&rga3_core1_driver); ++ platform_driver_unregister(&rga3_driver); + platform_driver_unregister(&rga2_driver); + + misc_deregister(&rga_dev); @@ -1906631,10 +1907819,10 @@ index 000000000..2d80c8089 +#endif diff --git a/drivers/video/rockchip/rga3/rga_fence.c b/drivers/video/rockchip/rga3/rga_fence.c new file mode 100644 -index 000000000..7d831d55d +index 000000000..9c663f3be --- /dev/null +++ b/drivers/video/rockchip/rga3/rga_fence.c -@@ -0,0 +1,146 @@ +@@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1906642,14 +1907830,13 @@ index 000000000..7d831d55d + * Author: Huang Lee + */ + -+#define pr_fmt(fmt) "rga_fence: " fmt -+ +#include +#include +#include + +#include "rga_drv.h" +#include "rga_fence.h" ++#include "rga_common.h" + +static const char *rga_fence_get_name(struct dma_fence *fence) +{ @@ -1906694,7 +1907881,7 @@ index 000000000..7d831d55d + struct dma_fence *fence = NULL; + + if (fence_ctx == NULL) { -+ pr_err("fence_context is NULL!\n"); ++ rga_err("fence_context is NULL!\n"); + return ERR_PTR(-EINVAL); + } + @@ -1906737,7 +1907924,7 @@ index 000000000..7d831d55d + + fence = sync_file_get_fence(fence_fd); + if (!fence) -+ pr_err("can not get fence from fd\n"); ++ rga_err("can not get fence from fd\n"); + + return fence; +} @@ -1906760,7 +1907947,7 @@ index 000000000..7d831d55d + + waiter = kmalloc(sizeof(*waiter), GFP_KERNEL); + if (!waiter) { -+ pr_err("%s: Failed to allocate waiter\n", __func__); ++ rga_err("%s: Failed to allocate waiter\n", __func__); + return -ENOMEM; + } + @@ -1906768,10 +1907955,10 @@ index 000000000..7d831d55d + + ret = dma_fence_add_callback(fence, &waiter->waiter, func); + if (ret == -ENOENT) { -+ pr_err("'input fence' has been already signaled."); ++ rga_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); ++ rga_err("%s: failed to add callback to dma_fence, err: %d\n", __func__, ret); + goto err_free_waiter; + } + @@ -1906783,10 +1907970,10 @@ index 000000000..7d831d55d +} diff --git a/drivers/video/rockchip/rga3/rga_hw_config.c b/drivers/video/rockchip/rga3/rga_hw_config.c new file mode 100644 -index 000000000..0cf2599b9 +index 000000000..d558c1513 --- /dev/null +++ b/drivers/video/rockchip/rga3/rga_hw_config.c -@@ -0,0 +1,352 @@ +@@ -0,0 +1,743 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1906803,6 +1907990,8 @@ index 000000000..0cf2599b9 +const uint32_t rga3_input_raster_format[] = { + RGA_FORMAT_RGBA_8888, + RGA_FORMAT_BGRA_8888, ++ RGA_FORMAT_RGBX_8888, ++ RGA_FORMAT_BGRX_8888, + RGA_FORMAT_RGB_888, + RGA_FORMAT_BGR_888, + RGA_FORMAT_RGB_565, @@ -1906826,6 +1908015,8 @@ index 000000000..0cf2599b9 +const uint32_t rga3_output_raster_format[] = { + RGA_FORMAT_RGBA_8888, + RGA_FORMAT_BGRA_8888, ++ RGA_FORMAT_RGBX_8888, ++ RGA_FORMAT_BGRX_8888, + RGA_FORMAT_RGB_888, + RGA_FORMAT_BGR_888, + RGA_FORMAT_RGB_565, @@ -1906847,6 +1908038,8 @@ index 000000000..0cf2599b9 +const uint32_t rga3_fbcd_format[] = { + RGA_FORMAT_RGBA_8888, + RGA_FORMAT_BGRA_8888, ++ RGA_FORMAT_RGBX_8888, ++ RGA_FORMAT_BGRX_8888, + RGA_FORMAT_RGB_888, + RGA_FORMAT_BGR_888, + RGA_FORMAT_RGB_565, @@ -1906898,10 +1908091,6 @@ index 000000000..0cf2599b9 + RGA_FORMAT_YCbCr_422_SP_10B, + RGA_FORMAT_YCrCb_422_SP_10B, + RGA_FORMAT_YCbCr_400, -+ RGA_FORMAT_RGBA_5551, -+ RGA_FORMAT_BGRA_5551, -+ RGA_FORMAT_RGBA_4444, -+ RGA_FORMAT_BGRA_4444, + RGA_FORMAT_XRGB_8888, + RGA_FORMAT_XBGR_8888, + RGA_FORMAT_BPP1, @@ -1906947,6 +1908136,112 @@ index 000000000..0cf2599b9 + RGA_FORMAT_YCrCb_422_SP_10B, + RGA_FORMAT_Y4, + RGA_FORMAT_YCbCr_400, ++ RGA_FORMAT_XRGB_8888, ++ RGA_FORMAT_XBGR_8888, ++ RGA_FORMAT_ARGB_8888, ++ RGA_FORMAT_ARGB_5551, ++ RGA_FORMAT_ARGB_4444, ++ RGA_FORMAT_ABGR_8888, ++ RGA_FORMAT_ABGR_5551, ++ RGA_FORMAT_ABGR_4444, ++}; ++ ++const uint32_t rga2p_input_raster_format[] = { ++ RGA_FORMAT_RGBA_8888, ++ RGA_FORMAT_RGBX_8888, ++ RGA_FORMAT_BGRA_8888, ++ RGA_FORMAT_BGRX_8888, ++ RGA_FORMAT_RGB_888, ++ RGA_FORMAT_BGR_888, ++ RGA_FORMAT_RGB_565, ++ RGA_FORMAT_BGR_565, ++ RGA_FORMAT_YCbCr_422_P, ++ RGA_FORMAT_YCbCr_420_P, ++ RGA_FORMAT_YCrCb_422_P, ++ RGA_FORMAT_YCrCb_420_P, ++ RGA_FORMAT_YCbCr_422_SP, ++ RGA_FORMAT_YCbCr_420_SP, ++ RGA_FORMAT_YCrCb_422_SP, ++ RGA_FORMAT_YCrCb_420_SP, ++ RGA_FORMAT_YVYU_422, ++ RGA_FORMAT_VYUY_422, ++ RGA_FORMAT_YUYV_422, ++ RGA_FORMAT_UYVY_422, ++ RGA_FORMAT_YCbCr_420_SP_10B, ++ RGA_FORMAT_YCrCb_420_SP_10B, ++ RGA_FORMAT_YCbCr_422_SP_10B, ++ RGA_FORMAT_YCrCb_422_SP_10B, ++ RGA_FORMAT_YCbCr_400, ++ RGA_FORMAT_XRGB_8888, ++ RGA_FORMAT_XBGR_8888, ++ RGA_FORMAT_BPP1, ++ RGA_FORMAT_BPP2, ++ RGA_FORMAT_BPP4, ++ RGA_FORMAT_BPP8, ++ RGA_FORMAT_ARGB_8888, ++ RGA_FORMAT_ARGB_5551, ++ RGA_FORMAT_ARGB_4444, ++ RGA_FORMAT_ABGR_8888, ++ RGA_FORMAT_ABGR_5551, ++ RGA_FORMAT_ABGR_4444, ++ RGA_FORMAT_RGBA_2BPP, ++ RGA_FORMAT_A8, ++ RGA_FORMAT_YCbCr_444_SP, ++ RGA_FORMAT_YCrCb_444_SP, ++}; ++ ++const uint32_t rga2p_input1_raster_format[] = { ++ RGA_FORMAT_RGBA_8888, ++ RGA_FORMAT_BGRA_8888, ++ RGA_FORMAT_RGBX_8888, ++ RGA_FORMAT_BGRX_8888, ++ RGA_FORMAT_XRGB_8888, ++ RGA_FORMAT_XBGR_8888, ++ RGA_FORMAT_ARGB_8888, ++ RGA_FORMAT_ABGR_8888, ++ RGA_FORMAT_ARGB_5551, ++ RGA_FORMAT_ABGR_5551, ++ RGA_FORMAT_ARGB_4444, ++ RGA_FORMAT_ABGR_4444, ++ RGA_FORMAT_RGB_888, ++ RGA_FORMAT_BGR_888, ++ RGA_FORMAT_RGB_565, ++ RGA_FORMAT_BGR_565, ++ RGA_FORMAT_A8, ++}; ++ ++const uint32_t rga2p_output_raster_format[] = { ++ RGA_FORMAT_RGBA_8888, ++ RGA_FORMAT_RGBX_8888, ++ RGA_FORMAT_BGRA_8888, ++ RGA_FORMAT_BGRX_8888, ++ RGA_FORMAT_RGB_888, ++ RGA_FORMAT_BGR_888, ++ RGA_FORMAT_RGB_565, ++ RGA_FORMAT_BGR_565, ++ RGA_FORMAT_YCbCr_422_P, ++ RGA_FORMAT_YCbCr_420_P, ++ RGA_FORMAT_YCrCb_422_P, ++ RGA_FORMAT_YCrCb_420_P, ++ RGA_FORMAT_YCbCr_422_SP, ++ RGA_FORMAT_YCbCr_420_SP, ++ RGA_FORMAT_YCrCb_422_SP, ++ RGA_FORMAT_YCrCb_420_SP, ++ RGA_FORMAT_YVYU_420, ++ RGA_FORMAT_VYUY_420, ++ RGA_FORMAT_YUYV_420, ++ RGA_FORMAT_UYVY_420, ++ RGA_FORMAT_YVYU_422, ++ RGA_FORMAT_VYUY_422, ++ RGA_FORMAT_YUYV_422, ++ RGA_FORMAT_UYVY_422, ++ RGA_FORMAT_YCbCr_420_SP_10B, ++ RGA_FORMAT_YCrCb_420_SP_10B, ++ RGA_FORMAT_YCbCr_422_SP_10B, ++ RGA_FORMAT_YCrCb_422_SP_10B, ++ RGA_FORMAT_Y4, ++ RGA_FORMAT_Y8, ++ RGA_FORMAT_YCbCr_400, + RGA_FORMAT_RGBA_5551, + RGA_FORMAT_BGRA_5551, + RGA_FORMAT_RGBA_4444, @@ -1906959,6 +1908254,49 @@ index 000000000..0cf2599b9 + RGA_FORMAT_ABGR_8888, + RGA_FORMAT_ABGR_5551, + RGA_FORMAT_ABGR_4444, ++ RGA_FORMAT_YCbCr_444_SP, ++ RGA_FORMAT_YCrCb_444_SP, ++}; ++ ++const uint32_t rga2p_tile4x4_format[] = { ++ RGA_FORMAT_YCbCr_400, ++ RGA_FORMAT_YCbCr_420_SP, ++ RGA_FORMAT_YCrCb_420_SP, ++ RGA_FORMAT_YCbCr_422_SP, ++ RGA_FORMAT_YCrCb_422_SP, ++ RGA_FORMAT_YCbCr_444_SP, ++ RGA_FORMAT_YCrCb_444_SP, ++ RGA_FORMAT_YCbCr_420_SP_10B, ++ RGA_FORMAT_YCrCb_420_SP_10B, ++ RGA_FORMAT_YCbCr_422_SP_10B, ++ RGA_FORMAT_YCrCb_422_SP_10B, ++}; ++ ++const uint32_t rga2p_rkfbc64x4_format[] = { ++ RGA_FORMAT_YCbCr_400, ++ RGA_FORMAT_YCbCr_420_SP, ++ RGA_FORMAT_YCrCb_420_SP, ++ RGA_FORMAT_YCbCr_422_SP, ++ RGA_FORMAT_YCrCb_422_SP, ++ RGA_FORMAT_YCbCr_444_SP, ++ RGA_FORMAT_YCrCb_444_SP, ++ RGA_FORMAT_YCbCr_420_SP_10B, ++ RGA_FORMAT_YCrCb_420_SP_10B, ++ RGA_FORMAT_YCbCr_422_SP_10B, ++ RGA_FORMAT_YCrCb_422_SP_10B, ++}; ++ ++const uint32_t rga2p_afbc32x8_format[] = { ++ RGA_FORMAT_RGBA_8888, ++ RGA_FORMAT_BGRA_8888, ++ RGA_FORMAT_RGBX_8888, ++ RGA_FORMAT_BGRX_8888, ++ RGA_FORMAT_XRGB_8888, ++ RGA_FORMAT_XBGR_8888, ++ RGA_FORMAT_ARGB_8888, ++ RGA_FORMAT_ABGR_8888, ++ RGA_FORMAT_RGB_888, ++ RGA_FORMAT_BGR_888, +}; + +const struct rga_win_data rga3_win_data[] = { @@ -1907006,13 +1908344,139 @@ index 000000000..0cf2599b9 + .rd_mode = RGA_RASTER_MODE | RGA_FBC_MODE | RGA_TILE_MODE, + + }, -+}; ++}; ++ ++const struct rga_win_data rga2e_win_data[] = { ++ { ++ .name = "rga2e-src0", ++ .formats[RGA_RASTER_INDEX] = rga2e_input_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2e_input_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", ++ .formats[RGA_RASTER_INDEX] = rga2e_input_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2e_input_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", ++ .formats[RGA_RASTER_INDEX] = rga2e_output_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2e_output_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_win_data rga2e_3506_win_data[] = { ++ { ++ .name = "rga2e-src0", ++ .formats[RGA_RASTER_INDEX] = rga2e_input_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2e_input_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", ++ .formats[RGA_RASTER_INDEX] = rga2p_input_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2p_input_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", ++ .formats[RGA_RASTER_INDEX] = rga2e_output_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2e_output_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_win_data rga2p_win_data[] = { ++ { ++ .name = "rga2p-src0", ++ .formats[RGA_RASTER_INDEX] = rga2p_input_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2p_input_raster_format), ++ .formats[RGA_TILE4x4_INDEX] = rga2p_tile4x4_format, ++ .formats_count[RGA_TILE4x4_INDEX] = ARRAY_SIZE(rga2p_tile4x4_format), ++ .formats[RGA_RKFBC64x4_INDEX] = rga2p_rkfbc64x4_format, ++ .formats_count[RGA_RKFBC64x4_INDEX] = ARRAY_SIZE(rga2p_rkfbc64x4_format), ++ .formats[RGA_AFBC32x8_INDEX] = rga2p_afbc32x8_format, ++ .formats_count[RGA_AFBC32x8_INDEX] = ARRAY_SIZE(rga2p_afbc32x8_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_TILE4x4_MODE | RGA_RKFBC_MODE | RGA_AFBC32x8_MODE, ++ ++ }, ++ ++ { ++ .name = "rga2p-src1", ++ .formats[RGA_RASTER_INDEX] = rga2p_input1_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2p_input1_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 | RGA_TILE4x4_MODE | RGA_RKFBC_MODE | RGA_AFBC32x8_MODE, ++ ++ }, ++ ++ { ++ .name = "rga2p-dst", ++ .formats[RGA_RASTER_INDEX] = rga2p_output_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2p_output_raster_format), ++ .formats[RGA_TILE4x4_INDEX] = rga2p_tile4x4_format, ++ .formats_count[RGA_TILE4x4_INDEX] = ARRAY_SIZE(rga2p_tile4x4_format), ++ .supported_rotations = 0, ++ .scale_up_mode = RGA_SCALE_UP_NONE, ++ .scale_down_mode = RGA_SCALE_DOWN_NONE, ++ .rd_mode = RGA_RASTER_MODE | RGA_TILE4x4_MODE, ++ ++ }, ++}; ++ ++const struct rga_win_data rga2p_non_fbc_win_data[] = { ++ { ++ .name = "rga2p-src0", ++ .formats[RGA_RASTER_INDEX] = rga2p_input_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2p_input_raster_format), ++ .formats[RGA_TILE4x4_INDEX] = rga2p_tile4x4_format, ++ .formats_count[RGA_TILE4x4_INDEX] = ARRAY_SIZE(rga2p_tile4x4_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_TILE4x4_MODE, ++ ++ }, + -+const struct rga_win_data rga2e_win_data[] = { + { -+ .name = "rga2e-src0", -+ .formats[RGA_RASTER_INDEX] = rga2e_input_raster_format, -+ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2e_input_raster_format), ++ .name = "rga2p-src1", ++ .formats[RGA_RASTER_INDEX] = rga2p_input1_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2p_input1_raster_format), + .supported_rotations = RGA_MODE_ROTATE_MASK, + .scale_up_mode = RGA_SCALE_UP_BIC, + .scale_down_mode = RGA_SCALE_DOWN_AVG, @@ -1907021,7 +1908485,20 @@ index 000000000..0cf2599b9 + }, + + { -+ .name = "rga2e-src1", ++ .name = "rga2p-dst", ++ .formats[RGA_RASTER_INDEX] = rga2p_output_raster_format, ++ .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2p_output_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_win_data rga2p_lite_win_data[] = { ++ { ++ .name = "rga2e-src0", + .formats[RGA_RASTER_INDEX] = rga2e_input_raster_format, + .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga2e_input_raster_format), + .supported_rotations = RGA_MODE_ROTATE_MASK, @@ -1907082,7 +1908559,8 @@ index 000000000..0cf2599b9 + .feature = RGA_COLOR_FILL | RGA_COLOR_PALETTE | + RGA_COLOR_KEY | RGA_ROP_CALCULATE | + RGA_NN_QUANTIZE | RGA_DITHER | RGA_FULL_CSC, -+ .csc_r2y_mode = RGA_MODE_CSC_BT601L | RGA_MODE_CSC_BT601F, ++ .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, + .mmu = RGA_MMU, @@ -1907114,6 +1908592,30 @@ index 000000000..0cf2599b9 + .mmu = RGA_NONE_MMU, +}; + ++const struct rga_hw_data rga2e_3506_data = { ++ .version = 0, ++ .input_range = {{2, 2}, {1280, 8192}}, ++ .output_range = {{2, 2}, {1280, 4096}}, ++ ++ .win = rga2e_3506_win_data, ++ .win_size = ARRAY_SIZE(rga2e_3506_win_data), ++ /* 1 << factor mean real factor */ ++ .max_upscale_factor = 4, ++ .max_downscale_factor = 4, ++ ++ .byte_stride_align = 4, ++ .max_byte_stride = WORD_TO_BYTE(8192), ++ ++ .feature = RGA_COLOR_FILL | RGA_COLOR_PALETTE | ++ RGA_COLOR_KEY | RGA_YIN_YOUT | RGA_YUV_HDS | RGA_YUV_VDS | ++ RGA_PRE_INTR | RGA_FULL_CSC | RGA_GAUSS, ++ .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, ++ .mmu = RGA_NONE_MMU, ++}; ++ +const struct rga_hw_data rga2e_iommu_data = { + .version = 0, + .input_range = {{2, 2}, {8192, 8192}}, @@ -1907139,12 +1908641,88 @@ index 000000000..0cf2599b9 + RGA_MODE_CSC_BT709, + .mmu = RGA_IOMMU, +}; ++ ++const struct rga_hw_data rga2p_iommu_data = { ++ .version = 0, ++ .input_range = {{2, 2}, {8192, 8192}}, ++ .output_range = {{2, 2}, {8192, 8192}}, ++ ++ .win = rga2p_win_data, ++ .win_size = ARRAY_SIZE(rga2p_win_data), ++ /* 1 << factor mean real factor */ ++ .max_upscale_factor = 4, ++ .max_downscale_factor = 4, ++ ++ .byte_stride_align = 4, ++ .max_byte_stride = WORD_TO_BYTE(8192), ++ ++ .feature = RGA_COLOR_FILL | RGA_COLOR_PALETTE | ++ RGA_COLOR_KEY | RGA_ROP_CALCULATE | ++ RGA_NN_QUANTIZE | RGA_DITHER | RGA_MOSAIC | ++ RGA_YIN_YOUT | RGA_YUV_HDS | RGA_YUV_VDS | ++ RGA_OSD | RGA_PRE_INTR | RGA_FULL_CSC, ++ .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, ++ .mmu = RGA_IOMMU, ++}; ++ ++const struct rga_hw_data rga2p_lite_1103b_data = { ++ .version = 0, ++ .input_range = {{2, 2}, {2880, 8192}}, ++ .output_range = {{2, 2}, {2880, 8192}}, ++ ++ .win = rga2p_lite_win_data, ++ .win_size = ARRAY_SIZE(rga2p_lite_win_data), ++ /* 1 << factor mean real factor */ ++ .max_upscale_factor = 4, ++ .max_downscale_factor = 4, ++ ++ .byte_stride_align = 4, ++ .max_byte_stride = WORD_TO_BYTE(8192), ++ ++ .feature = RGA_COLOR_FILL | RGA_DITHER | RGA_YIN_YOUT | ++ RGA_YUV_HDS | RGA_YUV_VDS | ++ RGA_PRE_INTR | RGA_FULL_CSC, ++ .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, ++ .mmu = RGA_NONE_MMU, ++}; ++ ++const struct rga_hw_data rga2p_iommu_non_fbc_data = { ++ /* Register have changed, so the version is increased. */ ++ .version = 1, ++ .input_range = {{2, 2}, {8192, 8192}}, ++ .output_range = {{2, 2}, {8192, 8192}}, ++ ++ .win = rga2p_non_fbc_win_data, ++ .win_size = ARRAY_SIZE(rga2p_non_fbc_win_data), ++ /* 1 << factor mean real factor */ ++ .max_upscale_factor = 4, ++ .max_downscale_factor = 4, ++ ++ .byte_stride_align = 4, ++ .max_byte_stride = WORD_TO_BYTE(8192), ++ ++ .feature = RGA_COLOR_FILL | RGA_COLOR_PALETTE | ++ RGA_COLOR_KEY | RGA_DITHER | ++ RGA_YIN_YOUT | RGA_YUV_HDS | RGA_YUV_VDS | ++ RGA_OSD | RGA_PRE_INTR | RGA_FULL_CSC, ++ .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, ++ .mmu = RGA_IOMMU, ++}; diff --git a/drivers/video/rockchip/rga3/rga_iommu.c b/drivers/video/rockchip/rga3/rga_iommu.c new file mode 100644 -index 000000000..6ef9cbc0d +index 000000000..4a3223e83 --- /dev/null +++ b/drivers/video/rockchip/rga3/rga_iommu.c -@@ -0,0 +1,425 @@ +@@ -0,0 +1,411 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1907152,8 +1908730,6 @@ index 000000000..6ef9cbc0d + * Author: Huang Lee + */ + -+#define pr_fmt(fmt) "rga_iommu: " fmt -+ +#include "rga_iommu.h" +#include "rga_dma_buf.h" +#include "rga_mm.h" @@ -1907184,11 +1908760,11 @@ index 000000000..6ef9cbc0d + } + + if (flag == 1) { -+ pr_info("src user memory check\n"); -+ pr_info("tai data is %d\n", *tai_vaddr); ++ rga_log("src user memory check\n"); ++ rga_log("tai data is %d\n", *tai_vaddr); + } else { -+ pr_info("dst user memory check\n"); -+ pr_info("tai data is %d\n", *tai_vaddr); ++ rga_log("dst user memory check\n"); ++ rga_log("tai data is %d\n", *tai_vaddr); + } + + if (taidata_num == 0) @@ -1907247,14 +1908823,14 @@ index 000000000..6ef9cbc0d + + if ((t->back - t->front) > t->size) { + if (t->front + size > t->back - t->size) { -+ pr_info("front %d, back %d dsize %d size %d", ++ rga_log("front %d, back %d dsize %d size %d", + t->front, t->back, t->size, size); + ret = -ENOMEM; + goto out; + } + } else { + if ((t->front + size) > t->back) { -+ pr_info("front %d, back %d dsize %d size %d", ++ rga_log("front %d, back %d dsize %d size %d", + t->front, t->back, t->size, size); + ret = -ENOMEM; + goto out; @@ -1907262,7 +1908838,7 @@ index 000000000..6ef9cbc0d + + if (t->front + size > t->size) { + if (size > (t->back - t->size)) { -+ pr_info("front %d, back %d dsize %d size %d", ++ rga_log("front %d, back %d dsize %d size %d", + t->front, t->back, t->size, size); + ret = -ENOMEM; + goto out; @@ -1907285,7 +1908861,7 @@ index 000000000..6ef9cbc0d + + ret = rga_mmu_buf_get_try(mmu_base, size); + if (ret < 0) { -+ pr_err("Get MMU mem failed\n"); ++ rga_err("Get MMU mem failed\n"); + return NULL; + } + @@ -1907316,28 +1908892,16 @@ index 000000000..6ef9cbc0d + * malloc pre scale mid buf mmu table: + * size * channel_num * address_size + */ -+ order = get_order(size * 3 * sizeof(*mmu_base->buf_virtual)); -+ if (order >= MAX_ORDER) { -+ pr_err("Can not alloc pages with order[%d] for mmu_page_table, max_order = %d\n", -+ order, MAX_ORDER); -+ goto err_free_mmu_base; -+ } -+ -+ mmu_base->buf_virtual = (uint32_t *) __get_free_pages(GFP_KERNEL | GFP_DMA32, order); ++ mmu_base->buf_virtual = (uint32_t *)rga_get_free_pages(GFP_KERNEL | GFP_DMA32, ++ &order, size * 3 * sizeof(*mmu_base->buf_virtual)); + if (mmu_base->buf_virtual == NULL) { + pr_err("Can not alloc pages for mmu_page_table\n"); + goto err_free_mmu_base; + } + mmu_base->buf_order = order; + -+ order = get_order(size * sizeof(*mmu_base->pages)); -+ if (order >= MAX_ORDER) { -+ pr_err("Can not alloc pages with order[%d] for mmu_base->pages, max_order = %d\n", -+ order, MAX_ORDER); -+ goto err_free_buf_virtual; -+ } -+ -+ mmu_base->pages = (struct page **)__get_free_pages(GFP_KERNEL | GFP_DMA32, order); ++ mmu_base->pages = (struct page **)rga_get_free_pages(GFP_KERNEL | GFP_DMA32, ++ &order, size * sizeof(*mmu_base->pages)); + if (mmu_base->pages == NULL) { + pr_err("Can not alloc pages for mmu_base->pages\n"); + goto err_free_buf_virtual; @@ -1907389,7 +1908953,7 @@ index 000000000..6ef9cbc0d + if (job == NULL) + return 0; + -+ pr_err("IOMMU intr fault, IOVA[0x%lx], STATUS[0x%x]\n", iova, status); ++ rga_err("IOMMU intr fault, IOVA[0x%lx], STATUS[0x%x]\n", iova, status); + if (scheduler->ops->irq) + scheduler->ops->irq(scheduler); + @@ -1907400,13 +1908964,13 @@ index 000000000..6ef9cbc0d + } + + if (status & RGA_IOMMU_IRQ_PAGE_FAULT) { -+ pr_err("RGA IOMMU: page fault! Please check the memory size.\n"); ++ rga_err("RGA IOMMU: page fault! Please check the memory size.\n"); + job->ret = -EACCES; + } else if (status & RGA_IOMMU_IRQ_BUS_ERROR) { -+ pr_err("RGA IOMMU: bus error! Please check if the memory is invalid or has been freed.\n"); ++ rga_err("RGA IOMMU: bus error! Please check if the memory is invalid or has been freed.\n"); + job->ret = -EACCES; + } else { -+ pr_err("RGA IOMMU: Wrong IOMMU interrupt signal!\n"); ++ rga_err("RGA IOMMU: Wrong IOMMU interrupt signal!\n"); + } + + return 0; @@ -1907572,10 +1909136,10 @@ index 000000000..6ef9cbc0d +} diff --git a/drivers/video/rockchip/rga3/rga_job.c b/drivers/video/rockchip/rga3/rga_job.c new file mode 100644 -index 000000000..fae613bbf +index 000000000..93e47be00 --- /dev/null +++ b/drivers/video/rockchip/rga3/rga_job.c -@@ -0,0 +1,1423 @@ +@@ -0,0 +1,1558 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1907583,8 +1909147,6 @@ index 000000000..fae613bbf + * Author: Huang Lee + */ + -+#define pr_fmt(fmt) "rga_job: " fmt -+ +#include "rga_job.h" +#include "rga_fence.h" +#include "rga_dma_buf.h" @@ -1907595,7 +1909157,10 @@ index 000000000..fae613bbf + +static void rga_job_free(struct rga_job *job) +{ -+ free_page((unsigned long)job); ++ if (job->cmd_buf) ++ rga_dma_free(job->cmd_buf); ++ ++ kfree(job); +} + +static void rga_job_kref_release(struct kref *ref) @@ -1907621,11 +1909186,6 @@ index 000000000..fae613bbf +{ + rga_job_put(job); + -+ if (DEBUGGER_EN(TIME)) -+ pr_info("request[%d], job cleanup total cost time %lld us\n", -+ job->request_id, -+ ktime_us_delta(ktime_get(), job->timestamp)); -+ + return 0; +} + @@ -1907639,7 +1909199,7 @@ index 000000000..fae613bbf + req = &job->rga_command_base; + mm = rga_drvdata->mm; + if (mm == NULL) { -+ pr_err("rga mm is null!\n"); ++ rga_job_err(job, "rga mm is null!\n"); + return -EFAULT; + } + @@ -1907694,14 +1909254,14 @@ index 000000000..fae613bbf +{ + struct rga_job *job = NULL; + -+ job = (struct rga_job *)get_zeroed_page(GFP_KERNEL | GFP_DMA32); ++ job = kzalloc(sizeof(*job), GFP_KERNEL); + if (!job) + return NULL; + + INIT_LIST_HEAD(&job->head); + kref_init(&job->refcount); + -+ job->timestamp = ktime_get(); ++ job->timestamp.init = ktime_get(); + job->pid = current->pid; + + job->rga_command_base = *rga_command_base; @@ -1907713,6 +1909273,13 @@ index 000000000..fae613bbf + job->priority = rga_command_base->priority; + } + ++ if (DEBUGGER_EN(INTERNAL_MODE)) { ++ job->flags |= RGA_JOB_DEBUG_FAKE_BUFFER; ++ ++ /* skip subsequent flag judgments. */ ++ return job; ++ } ++ + if (job->rga_command_base.handle_flag & 1) { + job->flags |= RGA_JOB_USE_HANDLE; + @@ -1907722,33 +1909289,6 @@ index 000000000..fae613bbf + return job; +} + -+static void rga_job_dump_info(struct rga_job *job) -+{ -+ pr_info("job: reqeust_id = %d, priority = %d, core = %d\n", -+ job->request_id, job->priority, job->core); -+} -+ -+void rga_job_scheduler_dump_info(struct rga_scheduler_t *scheduler) -+{ -+ struct rga_job *job_pos; -+ -+ lockdep_assert_held(&scheduler->irq_lock); -+ -+ pr_info("===============================================================\n"); -+ pr_info("%s core = %d job_count = %d status = %d\n", -+ dev_driver_string(scheduler->dev), -+ scheduler->core, scheduler->job_count, scheduler->status); -+ -+ if (scheduler->running_job) -+ rga_job_dump_info(scheduler->running_job); -+ -+ list_for_each_entry(job_pos, &scheduler->todo_list, head) { -+ rga_job_dump_info(job_pos); -+ } -+ -+ pr_info("===============================================================\n"); -+} -+ +static int rga_job_run(struct rga_job *job, struct rga_scheduler_t *scheduler) +{ + int ret = 0; @@ -1907756,23 +1909296,19 @@ index 000000000..fae613bbf + /* enable power */ + ret = rga_power_enable(scheduler); + if (ret < 0) { -+ pr_err("power enable failed"); ++ rga_job_err(job, "power enable failed"); + return ret; + } + + ret = scheduler->ops->set_reg(job, scheduler); + if (ret < 0) { -+ pr_err("set reg failed"); ++ rga_job_err(job, "set reg failed"); + rga_power_disable(scheduler); + return ret; + } + + set_bit(RGA_JOB_STATE_RUNNING, &job->state); + -+ /* for debug */ -+ if (DEBUGGER_EN(MSG)) -+ rga_job_dump_info(job); -+ + return ret; +} + @@ -1907806,18 +1909342,18 @@ index 000000000..fae613bbf + ret = rga_job_run(job, scheduler); + /* If some error before hw run */ + if (ret < 0) { -+ pr_err("some error on rga_job_run before hw start, %s(%d)\n", __func__, __LINE__); ++ rga_job_err(job, "some error on rga_job_run before hw start, %s(%d)\n", ++ __func__, __LINE__); + + spin_lock_irqsave(&scheduler->irq_lock, flags); -+ + scheduler->running_job = NULL; -+ rga_job_put(job); -+ + spin_unlock_irqrestore(&scheduler->irq_lock, flags); + + job->ret = ret; + rga_request_release_signal(scheduler, job); + ++ rga_job_put(job); ++ + goto next_job; + } + @@ -1907828,20 +1909364,32 @@ index 000000000..fae613bbf +{ + struct rga_job *job; + unsigned long flags; -+ ktime_t now = ktime_get(); + + spin_lock_irqsave(&scheduler->irq_lock, flags); + + job = scheduler->running_job; + if (job == NULL) { -+ pr_err("core[0x%x] running job has been cleanup.\n", scheduler->core); ++ rga_err("%s(%#x) running job has been cleanup.\n", ++ rga_get_core_name(scheduler->core), scheduler->core); ++ ++ spin_unlock_irqrestore(&scheduler->irq_lock, flags); ++ return NULL; ++ } ++ ++ if (!test_bit(RGA_JOB_STATE_FINISH, &job->state) && ++ !test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) { ++ rga_err("%s(%#x) running job has not yet been completed.", ++ rga_get_core_name(scheduler->core), scheduler->core); + + spin_unlock_irqrestore(&scheduler->irq_lock, flags); + return NULL; + } ++ + scheduler->running_job = NULL; + -+ scheduler->timer.busy_time += ktime_us_delta(now, job->hw_recoder_time); ++ scheduler->timer.busy_time += ++ ktime_us_delta(job->timestamp.hw_done, job->timestamp.hw_recode); ++ job->session->last_active = job->timestamp.hw_done; + set_bit(RGA_JOB_STATE_DONE, &job->state); + + spin_unlock_irqrestore(&scheduler->irq_lock, flags); @@ -1907853,16 +1909401,47 @@ index 000000000..fae613bbf + rga_dump_job_image(job); + + if (DEBUGGER_EN(TIME)) -+ pr_info("request[%d], hardware[%s] cost time %lld us\n", -+ job->request_id, ++ rga_job_log(job, "hardware[%s] cost time %lld us, work cycle %d\n", + rga_get_core_name(scheduler->core), -+ ktime_us_delta(now, job->hw_running_time)); ++ ktime_us_delta(job->timestamp.hw_done, job->timestamp.hw_execute), ++ job->work_cycle); + + rga_mm_unmap_job_info(job); + + return job; +} + ++static int rga_job_timeout_query_state(struct rga_job *job, int orig_ret) ++{ ++ int ret = orig_ret; ++ struct rga_scheduler_t *scheduler = job->scheduler; ++ ++ if (test_bit(RGA_JOB_STATE_DONE, &job->state) && ++ test_bit(RGA_JOB_STATE_FINISH, &job->state)) { ++ return orig_ret; ++ } else if (!test_bit(RGA_JOB_STATE_DONE, &job->state) && ++ test_bit(RGA_JOB_STATE_FINISH, &job->state)) { ++ rga_job_err(job, "job hardware has finished, but the software has timeout!\n"); ++ ++ ret = -EBUSY; ++ } else if (!test_bit(RGA_JOB_STATE_DONE, &job->state) && ++ !test_bit(RGA_JOB_STATE_FINISH, &job->state)) { ++ rga_job_err(job, "job hardware has timeout.\n"); ++ ++ if (scheduler->ops->read_status) ++ scheduler->ops->read_status(job, scheduler); ++ ++ ret = -EBUSY; ++ } ++ ++ rga_job_err(job, "timeout core[%d]: INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x], WORK_CYCLE[0x%x(%d)]\n", ++ scheduler->core, ++ job->intr_status, job->hw_status, job->cmd_status, ++ job->work_cycle, job->work_cycle); ++ ++ return ret; ++} ++ +static void rga_job_scheduler_timeout_clean(struct rga_scheduler_t *scheduler) +{ + unsigned long flags; @@ -1907870,13 +1909449,15 @@ index 000000000..fae613bbf + + spin_lock_irqsave(&scheduler->irq_lock, flags); + -+ if (scheduler->running_job == NULL || scheduler->running_job->hw_running_time == 0) { ++ if (scheduler->running_job == NULL || scheduler->running_job->timestamp.hw_execute == 0) { + spin_unlock_irqrestore(&scheduler->irq_lock, flags); + return; + } + + job = scheduler->running_job; -+ if (ktime_ms_delta(ktime_get(), job->hw_running_time) >= RGA_JOB_TIMEOUT_DELAY) { ++ if (ktime_ms_delta(ktime_get(), job->timestamp.hw_execute) >= RGA_JOB_TIMEOUT_DELAY) { ++ job->ret = rga_job_timeout_query_state(job, job->ret); ++ + scheduler->running_job = NULL; + scheduler->status = RGA_SCHEDULER_ABORT; + scheduler->ops->soft_reset(scheduler); @@ -1907884,8 +1909465,6 @@ index 000000000..fae613bbf + spin_unlock_irqrestore(&scheduler->irq_lock, flags); + + rga_mm_unmap_job_info(job); -+ -+ job->ret = -EBUSY; + rga_request_release_signal(scheduler, job); + + rga_power_disable(scheduler); @@ -1907927,6 +1909506,7 @@ index 000000000..fae613bbf + list_add_tail(&job->head, &scheduler->todo_list); + } + ++ job->timestamp.insert = ktime_get(); + scheduler->job_count++; + set_bit(RGA_JOB_STATE_PENDING, &job->state); + @@ -1907946,7 +1909526,7 @@ index 000000000..fae613bbf + if (rga_drvdata->num_of_scheduler > 1) { + job->core = rga_job_assign(job); + if (job->core <= 0) { -+ pr_err("job assign failed"); ++ rga_job_err(job, "job assign failed"); + job->ret = -EINVAL; + return NULL; + } @@ -1907957,7 +1909537,7 @@ index 000000000..fae613bbf + + scheduler = job->scheduler; + if (scheduler == NULL) { -+ pr_err("failed to get scheduler, %s(%d)\n", __func__, __LINE__); ++ rga_job_err(job, "failed to get scheduler, %s(%d)\n", __func__, __LINE__); + job->ret = -EFAULT; + return NULL; + } @@ -1907965,7 +1909545,7 @@ index 000000000..fae613bbf + return scheduler; +} + -+struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request) ++int rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request) +{ + int ret; + struct rga_job *job = NULL; @@ -1907973,8 +1909553,8 @@ index 000000000..fae613bbf + + job = rga_job_alloc(rga_command_base); + if (!job) { -+ pr_err("failed to alloc rga job!\n"); -+ return ERR_PTR(-ENOMEM); ++ rga_err("failed to alloc rga job!\n"); ++ return -ENOMEM; + } + + job->use_batch_mode = request->use_batch_mode; @@ -1907984,27 +1909564,32 @@ index 000000000..fae613bbf + + scheduler = rga_job_schedule(job); + if (scheduler == NULL) { -+ pr_err("failed to get scheduler, %s(%d)\n", __func__, __LINE__); ++ goto err_free_job; ++ } ++ ++ job->cmd_buf = rga_dma_alloc_coherent(scheduler, RGA_CMD_REG_SIZE); ++ if (job->cmd_buf == NULL) { ++ rga_job_err(job, "failed to alloc command buffer.\n"); + goto err_free_job; + } + + /* Memory mapping needs to keep pd enabled. */ + if (rga_power_enable(scheduler) < 0) { -+ pr_err("power enable failed"); ++ rga_job_err(job, "power enable failed"); + job->ret = -EFAULT; -+ goto err_free_job; ++ goto err_free_cmd_buf; + } + + ret = rga_mm_map_job_info(job); + if (ret < 0) { -+ pr_err("%s: failed to map job info\n", __func__); ++ rga_job_err(job, "%s: failed to map job info\n", __func__); + job->ret = ret; + goto err_power_disable; + } + + ret = scheduler->ops->init_reg(job); + if (ret < 0) { -+ pr_err("%s: init reg failed", __func__); ++ rga_job_err(job, "%s: init reg failed", __func__); + job->ret = ret; + goto err_unmap_job_info; + } @@ -1908015,7 +1909600,7 @@ index 000000000..fae613bbf + + rga_power_disable(scheduler); + -+ return job; ++ return 0; + +err_unmap_job_info: + rga_mm_unmap_job_info(job); @@ -1908023,11 +1909608,15 @@ index 000000000..fae613bbf +err_power_disable: + rga_power_disable(scheduler); + ++err_free_cmd_buf: ++ rga_dma_free(job->cmd_buf); ++ job->cmd_buf = NULL; ++ +err_free_job: + ret = job->ret; -+ rga_request_release_signal(scheduler, job); ++ rga_job_free(job); + -+ return ERR_PTR(ret); ++ return ret; +} + +static bool rga_is_need_current_mm(struct rga_req *req) @@ -1908106,11 +1909695,11 @@ index 000000000..fae613bbf + struct rga_pending_request_manager *request_manager = rga_drvdata->pend_request_manager; + + if (DEBUGGER_EN(MSG)) -+ pr_info("acquire_fence_fd = %d", acquire_fence_fd); ++ rga_req_log(request, "acquire_fence_fd = %d", acquire_fence_fd); + + acquire_fence = rga_get_dma_fence_from_fd(acquire_fence_fd); + if (IS_ERR_OR_NULL(acquire_fence)) { -+ pr_err("%s: failed to get acquire dma_fence from[%d]\n", ++ rga_req_err(request, "%s: failed to get acquire dma_fence from[%d]\n", + __func__, acquire_fence_fd); + return -EINVAL; + } @@ -1908124,7 +1909713,7 @@ index 000000000..fae613bbf + ksys_close(acquire_fence_fd); +#endif +#else -+ pr_err("Please update the driver to v1.2.28 to prevent acquire_fence_fd leaks."); ++ rga_req_err(request, "Please update the driver to v1.2.28 to prevent acquire_fence_fd leaks."); + return -EFAULT; +#endif + } @@ -1908132,7 +1909721,7 @@ index 000000000..fae613bbf + + ret = rga_dma_fence_get_status(acquire_fence); + if (ret < 0) { -+ pr_err("%s: Current acquire fence unexpectedly has error status before signal\n", ++ rga_req_err(request, "%s: Current acquire fence unexpectedly has error status before signal\n", + __func__); + return ret; + } else if (ret > 0) { @@ -1908151,7 +1909740,7 @@ index 000000000..fae613bbf + ret = rga_dma_fence_add_callback(acquire_fence, cb_func, (void *)request); + if (ret < 0) { + if (ret != -ENOENT) -+ pr_err("%s: failed to add fence callback\n", __func__); ++ rga_req_err(request, "%s: failed to add fence callback\n", __func__); + + mutex_lock(&request_manager->lock); + rga_request_put(request); @@ -1908165,38 +1909754,128 @@ index 000000000..fae613bbf +int rga_request_check(struct rga_user_request *req) +{ + if (req->id <= 0) { -+ pr_err("user request id[%d] is invalid", req->id); ++ rga_err("ID[%d]: request_id is invalid", req->id); + return -EINVAL; + } + + if (req->task_num <= 0) { -+ pr_err("invalied user request!\n"); ++ rga_err("ID[%d]: invalid user request!\n", req->id); + return -EINVAL; + } + + if (req->task_ptr == 0) { -+ pr_err("task_ptr is NULL!\n"); ++ rga_err("ID[%d]: task_ptr is NULL!\n", req->id); + return -EINVAL; + } + + if (req->task_num > RGA_TASK_NUM_MAX) { -+ pr_err("Only supports running %d tasks, now %d\n", -+ RGA_TASK_NUM_MAX, req->task_num); ++ rga_err("ID[%d]: Only supports running %d tasks, now %d\n", ++ req->id, RGA_TASK_NUM_MAX, req->task_num); + return -EFBIG; + } + -+ return 0; -+} ++ return 0; ++} ++ ++struct rga_request *rga_request_lookup(struct rga_pending_request_manager *manager, uint32_t id) ++{ ++ struct rga_request *request = NULL; ++ ++ WARN_ON(!mutex_is_locked(&manager->lock)); ++ ++ request = idr_find(&manager->request_idr, id); ++ ++ return request; ++} ++ ++void rga_request_scheduler_shutdown(struct rga_scheduler_t *scheduler) ++{ ++ struct rga_job *job, *job_q; ++ unsigned long flags; ++ ++ rga_power_enable(scheduler); ++ ++ spin_lock_irqsave(&scheduler->irq_lock, flags); ++ ++ job = scheduler->running_job; ++ if (job) { ++ if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state) || ++ test_bit(RGA_JOB_STATE_FINISH, &job->state)) { ++ spin_unlock_irqrestore(&scheduler->irq_lock, flags); ++ goto finish; ++ } ++ ++ scheduler->running_job = NULL; ++ scheduler->status = RGA_SCHEDULER_ABORT; ++ scheduler->ops->soft_reset(scheduler); ++ ++ spin_unlock_irqrestore(&scheduler->irq_lock, flags); ++ ++ rga_mm_unmap_job_info(job); ++ ++ job->ret = -EBUSY; ++ rga_request_release_signal(scheduler, job); ++ ++ /* ++ * Since the running job was abort, turn off the power here that ++ * should have been turned off after job done (corresponds to ++ * power_enable in rga_job_run()). ++ */ ++ rga_power_disable(scheduler); ++ } else { ++ /* Clean up the jobs in the todo list that need to be free. */ ++ list_for_each_entry_safe(job, job_q, &scheduler->todo_list, head) { ++ rga_mm_unmap_job_info(job); ++ ++ job->ret = -EBUSY; ++ rga_request_release_signal(scheduler, job); ++ } ++ ++ spin_unlock_irqrestore(&scheduler->irq_lock, flags); ++ } ++ ++finish: ++ rga_power_disable(scheduler); ++} ++ ++void rga_request_scheduler_abort(struct rga_scheduler_t *scheduler) ++{ ++ struct rga_job *job; ++ unsigned long flags; ++ ++ rga_power_enable(scheduler); ++ ++ spin_lock_irqsave(&scheduler->irq_lock, flags); ++ ++ job = scheduler->running_job; ++ if (job) { ++ scheduler->running_job = NULL; ++ scheduler->status = RGA_SCHEDULER_ABORT; ++ scheduler->ops->soft_reset(scheduler); ++ ++ spin_unlock_irqrestore(&scheduler->irq_lock, flags); ++ ++ rga_mm_unmap_job_info(job); ++ ++ job->ret = -EBUSY; ++ rga_request_release_signal(scheduler, job); + -+struct rga_request *rga_request_lookup(struct rga_pending_request_manager *manager, uint32_t id) -+{ -+ struct rga_request *request = NULL; ++ rga_job_next(scheduler); + -+ WARN_ON(!mutex_is_locked(&manager->lock)); ++ /* ++ * Since the running job was abort, turn off the power here that ++ * should have been turned off after job done (corresponds to ++ * power_enable in rga_job_run()). ++ */ ++ rga_power_disable(scheduler); ++ } else { ++ scheduler->status = RGA_SCHEDULER_ABORT; ++ scheduler->ops->soft_reset(scheduler); + -+ request = idr_find(&manager->request_idr, id); ++ spin_unlock_irqrestore(&scheduler->irq_lock, flags); ++ } + -+ return request; ++ rga_power_disable(scheduler); +} + +static int rga_request_scheduler_job_abort(struct rga_request *request) @@ -1908204,7 +1909883,7 @@ index 000000000..fae613bbf + int i; + unsigned long flags; + enum rga_scheduler_status scheduler_status; -+ int running_abort_count = 0, todo_abort_count = 0; ++ int running_abort_count = 0, todo_abort_count = 0, all_task_count = 0; + struct rga_scheduler_t *scheduler = NULL; + struct rga_job *job, *job_q; + LIST_HEAD(list_to_free); @@ -1908231,14 +1909910,16 @@ index 000000000..fae613bbf + scheduler->status = RGA_SCHEDULER_ABORT; + list_add_tail(&job->head, &list_to_free); + -+ if (job->hw_running_time != 0) { ++ if (job->timestamp.hw_execute != 0) { + scheduler->timer.busy_time += -+ ktime_us_delta(ktime_get(), job->hw_recoder_time); ++ ktime_us_delta(ktime_get(), ++ job->timestamp.hw_recode); + scheduler->ops->soft_reset(scheduler); + } ++ job->session->last_active = ktime_get(); + -+ pr_err("reset core[%d] by request[%d] abort", -+ scheduler->core, request->id); ++ rga_req_err(request, "reset core[%d] by request abort", ++ scheduler->core); + running_abort_count++; + } + } @@ -1908257,13 +1909938,17 @@ index 000000000..fae613bbf + rga_job_cleanup(job); + } + ++ all_task_count = request->finished_task_count + request->failed_task_count + ++ running_abort_count + todo_abort_count; ++ + /* This means it has been cleaned up. */ -+ if (running_abort_count + todo_abort_count == 0) ++ if (running_abort_count + todo_abort_count == 0 && ++ all_task_count == request->task_count) + return 1; + -+ pr_err("request[%d] abort! finished %d failed %d running_abort %d todo_abort %d\n", -+ request->id, request->finished_task_count, request->failed_task_count, -+ running_abort_count, todo_abort_count); ++ rga_err("request[%d] abort! finished %d failed %d running_abort %d todo_abort %d\n", ++ request->id, request->finished_task_count, request->failed_task_count, ++ running_abort_count, todo_abort_count); + + return 0; +} @@ -1908309,7 +1909994,7 @@ index 000000000..fae613bbf + + request_manager = rga_drvdata->pend_request_manager; + if (request_manager == NULL) { -+ pr_err("rga_pending_request_manager is null!\n"); ++ rga_err("rga_pending_request_manager is null!\n"); + return; + } + @@ -1908317,8 +1910002,8 @@ index 000000000..fae613bbf + + idr_for_each_entry(&request_manager->request_idr, request, request_id) { + if (session == request->session) { -+ pr_err("[tgid:%d pid:%d] destroy request[%d] when the user exits", -+ session->tgid, current->pid, request->id); ++ rga_req_err(request, "destroy when the user exits, current refcount = %d\n", ++ kref_read(&request->refcount)); + rga_request_put(request); + } + } @@ -1908340,23 +1910025,12 @@ index 000000000..fae613bbf + + if (scheduler->running_job) { + job = scheduler->running_job; ++ + if (request->id == job->request_id) { -+ if (test_bit(RGA_JOB_STATE_DONE, &job->state) && -+ test_bit(RGA_JOB_STATE_FINISH, &job->state)) { -+ spin_unlock_irqrestore(&scheduler->irq_lock, flags); -+ return request->ret; -+ } else if (!test_bit(RGA_JOB_STATE_DONE, &job->state) && -+ test_bit(RGA_JOB_STATE_FINISH, &job->state)) { -+ spin_unlock_irqrestore(&scheduler->irq_lock, flags); -+ pr_err("request[%d] hardware has finished, but the software has timeout!\n", -+ request->id); -+ return -EBUSY; -+ } else if (!test_bit(RGA_JOB_STATE_DONE, &job->state) && -+ !test_bit(RGA_JOB_STATE_FINISH, &job->state)) { -+ spin_unlock_irqrestore(&scheduler->irq_lock, flags); -+ pr_err("request[%d] hardware has timeout.\n", request->id); -+ return -EBUSY; -+ } ++ request->ret = rga_job_timeout_query_state(job, request->ret); ++ ++ spin_unlock_irqrestore(&scheduler->irq_lock, flags); ++ break; + } + } + @@ -1908377,43 +1910051,39 @@ index 000000000..fae613bbf + switch (left_time) { + case 0: + ret = rga_request_timeout_query_state(request); -+ goto err_request_abort; ++ break; + case -ERESTARTSYS: + ret = -ERESTARTSYS; -+ goto err_request_abort; ++ break; + default: + ret = request->ret; + break; + } + + return ret; -+ -+err_request_abort: -+ rga_request_release_abort(request, ret); -+ -+ return ret; +} + +int rga_request_commit(struct rga_request *request) +{ + int ret; + int i = 0; -+ struct rga_job *job; ++ ++ if (DEBUGGER_EN(MSG)) ++ rga_req_log(request, "commit process: %s\n", request->session->pname); + + for (i = 0; i < request->task_count; i++) { + struct rga_req *req = &(request->task_list[i]); + + if (DEBUGGER_EN(MSG)) { -+ pr_info("commit request[%d] task[%d]:\n", request->id, i); -+ rga_cmd_print_debug_info(req); ++ rga_req_log(request, "commit task[%d]:\n", i); ++ rga_dump_req(request, req); + } + -+ job = rga_job_commit(req, request); -+ if (IS_ERR(job)) { -+ pr_err("request[%d] task[%d] job_commit failed.\n", request->id, i); -+ rga_request_release_abort(request, PTR_ERR(job)); ++ ret = rga_job_commit(req, request); ++ if (ret < 0) { ++ rga_req_err(request, "task[%d] job_commit failed.\n", i); + -+ return PTR_ERR(job); ++ return ret; + } + } + @@ -1908426,19 +1910096,17 @@ index 000000000..fae613bbf + return 0; +} + -+static void rga_request_acquire_fence_signaled_cb(struct dma_fence *fence, -+ struct dma_fence_cb *_waiter) ++static void rga_request_acquire_fence_work(struct work_struct *work) +{ + int ret; + unsigned long flags; + struct mm_struct *current_mm; -+ struct rga_fence_waiter *waiter = (struct rga_fence_waiter *)_waiter; -+ struct rga_request *request = (struct rga_request *)waiter->private; ++ struct rga_request *request = container_of(work, struct rga_request, fence_work); + struct rga_pending_request_manager *request_manager = rga_drvdata->pend_request_manager; + + ret = rga_request_commit(request); + if (ret < 0) { -+ pr_err("acquire_fence callback: rga request[%d] commit failed!\n", request->id); ++ rga_req_err(request, "acquire_fence callback: request commit failed!\n"); + + spin_lock_irqsave(&request->lock, flags); + @@ -1908450,18 +1910118,22 @@ index 000000000..fae613bbf + + rga_request_put_current_mm(current_mm); + -+ /* -+ * Since the callback is called while holding &dma_fence.lock, -+ * the _locked API is used here. -+ */ -+ if (dma_fence_get_status_locked(request->release_fence) == 0) -+ dma_fence_signal_locked(request->release_fence); ++ if (rga_dma_fence_get_status(request->release_fence) == 0) ++ rga_dma_fence_signal(request->release_fence, ret); + } + + mutex_lock(&request_manager->lock); + rga_request_put(request); + mutex_unlock(&request_manager->lock); ++} ++ ++static void rga_request_acquire_fence_signaled_cb(struct dma_fence *fence, ++ struct dma_fence_cb *_waiter) ++{ ++ struct rga_fence_waiter *waiter = (struct rga_fence_waiter *)_waiter; ++ struct rga_request *request = (struct rga_request *)waiter->private; + ++ queue_work(system_highpri_wq, &request->fence_work); + kfree(waiter); +} + @@ -1908476,7 +1910148,7 @@ index 000000000..fae613bbf + + request_manager = rga_drvdata->pend_request_manager; + if (request_manager == NULL) { -+ pr_err("rga_pending_request_manager is null!\n"); ++ rga_job_err(job, "rga_pending_request_manager is null!\n"); + return -EFAULT; + } + @@ -1908484,7 +1910156,7 @@ index 000000000..fae613bbf + + request = rga_request_lookup(request_manager, job->request_id); + if (IS_ERR_OR_NULL(request)) { -+ pr_err("can not find internal request from id[%d]", job->request_id); ++ rga_job_err(job, "can not find internal request from id[%d]", job->request_id); + mutex_unlock(&request_manager->lock); + return -EINVAL; + } @@ -1908521,10 +1910193,10 @@ index 000000000..fae613bbf + rga_dma_fence_signal(request->release_fence, request->ret); + + is_finished = true; ++ job->timestamp.done = ktime_get(); + + if (DEBUGGER_EN(MSG)) -+ pr_info("request[%d] finished %d failed %d\n", -+ request->id, finished_count, failed_count); ++ rga_job_log(job, "finished %d failed %d\n", finished_count, failed_count); + + /* current submit request put */ + mutex_lock(&request_manager->lock); @@ -1908541,10 +1910213,17 @@ index 000000000..fae613bbf + + mutex_unlock(&request_manager->lock); + -+ if (DEBUGGER_EN(TIME)) -+ pr_info("request[%d], job done total cost time %lld us\n", -+ job->request_id, -+ ktime_us_delta(ktime_get(), job->timestamp)); ++ if (DEBUGGER_EN(TIME)) { ++ rga_job_log(job, ++ "stats: prepare %lld us, schedule %lld us, hardware %lld us, free %lld us\n", ++ ktime_us_delta(job->timestamp.insert, job->timestamp.init), ++ ktime_us_delta(job->timestamp.hw_execute, job->timestamp.insert), ++ ktime_us_delta(job->timestamp.hw_done, job->timestamp.hw_execute), ++ ktime_us_delta(ktime_get(), job->timestamp.hw_done)); ++ rga_job_log(job, "total: job done cost %lld us, cleanup done cost %lld us\n", ++ ktime_us_delta(job->timestamp.done, job->timestamp.init), ++ ktime_us_delta(ktime_get(), job->timestamp.init)); ++ } + + rga_job_cleanup(job); + @@ -1908561,7 +1910240,7 @@ index 000000000..fae613bbf + + request_manager = rga_drvdata->pend_request_manager; + if (request_manager == NULL) { -+ pr_err("rga_pending_request_manager is null!\n"); ++ rga_err("rga_pending_request_manager is null!\n"); + return ERR_PTR(-EFAULT); + } + @@ -1908569,7 +1910248,7 @@ index 000000000..fae613bbf + + request = rga_request_lookup(request_manager, user_request->id); + if (IS_ERR_OR_NULL(request)) { -+ pr_err("can not find request from id[%d]", user_request->id); ++ rga_err("can not find request from id[%d]", user_request->id); + mutex_unlock(&request_manager->lock); + return ERR_PTR(-EINVAL); + } @@ -1908579,14 +1910258,14 @@ index 000000000..fae613bbf + + task_list = kmalloc_array(user_request->task_num, sizeof(struct rga_req), GFP_KERNEL); + if (task_list == NULL) { -+ pr_err("task_req list alloc error!\n"); ++ rga_req_err(request, "task_req list alloc error!\n"); + ret = -ENOMEM; + goto err_put_request; + } + + if (unlikely(copy_from_user(task_list, u64_to_user_ptr(user_request->task_ptr), + sizeof(struct rga_req) * user_request->task_num))) { -+ pr_err("rga_user_request task list copy_from_user failed\n"); ++ rga_req_err(request, "rga_user_request task list copy_from_user failed\n"); + ret = -EFAULT; + goto err_free_task_list; + } @@ -1908625,7 +1910304,7 @@ index 000000000..fae613bbf + + request_manager = rga_drvdata->pend_request_manager; + if (request_manager == NULL) { -+ pr_err("rga_pending_request_manager is null!\n"); ++ rga_err("rga_pending_request_manager is null!\n"); + return ERR_PTR(-EFAULT); + } + @@ -1908633,7 +1910312,7 @@ index 000000000..fae613bbf + + request = rga_request_lookup(request_manager, user_request->id); + if (IS_ERR_OR_NULL(request)) { -+ pr_err("can not find request from id[%d]", user_request->id); ++ rga_err("can not find request from id[%d]", user_request->id); + mutex_unlock(&request_manager->lock); + return ERR_PTR(-EINVAL); + } @@ -1908643,7 +1910322,7 @@ index 000000000..fae613bbf + + task_list = kmalloc_array(user_request->task_num, sizeof(struct rga_req), GFP_KERNEL); + if (task_list == NULL) { -+ pr_err("task_req list alloc error!\n"); ++ rga_req_err(request, "task_req list alloc error!\n"); + ret = -ENOMEM; + goto err_put_request; + } @@ -1908677,26 +1910356,23 @@ index 000000000..fae613bbf + int ret = 0; + unsigned long flags; + struct dma_fence *release_fence; -+ struct mm_struct *current_mm; -+ -+ current_mm = rga_request_get_current_mm(request); + + spin_lock_irqsave(&request->lock, flags); + + if (request->is_running) { + spin_unlock_irqrestore(&request->lock, flags); + -+ pr_err("can not re-config when request is running\n"); ++ rga_req_err(request, "can not re-config when request is running\n"); + ret = -EFAULT; -+ goto err_put_current_mm; ++ goto err_abort_request; + } + + if (request->task_list == NULL) { + spin_unlock_irqrestore(&request->lock, flags); + -+ pr_err("can not find task list from id[%d]\n", request->id); ++ rga_req_err(request, "can not find task list\n"); + ret = -EINVAL; -+ goto err_put_current_mm; ++ goto err_abort_request; + } + + /* Reset */ @@ -1908704,21 +1910380,24 @@ index 000000000..fae613bbf + request->is_done = false; + request->finished_task_count = 0; + request->failed_task_count = 0; -+ request->current_mm = current_mm; ++ request->ret = 0; + + /* Unlock after ensuring that the current request will not be resubmitted. */ + spin_unlock_irqrestore(&request->lock, flags); + + if (request->sync_mode == RGA_BLIT_ASYNC) { + release_fence = rga_dma_fence_alloc(); -+ if (IS_ERR(release_fence)) { -+ pr_err("Can not alloc release fence!\n"); -+ ret = IS_ERR(release_fence); -+ goto err_reset_request; ++ if (IS_ERR_OR_NULL(release_fence)) { ++ rga_req_err(request, "Can not alloc release fence!\n"); ++ ret = IS_ERR(release_fence) ? PTR_ERR(release_fence) : -EINVAL; ++ goto err_abort_request; + } ++ ++ request->current_mm = rga_request_get_current_mm(request); + request->release_fence = release_fence; + + if (request->acquire_fence_fd > 0) { ++ INIT_WORK(&request->fence_work, rga_request_acquire_fence_work); + ret = rga_request_add_acquire_fence_callback( + request->acquire_fence_fd, request, + rga_request_acquire_fence_signaled_cb); @@ -1908729,27 +1910408,32 @@ index 000000000..fae613bbf + /* acquire fence has been signaled */ + goto request_commit; + } else { -+ pr_err("Failed to add callback with acquire fence fd[%d]!\n", ++ rga_req_err(request, "Failed to add callback with acquire fence fd[%d]!\n", + request->acquire_fence_fd); -+ goto err_put_release_fence; ++ ++ rga_dma_fence_put(request->release_fence); ++ request->release_fence = NULL; ++ goto err_put_current_mm; + } + } ++ } else { ++ request->current_mm = rga_request_get_current_mm(request); ++ request->release_fence = NULL; + } + +request_commit: + ret = rga_request_commit(request); + if (ret < 0) { -+ pr_err("rga request[%d] commit failed!\n", request->id); -+ goto err_put_release_fence; ++ rga_req_err(request, "request commit failed!\n"); ++ goto err_put_current_mm; + } + +export_release_fence_fd: + if (request->release_fence != NULL) { + ret = rga_dma_fence_get_fd(request->release_fence); + if (ret < 0) { -+ pr_err("Failed to alloc release fence fd!\n"); -+ rga_request_release_abort(request, ret); -+ return ret; ++ rga_req_err(request, "Failed to alloc release fence fd!\n"); ++ goto err_put_current_mm; + } + + request->release_fence_fd = ret; @@ -1908757,22 +1910441,12 @@ index 000000000..fae613bbf + + return 0; + -+err_put_release_fence: -+ if (request->release_fence != NULL) { -+ rga_dma_fence_put(request->release_fence); -+ request->release_fence = NULL; -+ } -+ -+err_reset_request: -+ spin_lock_irqsave(&request->lock, flags); -+ ++err_put_current_mm: ++ rga_request_put_current_mm(request->current_mm); + request->current_mm = NULL; -+ request->is_running = false; -+ -+ spin_unlock_irqrestore(&request->lock, flags); + -+err_put_current_mm: -+ rga_request_put_current_mm(current_mm); ++err_abort_request: ++ rga_request_release_abort(request, ret); + + return ret; +} @@ -1908780,26 +1910454,31 @@ index 000000000..fae613bbf +int rga_request_mpi_submit(struct rga_req *req, struct rga_request *request) +{ + int ret = 0; -+ struct rga_job *job = NULL; + unsigned long flags; ++ struct rga_pending_request_manager *request_manager; ++ ++ request_manager = rga_drvdata->pend_request_manager; + + if (request->sync_mode == RGA_BLIT_ASYNC) { -+ pr_err("mpi unsupported async mode!\n"); -+ return -EINVAL; ++ rga_req_err(request, "mpi unsupported async mode!\n"); ++ ret = -EINVAL; ++ goto err_abort_request; + } + + spin_lock_irqsave(&request->lock, flags); + + if (request->is_running) { -+ pr_err("can not re-config when request is running"); ++ rga_req_err(request, "can not re-config when request is running"); + spin_unlock_irqrestore(&request->lock, flags); -+ return -EFAULT; ++ ret = -EFAULT; ++ goto err_abort_request; + } + + if (request->task_list == NULL) { -+ pr_err("can not find task list from id[%d]", request->id); ++ rga_req_err(request, "can not find task list"); + spin_unlock_irqrestore(&request->lock, flags); -+ return -EINVAL; ++ ret = -EINVAL; ++ goto err_abort_request; + } + + /* Reset */ @@ -1908807,20 +1910486,34 @@ index 000000000..fae613bbf + request->is_done = false; + request->finished_task_count = 0; + request->failed_task_count = 0; ++ request->ret = 0; + + spin_unlock_irqrestore(&request->lock, flags); + -+ job = rga_job_commit(req, request); -+ if (IS_ERR_OR_NULL(job)) { -+ pr_err("failed to commit job!\n"); -+ return job ? PTR_ERR(job) : -EFAULT; ++ /* ++ * The mpi submit will use the request repeatedly, so an additional ++ * get() is added here. ++ */ ++ mutex_lock(&request_manager->lock); ++ rga_request_get(request); ++ mutex_unlock(&request_manager->lock); ++ ++ ret = rga_job_commit(req, request); ++ if (ret < 0) { ++ rga_req_err(request, "failed to commit job!\n"); ++ goto err_abort_request; + } + + ret = rga_request_wait(request); + if (ret < 0) -+ return ret; ++ goto err_abort_request; + + return 0; ++ ++err_abort_request: ++ rga_request_release_abort(request, ret); ++ ++ return ret; +} + +int rga_request_free(struct rga_request *request) @@ -1908831,14 +1910524,14 @@ index 000000000..fae613bbf + + request_manager = rga_drvdata->pend_request_manager; + if (request_manager == NULL) { -+ pr_err("rga_pending_request_manager is null!\n"); ++ rga_err("rga_pending_request_manager is null!\n"); + return -EFAULT; + } + + WARN_ON(!mutex_is_locked(&request_manager->lock)); + + if (IS_ERR_OR_NULL(request)) { -+ pr_err("request already freed"); ++ rga_err("request already freed"); + return -EFAULT; + } + @@ -1908854,6 +1910547,8 @@ index 000000000..fae613bbf + if (task_list != NULL) + kfree(task_list); + ++ rga_session_put(request->session); ++ + kfree(request); + + return 0; @@ -1908910,13 +1910605,13 @@ index 000000000..fae613bbf + + request_manager = rga_drvdata->pend_request_manager; + if (request_manager == NULL) { -+ pr_err("rga_pending_request_manager is null!\n"); ++ rga_err("rga_pending_request_manager is null!\n"); + return -EFAULT; + } + + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) { -+ pr_err("can not kzalloc for rga_request\n"); ++ rga_err("can not kzalloc for rga_request\n"); + return -ENOMEM; + } + @@ -1908925,7 +1910620,10 @@ index 000000000..fae613bbf + + request->pid = current->pid; + request->flags = flags; ++ ++ rga_session_get(session); + request->session = session; ++ + kref_init(&request->refcount); + + /* @@ -1908938,9 +1910636,10 @@ index 000000000..fae613bbf + new_id = idr_alloc_cyclic(&request_manager->request_idr, request, 1, 0, GFP_NOWAIT); + idr_preload_end(); + if (new_id < 0) { -+ pr_err("request alloc id failed!\n"); ++ rga_err("request alloc id failed!\n"); + + mutex_unlock(&request_manager->lock); ++ rga_session_put(session); + kfree(request); + return new_id; + } @@ -1909001,10 +1910700,10 @@ index 000000000..fae613bbf +} diff --git a/drivers/video/rockchip/rga3/rga_mm.c b/drivers/video/rockchip/rga3/rga_mm.c new file mode 100644 -index 000000000..de7e9a6fd +index 000000000..b130e6e60 --- /dev/null +++ b/drivers/video/rockchip/rga3/rga_mm.c -@@ -0,0 +1,2229 @@ +@@ -0,0 +1,2483 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1909012,8 +1910711,6 @@ index 000000000..de7e9a6fd + * Author: Cerf Yu + */ + -+#define pr_fmt(fmt) "rga_mm: " fmt -+ +#include "rga.h" +#include "rga_job.h" +#include "rga_mm.h" @@ -1909060,14 +1910757,14 @@ index 000000000..de7e9a6fd + for (i = 0; i < pageCount; i++) { + vma = find_vma(current_mm, (Memory + i) << PAGE_SHIFT); + if (!vma) { -+ pr_err("page[%d] failed to get vma\n", i); ++ rga_err("page[%d] failed to get vma\n", i); + ret = RGA_OUT_OF_RESOURCES; + break; + } + + pgd = pgd_offset(current_mm, (Memory + i) << PAGE_SHIFT); + if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) { -+ pr_err("page[%d] failed to get pgd\n", i); ++ rga_err("page[%d] failed to get pgd\n", i); + ret = RGA_OUT_OF_RESOURCES; + break; + } @@ -1909078,7 +1910775,7 @@ index 000000000..de7e9a6fd + */ + p4d = p4d_offset(pgd, (Memory + i) << PAGE_SHIFT); + if (p4d_none(*p4d) || unlikely(p4d_bad(*p4d))) { -+ pr_err("page[%d] failed to get p4d\n", i); ++ rga_err("page[%d] failed to get p4d\n", i); + ret = RGA_OUT_OF_RESOURCES; + break; + } @@ -1909089,20 +1910786,20 @@ index 000000000..de7e9a6fd +#endif + + if (pud_none(*pud) || unlikely(pud_bad(*pud))) { -+ pr_err("page[%d] failed to get pud\n", i); ++ rga_err("page[%d] failed to get pud\n", i); + ret = RGA_OUT_OF_RESOURCES; + break; + } + pmd = pmd_offset(pud, (Memory + i) << PAGE_SHIFT); + if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) { -+ pr_err("page[%d] failed to get pmd\n", i); ++ rga_err("page[%d] failed to get pmd\n", i); + ret = RGA_OUT_OF_RESOURCES; + break; + } + pte = pte_offset_map_lock(current_mm, pmd, + (Memory + i) << PAGE_SHIFT, &ptl); + if (pte_none(*pte)) { -+ pr_err("page[%d] failed to get pte\n", i); ++ rga_err("page[%d] failed to get pte\n", i); + pte_unmap_unlock(pte, ptl); + ret = RGA_OUT_OF_RESOURCES; + break; @@ -1909114,8 +1910811,8 @@ index 000000000..de7e9a6fd + } + + if (ret == RGA_OUT_OF_RESOURCES && i > 0) -+ pr_err("Only get buffer %d byte from vma, but current image required %d byte", -+ (int)(i * PAGE_SIZE), (int)(pageCount * PAGE_SIZE)); ++ rga_err("Only get buffer %d byte from vma, but current image required %d byte", ++ (int)(i * PAGE_SIZE), (int)(pageCount * PAGE_SIZE)); + + return ret; +} @@ -1909142,9 +1910839,12 @@ index 000000000..de7e9a6fd + result = get_user_pages_remote(current, current_mm, + Memory << PAGE_SHIFT, + pageCount, writeFlag ? FOLL_WRITE : 0, pages, NULL, NULL); -+#else ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) + result = get_user_pages_remote(current_mm, Memory << PAGE_SHIFT, + pageCount, writeFlag ? FOLL_WRITE : 0, pages, NULL, NULL); ++#else ++ result = get_user_pages_remote(current_mm, Memory << PAGE_SHIFT, ++ pageCount, writeFlag ? FOLL_WRITE : 0, pages, NULL); +#endif + + if (result > 0 && result >= pageCount) { @@ -1909156,8 +1910856,8 @@ index 000000000..de7e9a6fd + + ret = rga_get_user_pages_from_vma(pages, Memory, pageCount, current_mm); + if (ret < 0 && result > 0) { -+ pr_err("Only get buffer %d byte from user pages, but current image required %d byte\n", -+ (int)(result * PAGE_SIZE), (int)(pageCount * PAGE_SIZE)); ++ rga_err("Only get buffer %d byte from user pages, but current image required %d byte\n", ++ (int)(result * PAGE_SIZE), (int)(pageCount * PAGE_SIZE)); + } + } + @@ -1909183,20 +1910883,19 @@ index 000000000..de7e9a6fd + + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); + if (sgt == NULL) { -+ pr_err("%s alloc sgt error!\n", __func__); ++ rga_err("%s alloc sgt error!\n", __func__); + return ERR_PTR(-ENOMEM); + } + + /* get sg form pages. */ -+ /* iova requires minimum page alignment, so sgt cannot have offset */ + ret = sg_alloc_table_from_pages(sgt, + virt_addr->pages, + virt_addr->page_count, -+ 0, ++ virt_addr->offset, + virt_addr->size, + GFP_KERNEL); + if (ret) { -+ pr_err("sg_alloc_table_from_pages failed"); ++ rga_err("sg_alloc_table_from_pages failed"); + goto out_free_sgt; + } + @@ -1909241,7 +1910940,6 @@ index 000000000..de7e9a6fd + unsigned int count; + int img_size; + size_t offset; -+ unsigned long size; + struct page **pages = NULL; + struct rga_virt_addr *virt_addr = NULL; + @@ -1909255,32 +1910953,25 @@ index 000000000..de7e9a6fd + + offset = viraddr & (~PAGE_MASK); + count = RGA_GET_PAGE_COUNT(img_size + offset); -+ size = count * PAGE_SIZE; -+ if (!size) { -+ pr_err("failed to calculating buffer size! size = %ld, count = %d, offset = %ld\n", -+ size, count, (unsigned long)offset); ++ if (!count) { ++ rga_err("failed to calculating buffer size! img_size = %d, count = %d, offset = %ld\n", ++ img_size, count, (unsigned long)offset); + rga_dump_memory_parm(memory_parm); + return -EFAULT; + } + + /* alloc pages and page_table */ -+ order = get_order(count * sizeof(struct page *)); -+ if (order >= MAX_ORDER) { -+ pr_err("Can not alloc pages with order[%d] for viraddr pages, max_order = %d\n", -+ order, MAX_ORDER); -+ return -ENOMEM; -+ } -+ -+ pages = (struct page **)__get_free_pages(GFP_KERNEL, order); ++ pages = (struct page **)rga_get_free_pages(GFP_KERNEL, ++ &order, count * sizeof(struct page *)); + if (pages == NULL) { -+ pr_err("%s can not alloc pages for viraddr pages\n", __func__); ++ rga_err("%s can not alloc pages for viraddr pages\n", __func__); + return -ENOMEM; + } + + /* get pages from virtual address. */ + ret = rga_get_user_pages(pages, viraddr >> PAGE_SHIFT, count, writeFlag, mm); + if (ret < 0) { -+ pr_err("failed to get pages from virtual adrees: 0x%lx\n", ++ rga_err("failed to get pages from virtual adrees: 0x%lx\n", + (unsigned long)viraddr); + ret = -EINVAL; + goto out_free_pages; @@ -1909291,7 +1910982,7 @@ index 000000000..de7e9a6fd + + *virt_addr_p = kzalloc(sizeof(struct rga_virt_addr), GFP_KERNEL); + if (*virt_addr_p == NULL) { -+ pr_err("%s alloc virt_addr error!\n", __func__); ++ rga_err("%s alloc virt_addr error!\n", __func__); + ret = -ENOMEM; + goto out_put_and_free_pages; + } @@ -1909301,7 +1910992,7 @@ index 000000000..de7e9a6fd + virt_addr->pages = pages; + virt_addr->pages_order = order; + virt_addr->page_count = count; -+ virt_addr->size = size; ++ virt_addr->size = img_size; + virt_addr->offset = offset; + virt_addr->result = result; + @@ -1909323,7 +1911014,7 @@ index 000000000..de7e9a6fd + + if (scheduler->data->mmu == RGA_MMU && + !(mm_flag & RGA_MEM_UNDER_4G)) { -+ pr_err("%s unsupported memory larger than 4G!\n", ++ rga_err("%s unsupported memory larger than 4G!\n", + rga_get_mmu_type_str(scheduler->data->mmu)); + return false; + } @@ -1909390,7 +1911081,7 @@ index 000000000..de7e9a6fd + scheduler = job ? job->scheduler : + rga_drvdata->scheduler[rga_drvdata->map_scheduler_index]; + if (scheduler == NULL) { -+ pr_err("Invalid scheduler device!\n"); ++ rga_err("Invalid scheduler device!\n"); + return -EINVAL; + } + @@ -1909402,23 +1911093,22 @@ index 000000000..de7e9a6fd + external_buffer->memory_parm.format, + NULL, NULL, NULL); + if (ex_buffer_size <= 0) { -+ pr_err("failed to calculating buffer size!\n"); ++ rga_err("failed to calculating buffer size!\n"); + rga_dump_memory_parm(&external_buffer->memory_parm); + return ex_buffer_size == 0 ? -EINVAL : ex_buffer_size; + } + -+ /* -+ * dma-buf api needs to use default_domain of main dev, -+ * and not IOMMU for devices without iommu_info ptr. -+ */ -+ map_dev = scheduler->iommu_info ? scheduler->iommu_info->default_dev : scheduler->dev; -+ + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (buffer == NULL) { -+ pr_err("%s alloc internal_buffer error!\n", __func__); ++ rga_err("%s alloc internal_buffer error!\n", __func__); + return -ENOMEM; + } + ++ /* ++ * dma-buf api needs to use default_domain of main dev, ++ * and not IOMMU for devices without iommu_info ptr. ++ */ ++ map_dev = scheduler->iommu_info ? scheduler->iommu_info->default_dev : scheduler->dev; + switch (external_buffer->type) { + case RGA_DMA_BUFFER: + ret = rga_dma_map_fd((int)external_buffer->memory, @@ -1909435,21 +1911125,22 @@ index 000000000..de7e9a6fd + break; + } + if (ret < 0) { -+ pr_err("%s core[%d] map dma buffer error!\n", -+ __func__, scheduler->core); ++ rga_err("%s core[%d] map dma buffer error!\n", ++ __func__, scheduler->core); + goto free_buffer; + } + + if (buffer->size < ex_buffer_size) { -+ pr_err("Only get buffer %ld byte from %s = 0x%lx, but current image required %d byte\n", -+ buffer->size, rga_get_memory_type_str(external_buffer->type), -+ (unsigned long)external_buffer->memory, ex_buffer_size); ++ rga_err("Only get buffer %ld byte from %s = 0x%lx, but current image required %d byte\n", ++ buffer->size, rga_get_memory_type_str(external_buffer->type), ++ (unsigned long)external_buffer->memory, ex_buffer_size); + rga_dump_memory_parm(&external_buffer->memory_parm); + ret = -EINVAL; + goto unmap_buffer; + } + -+ buffer->scheduler = scheduler; ++ if (scheduler->data->mmu == RGA_IOMMU) ++ buffer->iova = buffer->dma_addr; + + if (rga_mm_check_range_sgt(buffer->sgt)) + mm_flag |= RGA_MEM_UNDER_4G; @@ -1909461,7 +1911152,7 @@ index 000000000..de7e9a6fd + if (rga_mm_check_contiguous_sgt(buffer->sgt)) { + phys_addr = sg_phys(buffer->sgt->sgl); + if (phys_addr == 0) { -+ pr_err("%s get physical address error!", __func__); ++ rga_err("%s get physical address error!", __func__); + ret = -EFAULT; + goto unmap_buffer; + } @@ -1909470,8 +1911161,8 @@ index 000000000..de7e9a6fd + } + + if (!rga_mm_check_memory_limit(scheduler, mm_flag)) { -+ pr_err("scheduler core[%d] unsupported mm_flag[0x%x]!\n", -+ scheduler->core, mm_flag); ++ rga_err("scheduler core[%d] unsupported mm_flag[0x%x]!\n", ++ scheduler->core, mm_flag); + ret = -EINVAL; + goto unmap_buffer; + } @@ -1909479,6 +1911170,8 @@ index 000000000..de7e9a6fd + internal_buffer->dma_buffer = buffer; + internal_buffer->mm_flag = mm_flag; + internal_buffer->phys_addr = phys_addr ? phys_addr : 0; ++ internal_buffer->size = buffer->size - buffer->offset; ++ internal_buffer->scheduler = scheduler; + + return 0; + @@ -1909498,19 +1911191,7 @@ index 000000000..de7e9a6fd + if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer)) + return; + -+ switch (internal_buffer->dma_buffer->scheduler->data->mmu) { -+ case RGA_IOMMU: -+ rga_iommu_unmap(internal_buffer->dma_buffer); -+ break; -+ case RGA_MMU: -+ dma_unmap_sg(internal_buffer->dma_buffer->scheduler->dev, -+ internal_buffer->dma_buffer->sgt->sgl, -+ internal_buffer->dma_buffer->sgt->orig_nents, -+ DMA_BIDIRECTIONAL); -+ break; -+ default: -+ break; -+ } ++ rga_dma_unmap_sgt(internal_buffer->dma_buffer); + + if (internal_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS && + internal_buffer->phys_addr > 0) @@ -1909538,18 +1911219,19 @@ index 000000000..de7e9a6fd + struct sg_table *sgt; + struct rga_virt_addr *virt_addr; + struct rga_dma_buffer *buffer; ++ struct device *map_dev; + struct rga_scheduler_t *scheduler; + + scheduler = job ? job->scheduler : + rga_drvdata->scheduler[rga_drvdata->map_scheduler_index]; + if (scheduler == NULL) { -+ pr_err("Invalid scheduler device!\n"); ++ rga_err("Invalid scheduler device!\n"); + return -EINVAL; + } + + internal_buffer->current_mm = job ? job->mm : current->mm; + if (internal_buffer->current_mm == NULL) { -+ pr_err("%s, cannot get current mm!\n", __func__); ++ rga_err("%s, cannot get current mm!\n", __func__); + return -EFAULT; + } + mmgrab(internal_buffer->current_mm); @@ -1909560,14 +1911242,14 @@ index 000000000..de7e9a6fd + &internal_buffer->memory_parm, + write_flag, internal_buffer->current_mm); + if (ret < 0) { -+ pr_err("Can not alloc rga_virt_addr from 0x%lx\n", ++ rga_err("Can not alloc rga_virt_addr from 0x%lx\n", + (unsigned long)external_buffer->memory); + goto put_current_mm; + } + + sgt = rga_alloc_sgt(virt_addr); + if (IS_ERR(sgt)) { -+ pr_err("alloc sgt error!\n"); ++ rga_err("alloc sgt error!\n"); + ret = PTR_ERR(sgt); + goto free_virt_addr; + } @@ -1909578,12 +1911260,17 @@ index 000000000..de7e9a6fd + if (rga_mm_check_contiguous_sgt(sgt)) { + phys_addr = sg_phys(sgt->sgl); + if (phys_addr == 0) { -+ pr_err("%s get physical address error!", __func__); ++ rga_err("%s get physical address error!", __func__); + ret = -EFAULT; + goto free_sgt; + } + + mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS; ++ } else if (scheduler->data->mmu == RGA_NONE_MMU) { ++ rga_err("Current %s[%d] cannot support physically discontinuous virtual address!\n", ++ rga_get_mmu_type_str(scheduler->data->mmu), scheduler->data->mmu); ++ ret = -EOPNOTSUPP; ++ goto free_sgt; + } + + /* @@ -1909594,57 +1911281,41 @@ index 000000000..de7e9a6fd + mm_flag |= RGA_MEM_FORCE_FLUSH_CACHE; + + if (!rga_mm_check_memory_limit(scheduler, mm_flag)) { -+ pr_err("scheduler core[%d] unsupported mm_flag[0x%x]!\n", -+ scheduler->core, mm_flag); ++ rga_err("scheduler core[%d] unsupported mm_flag[0x%x]!\n", ++ scheduler->core, mm_flag); + ret = -EINVAL; + goto free_sgt; + } + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (buffer == NULL) { -+ pr_err("%s alloc internal dma_buffer error!\n", __func__); ++ rga_err("%s alloc internal dma_buffer error!\n", __func__); + ret = -ENOMEM; + goto free_sgt; + } + -+ switch (scheduler->data->mmu) { -+ case RGA_IOMMU: -+ ret = rga_iommu_map_sgt(sgt, virt_addr->size, buffer, scheduler->dev); -+ if (ret < 0) { -+ pr_err("%s core[%d] iommu_map virtual address error!\n", -+ __func__, scheduler->core); -+ goto free_dma_buffer; -+ } -+ break; -+ case RGA_MMU: -+ ret = dma_map_sg(scheduler->dev, sgt->sgl, sgt->orig_nents, DMA_BIDIRECTIONAL); -+ if (ret == 0) { -+ pr_err("%s core[%d] dma_map_sgt error! va = 0x%lx, nents = %d\n", -+ __func__, scheduler->core, -+ (unsigned long)virt_addr->addr, sgt->orig_nents); -+ ret = -EINVAL; -+ goto free_dma_buffer; -+ } -+ break; -+ default: -+ if (mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) -+ break; -+ -+ pr_err("Current %s[%d] cannot support physically discontinuous virtual address!\n", -+ rga_get_mmu_type_str(scheduler->data->mmu), scheduler->data->mmu); -+ ret = -EOPNOTSUPP; ++ /* ++ * dma-buf api needs to use default_domain of main dev, ++ * and not IOMMU for devices without iommu_info ptr. ++ */ ++ map_dev = scheduler->iommu_info ? scheduler->iommu_info->default_dev : scheduler->dev; ++ ret = rga_dma_map_sgt(sgt, buffer, DMA_BIDIRECTIONAL, map_dev); ++ if (ret < 0) { ++ rga_err("%s core[%d] rga map sgt failed! va = 0x%lx, orig_nents = %d\n", ++ __func__, scheduler->core, ++ (unsigned long)virt_addr->addr, sgt->orig_nents); + goto free_dma_buffer; + } + -+ buffer->sgt = sgt; -+ buffer->offset = virt_addr->offset; -+ buffer->size = virt_addr->size; -+ buffer->scheduler = scheduler; ++ if (scheduler->data->mmu == RGA_IOMMU) ++ buffer->iova = buffer->dma_addr; + + internal_buffer->virt_addr = virt_addr; + internal_buffer->dma_buffer = buffer; + internal_buffer->mm_flag = mm_flag; + internal_buffer->phys_addr = phys_addr ? phys_addr + virt_addr->offset : 0; ++ internal_buffer->size = buffer->size - buffer->offset; ++ internal_buffer->scheduler = scheduler; + + return 0; + @@ -1909664,16 +1911335,12 @@ index 000000000..de7e9a6fd + +static void rga_mm_unmap_phys_addr(struct rga_internal_buffer *internal_buffer) +{ -+ WARN_ON(internal_buffer->dma_buffer == NULL); -+ -+ if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer)) -+ return; -+ -+ if (internal_buffer->dma_buffer->scheduler->data->mmu == RGA_IOMMU) -+ rga_iommu_unmap(internal_buffer->dma_buffer); ++ if (internal_buffer->dma_buffer != NULL) { ++ rga_dma_unmap_phys_addr(internal_buffer->dma_buffer); ++ kfree(internal_buffer->dma_buffer); ++ internal_buffer->dma_buffer = NULL; ++ } + -+ kfree(internal_buffer->dma_buffer); -+ internal_buffer->dma_buffer = NULL; + internal_buffer->phys_addr = 0; + internal_buffer->size = 0; +} @@ -1909686,13 +1911353,14 @@ index 000000000..de7e9a6fd + phys_addr_t phys_addr; + int buffer_size; + uint32_t mm_flag = 0; -+ struct rga_dma_buffer *buffer; ++ struct rga_dma_buffer *buffer = NULL; ++ struct device *map_dev; + struct rga_scheduler_t *scheduler; + + scheduler = job ? job->scheduler : + rga_drvdata->scheduler[rga_drvdata->map_scheduler_index]; + if (scheduler == NULL) { -+ pr_err("Invalid scheduler device!\n"); ++ rga_err("Invalid scheduler device!\n"); + return -EINVAL; + } + @@ -1909704,7 +1911372,7 @@ index 000000000..de7e9a6fd + internal_buffer->memory_parm.format, + NULL, NULL, NULL); + if (buffer_size <= 0) { -+ pr_err("Failed to get phys addr size!\n"); ++ rga_err("Failed to get phys addr size!\n"); + rga_dump_memory_parm(&internal_buffer->memory_parm); + return buffer_size == 0 ? -EINVAL : buffer_size; + } @@ -1909715,31 +1911383,39 @@ index 000000000..de7e9a6fd + mm_flag |= RGA_MEM_UNDER_4G; + + if (!rga_mm_check_memory_limit(scheduler, mm_flag)) { -+ pr_err("scheduler core[%d] unsupported mm_flag[0x%x]!\n", -+ scheduler->core, mm_flag); ++ rga_err("scheduler core[%d] unsupported mm_flag[0x%x]!\n", ++ scheduler->core, mm_flag); + return -EINVAL; + } + -+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); -+ if (buffer == NULL) { -+ pr_err("%s alloc internal dma buffer error!\n", __func__); -+ return -ENOMEM; -+ } -+ + if (scheduler->data->mmu == RGA_IOMMU) { -+ ret = rga_iommu_map(phys_addr, buffer_size, buffer, scheduler->dev); ++ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); ++ if (buffer == NULL) { ++ rga_err("%s alloc internal dma buffer error!\n", __func__); ++ return -ENOMEM; ++ } ++ ++ /* ++ * dma-buf api needs to use default_domain of main dev, ++ * and not IOMMU for devices without iommu_info ptr. ++ */ ++ map_dev = scheduler->iommu_info ? ++ scheduler->iommu_info->default_dev : scheduler->dev; ++ ret = rga_dma_map_phys_addr(phys_addr, buffer_size, buffer, ++ DMA_BIDIRECTIONAL, map_dev); + if (ret < 0) { -+ pr_err("%s core[%d] map phys_addr error!\n", __func__, scheduler->core); ++ rga_err("%s core[%d] map phys_addr error!\n", __func__, scheduler->core); + goto free_dma_buffer; + } -+ } + -+ buffer->scheduler = scheduler; ++ buffer->iova = buffer->dma_addr; ++ } + -+ internal_buffer->phys_addr = phys_addr; -+ internal_buffer->size = buffer_size; -+ internal_buffer->mm_flag = mm_flag; + internal_buffer->dma_buffer = buffer; ++ internal_buffer->mm_flag = mm_flag; ++ internal_buffer->phys_addr = phys_addr; ++ internal_buffer->size = buffer ? buffer->size : buffer_size; ++ internal_buffer->scheduler = scheduler; + + return 0; + @@ -1909763,7 +1911439,7 @@ index 000000000..de7e9a6fd + rga_mm_unmap_phys_addr(internal_buffer); + break; + default: -+ pr_err("Illegal external buffer!\n"); ++ rga_err("Illegal external buffer!\n"); + return -EFAULT; + } + @@ -1909785,41 +1911461,35 @@ index 000000000..de7e9a6fd + internal_buffer->type = external_buffer->type; + + ret = rga_mm_map_dma_buffer(external_buffer, internal_buffer, job); -+ if (ret < 0) { -+ pr_err("%s map dma_buf error!\n", __func__); ++ if (ret < 0) + return ret; -+ } + -+ internal_buffer->size = internal_buffer->dma_buffer->size - -+ internal_buffer->dma_buffer->offset; + internal_buffer->mm_flag |= RGA_MEM_NEED_USE_IOMMU; + break; + case RGA_VIRTUAL_ADDRESS: + internal_buffer->type = RGA_VIRTUAL_ADDRESS; + + ret = rga_mm_map_virt_addr(external_buffer, internal_buffer, job, write_flag); -+ if (ret < 0) { -+ pr_err("%s map virtual address error!\n", __func__); ++ if (ret < 0) + return ret; -+ } + -+ internal_buffer->size = internal_buffer->virt_addr->size - -+ internal_buffer->virt_addr->offset; + internal_buffer->mm_flag |= RGA_MEM_NEED_USE_IOMMU; + break; + case RGA_PHYSICAL_ADDRESS: + internal_buffer->type = RGA_PHYSICAL_ADDRESS; + + ret = rga_mm_map_phys_addr(external_buffer, internal_buffer, job); -+ if (ret < 0) { -+ pr_err("%s map physical address error!\n", __func__); ++ if (ret < 0) + return ret; -+ } + + internal_buffer->mm_flag |= RGA_MEM_NEED_USE_IOMMU; + break; + default: -+ pr_err("Illegal external buffer!\n"); ++ if (job) ++ rga_job_err(job, "Illegal external buffer!\n"); ++ else ++ rga_err("Illegal external buffer!\n"); ++ + return -EFAULT; + } + @@ -1909829,32 +1911499,46 @@ index 000000000..de7e9a6fd +static void rga_mm_kref_release_buffer(struct kref *ref) +{ + struct rga_internal_buffer *internal_buffer; ++ struct rga_mm *mm = rga_drvdata->mm; + + internal_buffer = container_of(ref, struct rga_internal_buffer, refcount); -+ rga_mm_unmap_buffer(internal_buffer); ++ idr_remove(&mm->memory_idr, internal_buffer->handle); ++ mm->buffer_count--; ++ mutex_unlock(&mm->lock); ++ + -+ idr_remove(&rga_drvdata->mm->memory_idr, internal_buffer->handle); ++ rga_mm_unmap_buffer(internal_buffer); + kfree(internal_buffer); -+ rga_drvdata->mm->buffer_count--; ++ ++ mutex_lock(&mm->lock); ++} ++ ++/* Force release the current internal_buffer from the IDR. */ ++static void rga_mm_force_releaser_buffer(struct rga_internal_buffer *buffer) ++{ ++ struct rga_mm *mm = rga_drvdata->mm; ++ ++ WARN_ON(!mutex_is_locked(&mm->lock)); ++ ++ idr_remove(&mm->memory_idr, buffer->handle); ++ mm->buffer_count--; ++ ++ rga_mm_unmap_buffer(buffer); ++ kfree(buffer); +} + +/* + * Called at driver close to release the memory's handle references. + */ -+static int rga_mm_handle_remove(int id, void *ptr, void *data) ++static int rga_mm_buffer_destroy_for_idr(int id, void *ptr, void *data) +{ + struct rga_internal_buffer *internal_buffer = ptr; + -+ rga_mm_kref_release_buffer(&internal_buffer->refcount); ++ rga_mm_force_releaser_buffer(internal_buffer); + + return 0; +} + -+static void rga_mm_buffer_destroy(struct rga_internal_buffer *buffer) -+{ -+ rga_mm_kref_release_buffer(&buffer->refcount); -+} -+ +static struct rga_internal_buffer * +rga_mm_lookup_external(struct rga_mm *mm_session, + struct rga_external_buffer *external_buffer, @@ -1909925,7 +1911609,7 @@ index 000000000..de7e9a6fd + break; + + default: -+ pr_err("Illegal external buffer!\n"); ++ rga_err("Illegal external buffer!\n"); + return NULL; + } + @@ -1909949,7 +1911633,7 @@ index 000000000..de7e9a6fd + + output_buffer = rga_mm_lookup_handle(mm_session, handle); + if (output_buffer == NULL) { -+ pr_err("This handle[%ld] is illegal.\n", (unsigned long)handle); ++ rga_err("This handle[%ld] is illegal.\n", (unsigned long)handle); + return -EINVAL; + } + @@ -1909974,8 +1911658,9 @@ index 000000000..de7e9a6fd + +void rga_mm_dump_buffer(struct rga_internal_buffer *dump_buffer) +{ -+ pr_info("handle = %d refcount = %d mm_flag = 0x%x\n", -+ dump_buffer->handle, kref_read(&dump_buffer->refcount), ++ rga_buf_log(dump_buffer, "type = %s, refcount = %d mm_flag = 0x%x\n", ++ rga_get_memory_type_str(dump_buffer->type), ++ kref_read(&dump_buffer->refcount), + dump_buffer->mm_flag); + + switch (dump_buffer->type) { @@ -1909984,24 +1911669,25 @@ index 000000000..de7e9a6fd + if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer)) + break; + -+ pr_info("dma_buffer:\n"); -+ pr_info("dma_buf = %p, iova = 0x%lx, sgt = %p, size = %ld, map_core = 0x%x\n", -+ dump_buffer->dma_buffer->dma_buf, ++ rga_buf_log(dump_buffer, "dma_buf = %p\n", ++ dump_buffer->dma_buffer->dma_buf); ++ rga_buf_log(dump_buffer, "iova = 0x%lx, dma_addr = 0x%lx, offset = 0x%lx, sgt = %p, size = %ld, map_core = 0x%x\n", + (unsigned long)dump_buffer->dma_buffer->iova, ++ (unsigned long)dump_buffer->dma_buffer->dma_addr, ++ (unsigned long)dump_buffer->dma_buffer->offset, + dump_buffer->dma_buffer->sgt, + dump_buffer->dma_buffer->size, -+ dump_buffer->dma_buffer->scheduler->core); ++ dump_buffer->scheduler->core); + + if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) -+ pr_info("is contiguous, pa = 0x%lx\n", ++ rga_log("is contiguous, pa = 0x%lx\n", + (unsigned long)dump_buffer->phys_addr); + break; + case RGA_VIRTUAL_ADDRESS: + if (dump_buffer->virt_addr == NULL) + break; + -+ pr_info("virtual address:\n"); -+ pr_info("va = 0x%lx, pages = %p, size = %ld\n", ++ rga_buf_log(dump_buffer, "va = 0x%lx, pages = %p, size = %ld\n", + (unsigned long)dump_buffer->virt_addr->addr, + dump_buffer->virt_addr->pages, + dump_buffer->virt_addr->size); @@ -1910009,22 +1911695,33 @@ index 000000000..de7e9a6fd + if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer)) + break; + -+ pr_info("iova = 0x%lx, offset = 0x%lx, sgt = %p, size = %ld, map_core = 0x%x\n", ++ rga_buf_log(dump_buffer, "iova = 0x%lx, dma_addr = 0x%lx, offset = 0x%lx, sgt = %p, size = %ld, map_core = 0x%x\n", + (unsigned long)dump_buffer->dma_buffer->iova, ++ (unsigned long)dump_buffer->dma_buffer->dma_addr, + (unsigned long)dump_buffer->dma_buffer->offset, + dump_buffer->dma_buffer->sgt, + dump_buffer->dma_buffer->size, -+ dump_buffer->dma_buffer->scheduler->core); ++ dump_buffer->scheduler->core); + + if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) -+ pr_info("is contiguous, pa = 0x%lx\n", ++ rga_buf_log(dump_buffer, "is contiguous, pa = 0x%lx\n", + (unsigned long)dump_buffer->phys_addr); + break; + case RGA_PHYSICAL_ADDRESS: -+ pr_info("physical address: pa = 0x%lx\n", (unsigned long)dump_buffer->phys_addr); ++ rga_buf_log(dump_buffer, "pa = 0x%lx\n", (unsigned long)dump_buffer->phys_addr); ++ ++ if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer)) ++ break; ++ ++ rga_buf_log(dump_buffer, "iova = 0x%lx, dma_addr = 0x%lx, offset = 0x%lx, size = %ld, map_core = 0x%x\n", ++ (unsigned long)dump_buffer->dma_buffer->iova, ++ (unsigned long)dump_buffer->dma_buffer->dma_addr, ++ (unsigned long)dump_buffer->dma_buffer->offset, ++ dump_buffer->dma_buffer->size, ++ dump_buffer->scheduler->core); + break; + default: -+ pr_err("Illegal external buffer!\n"); ++ rga_buf_err(dump_buffer, "Illegal buffer! type= %d\n", dump_buffer->type); + break; + } +} @@ -1910036,15 +1911733,15 @@ index 000000000..de7e9a6fd + + WARN_ON(!mutex_is_locked(&mm_session->lock)); + -+ pr_info("rga mm info:\n"); ++ rga_log("rga mm info:\n"); + -+ pr_info("buffer count = %d\n", mm_session->buffer_count); -+ pr_info("===============================================================\n"); ++ rga_log("buffer count = %d\n", mm_session->buffer_count); ++ rga_log("===============================================================\n"); + + idr_for_each_entry(&mm_session->memory_idr, dump_buffer, id) { + rga_mm_dump_buffer(dump_buffer); + -+ pr_info("---------------------------------------------------------------\n"); ++ rga_log("---------------------------------------------------------------\n"); + } +} + @@ -1910117,7 +1911814,7 @@ index 000000000..de7e9a6fd + * The length of each sgl is expected to be obtained here, not + * the length of the entire dma_buf, so sg_dma_len() is not used. + */ -+ len = sgl->length >> PAGE_SHIFT; ++ len = (sgl->length + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + + if (use_dma_address) + /* @@ -1910136,6 +1911833,8 @@ index 000000000..de7e9a6fd + else + Address = sg_phys(sgl); + ++ Address &= PAGE_MASK; ++ + for (i = 0; i < len; i++) { + if (mapped_size + i >= pageCount) { + break_flag = 1; @@ -1910174,8 +1911873,8 @@ index 000000000..de7e9a6fd + img_size = rga_image_size_cal(img->vir_w, img->vir_h, img->format, + &yrgb_size, &uv_size, &v_size); + if (img_size <= 0) { -+ pr_err("Image size cal error! width = %d, height = %d, format = %s\n", -+ img->vir_w, img->vir_h, rga_get_format_name(img->format)); ++ rga_job_err(job, "Image size cal error! width = %d, height = %d, format = %s\n", ++ img->vir_w, img->vir_h, rga_get_format_name(img->format)); + return -EINVAL; + } + @@ -1910194,23 +1911893,17 @@ index 000000000..de7e9a6fd + page_count = yrgb_count + uv_count + v_count; + + if (page_count <= 0) { -+ pr_err("page count cal error! yrba = %d, uv = %d, v = %d\n", -+ yrgb_count, uv_count, v_count); ++ rga_job_err(job, "page count cal error! yrba = %d, uv = %d, v = %d\n", ++ yrgb_count, uv_count, v_count); + return -EFAULT; + } + + if (job->flags & RGA_JOB_USE_HANDLE) { -+ order = get_order(page_count * sizeof(uint32_t *)); -+ if (order >= MAX_ORDER) { -+ pr_err("Can not alloc pages with order[%d] for page_table, max_order = %d\n", -+ order, MAX_ORDER); -+ return -ENOMEM; -+ } -+ -+ page_table = (uint32_t *)__get_free_pages(GFP_KERNEL | GFP_DMA32, order); ++ page_table = (uint32_t *)rga_get_free_pages(GFP_KERNEL | GFP_DMA32, ++ &order, page_count * sizeof(uint32_t *)); + if (page_table == NULL) { -+ pr_err("%s can not alloc pages for page_table, order = %d\n", -+ __func__, order); ++ rga_job_err(job, "%s can not alloc pages for page_table, order = %d\n", ++ __func__, order); + return -ENOMEM; + } + } else { @@ -1910218,7 +1911911,7 @@ index 000000000..de7e9a6fd + + page_table = rga_mmu_buf_get(rga_drvdata->mmu_base, page_count); + if (page_table == NULL) { -+ pr_err("mmu_buf get error!\n"); ++ rga_err("mmu_buf get error!\n"); + mutex_unlock(&rga_drvdata->lock); + return -EFAULT; + } @@ -1910228,7 +1911921,7 @@ index 000000000..de7e9a6fd + + sgt = rga_mm_lookup_sgt(job_buf->y_addr); + if (sgt == NULL) { -+ pr_err("rga2 cannot get sgt from internal buffer!\n"); ++ rga_job_err(job, "rga2 cannot get sgt from internal buffer!\n"); + ret = -EINVAL; + goto err_free_page_table; + } @@ -1910236,7 +1911929,7 @@ index 000000000..de7e9a6fd + + sgt = rga_mm_lookup_sgt(job_buf->uv_addr); + if (sgt == NULL) { -+ pr_err("rga2 cannot get sgt from internal buffer!\n"); ++ rga_job_err(job, "rga2 cannot get sgt from internal buffer!\n"); + ret = -EINVAL; + goto err_free_page_table; + } @@ -1910244,7 +1911937,7 @@ index 000000000..de7e9a6fd + + sgt = rga_mm_lookup_sgt(job_buf->v_addr); + if (sgt == NULL) { -+ pr_err("rga2 cannot get sgt from internal buffer!\n"); ++ rga_job_err(job, "rga2 cannot get sgt from internal buffer!\n"); + ret = -EINVAL; + goto err_free_page_table; + } @@ -1910259,23 +1911952,17 @@ index 000000000..de7e9a6fd + + page_count = RGA_GET_PAGE_COUNT(img_size + img_offset); + if (page_count < 0) { -+ pr_err("page count cal error! yrba = %d, uv = %d, v = %d\n", -+ yrgb_count, uv_count, v_count); ++ rga_job_err(job, "page count cal error! yrba = %d, uv = %d, v = %d\n", ++ yrgb_count, uv_count, v_count); + return -EFAULT; + } + + if (job->flags & RGA_JOB_USE_HANDLE) { -+ order = get_order(page_count * sizeof(uint32_t *)); -+ if (order >= MAX_ORDER) { -+ pr_err("Can not alloc pages with order[%d] for page_table, max_order = %d\n", -+ order, MAX_ORDER); -+ return -ENOMEM; -+ } -+ -+ page_table = (uint32_t *)__get_free_pages(GFP_KERNEL | GFP_DMA32, order); ++ page_table = (uint32_t *)rga_get_free_pages(GFP_KERNEL | GFP_DMA32, ++ &order, page_count * sizeof(uint32_t *)); + if (page_table == NULL) { -+ pr_err("%s can not alloc pages for page_table, order = %d\n", -+ __func__, order); ++ rga_job_err(job, "%s can not alloc pages for page_table, order = %d\n", ++ __func__, order); + return -ENOMEM; + } + } else { @@ -1910283,7 +1911970,7 @@ index 000000000..de7e9a6fd + + page_table = rga_mmu_buf_get(rga_drvdata->mmu_base, page_count); + if (page_table == NULL) { -+ pr_err("mmu_buf get error!\n"); ++ rga_job_err(job, "mmu_buf get error!\n"); + mutex_unlock(&rga_drvdata->lock); + return -EFAULT; + } @@ -1910293,7 +1911980,7 @@ index 000000000..de7e9a6fd + + sgt = rga_mm_lookup_sgt(job_buf->addr); + if (sgt == NULL) { -+ pr_err("rga2 cannot get sgt from internal buffer!\n"); ++ rga_job_err(job, "rga2 cannot get sgt from internal buffer!\n"); + ret = -EINVAL; + goto err_free_page_table; + } @@ -1910321,28 +1912008,44 @@ index 000000000..de7e9a6fd +{ + struct sg_table *sgt; + struct rga_scheduler_t *scheduler; ++ ktime_t timestamp = ktime_get(); + -+ scheduler = buffer->dma_buffer->scheduler; ++ scheduler = buffer->scheduler; + if (scheduler == NULL) { -+ pr_err("%s(%d), failed to get scheduler, core = 0x%x\n", -+ __func__, __LINE__, job->core); ++ rga_job_err(job, "%s(%d), failed to get scheduler, core = 0x%x\n", ++ __func__, __LINE__, job->core); + return -EFAULT; + } + -+ if (buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS && -+ scheduler->data->mmu != RGA_IOMMU) { -+ dma_sync_single_for_device(scheduler->dev, buffer->phys_addr, buffer->size, dir); ++ if (buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) { ++ if (scheduler->data->mmu == RGA_IOMMU) { ++ if (rga_mm_is_invalid_dma_buffer(buffer->dma_buffer)) { ++ rga_job_err(job, "invalid dma-buffer with IOMMU device!\n"); ++ return -EFAULT; ++ } ++ ++ dma_sync_single_for_device(buffer->dma_buffer->map_dev, ++ buffer->dma_buffer->iova, buffer->dma_buffer->size, dir); ++ } else { ++ dma_sync_single_for_device(scheduler->dev, ++ buffer->phys_addr, buffer->size, dir); ++ } + } else { + sgt = rga_mm_lookup_sgt(buffer); + if (sgt == NULL) { -+ pr_err("%s(%d), failed to get sgt, core = 0x%x\n", -+ __func__, __LINE__, job->core); ++ rga_job_err(job, "%s(%d), failed to get sgt, core = 0x%x\n", ++ __func__, __LINE__, job->core); + return -EINVAL; + } + + dma_sync_sg_for_device(scheduler->dev, sgt->sgl, sgt->orig_nents, dir); + } + ++ if (DEBUGGER_EN(TIME)) ++ rga_job_log(job, "handle[%d], %s, flush CPU cache for device cost %lld us\n", ++ buffer->handle, rga_get_dma_data_direction_str(dir), ++ ktime_us_delta(ktime_get(), timestamp)); ++ + return 0; +} + @@ -1910352,28 +1912055,44 @@ index 000000000..de7e9a6fd +{ + struct sg_table *sgt; + struct rga_scheduler_t *scheduler; ++ ktime_t timestamp = ktime_get(); + -+ scheduler = buffer->dma_buffer->scheduler; ++ scheduler = buffer->scheduler; + if (scheduler == NULL) { -+ pr_err("%s(%d), failed to get scheduler, core = 0x%x\n", -+ __func__, __LINE__, job->core); ++ rga_job_err(job, "%s(%d), failed to get scheduler, core = 0x%x\n", ++ __func__, __LINE__, job->core); + return -EFAULT; + } + -+ if (buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS && -+ scheduler->data->mmu != RGA_IOMMU) { -+ dma_sync_single_for_cpu(scheduler->dev, buffer->phys_addr, buffer->size, dir); ++ if (buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) { ++ if (scheduler->data->mmu == RGA_IOMMU) { ++ if (rga_mm_is_invalid_dma_buffer(buffer->dma_buffer)) { ++ rga_job_err(job, "invalid dma-buffer with IOMMU device!\n"); ++ return -EFAULT; ++ } ++ ++ dma_sync_single_for_cpu(buffer->dma_buffer->map_dev, ++ buffer->dma_buffer->iova, buffer->dma_buffer->size, dir); ++ } else { ++ dma_sync_single_for_cpu(scheduler->dev, ++ buffer->phys_addr, buffer->size, dir); ++ } + } else { + sgt = rga_mm_lookup_sgt(buffer); + if (sgt == NULL) { -+ pr_err("%s(%d), failed to get sgt, core = 0x%x\n", -+ __func__, __LINE__, job->core); ++ rga_job_err(job, "%s(%d), failed to get sgt, core = 0x%x\n", ++ __func__, __LINE__, job->core); + return -EINVAL; + } + + dma_sync_sg_for_cpu(scheduler->dev, sgt->sgl, sgt->orig_nents, dir); + } + ++ if (DEBUGGER_EN(TIME)) ++ rga_job_log(job, "handle[%d], %s, flush CPU cache for CPU cost %lld us\n", ++ buffer->handle, rga_get_dma_data_direction_str(dir), ++ ktime_us_delta(ktime_get(), timestamp)); ++ + return 0; +} + @@ -1910385,12 +1912104,15 @@ index 000000000..de7e9a6fd + + switch (job->scheduler->data->mmu) { + case RGA_IOMMU: -+ addr = rga_mm_lookup_iova(internal_buffer); -+ if (addr == 0) { -+ pr_err("core[%d] lookup buffer_type[0x%x] iova error!\n", -+ job->core, internal_buffer->type); ++ if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer)) { ++ rga_job_err(job, ++ "core[%d] handle[%d] lookup buffer_type[0x%x] iova error!\n", ++ job->core, internal_buffer->handle, internal_buffer->type); + return -EINVAL; + } ++ ++ addr = rga_mm_lookup_iova(internal_buffer); ++ + break; + case RGA_MMU: + default: @@ -1910411,7 +1912133,7 @@ index 000000000..de7e9a6fd + addr = internal_buffer->phys_addr; + break; + default: -+ pr_err("Illegal external buffer!\n"); ++ rga_job_err(job, "Illegal external buffer!\n"); + return -EFAULT; + } + break; @@ -1910434,14 +1912156,14 @@ index 000000000..de7e9a6fd + struct rga_internal_buffer *internal_buffer = NULL; + + if (handle == 0) { -+ pr_err("No buffer handle can be used!\n"); ++ rga_job_err(job, "No buffer handle can be used!\n"); + return -EFAULT; + } + + mutex_lock(&mm->lock); + *buf = rga_mm_lookup_handle(mm, handle); + if (*buf == NULL) { -+ pr_err("This handle[%ld] is illegal.\n", (unsigned long)handle); ++ rga_job_err(job, "This handle[%ld] is illegal.\n", (unsigned long)handle); + + mutex_unlock(&mm->lock); + return -EFAULT; @@ -1910451,7 +1912173,7 @@ index 000000000..de7e9a6fd + kref_get(&internal_buffer->refcount); + + if (DEBUGGER_EN(MM)) { -+ pr_info("handle[%d] get info:\n", (int)handle); ++ rga_job_log(job, "handle[%d] get info:\n", (int)handle); + rga_mm_dump_buffer(internal_buffer); + } + @@ -1910459,13 +1912181,14 @@ index 000000000..de7e9a6fd + + ret = rga_mm_get_buffer_info(job, internal_buffer, channel_addr); + if (ret < 0) { -+ pr_err("handle[%ld] failed to get internal buffer info!\n", (unsigned long)handle); ++ rga_job_err(job, "handle[%ld] failed to get internal buffer info!\n", ++ (unsigned long)handle); + return ret; + } + + if (internal_buffer->size < require_size) { + ret = -EINVAL; -+ pr_err("Only get buffer %ld byte from handle[%ld], but current required %d byte\n", ++ rga_job_err(job, "Only get buffer %ld byte from handle[%ld], but current required %d byte\n", + internal_buffer->size, (unsigned long)handle, require_size); + + goto put_internal_buffer; @@ -1910479,7 +1912202,7 @@ index 000000000..de7e9a6fd + */ + ret = rga_mm_sync_dma_sg_for_device(internal_buffer, job, dir); + if (ret < 0) { -+ pr_err("sync sgt for device error!\n"); ++ rga_job_err(job, "sync sgt for device error!\n"); + goto put_internal_buffer; + } + } @@ -1910502,10 +1912225,10 @@ index 000000000..de7e9a6fd +{ + if (internal_buffer->mm_flag & RGA_MEM_FORCE_FLUSH_CACHE && dir != DMA_NONE) + if (rga_mm_sync_dma_sg_for_cpu(internal_buffer, job, dir)) -+ pr_err("sync sgt for cpu error!\n"); ++ rga_job_err(job, "sync sgt for cpu error!\n"); + + if (DEBUGGER_EN(MM)) { -+ pr_info("handle[%d] put info:\n", (int)internal_buffer->handle); ++ rga_job_log(job, "handle[%d] put info:\n", (int)internal_buffer->handle); + rga_mm_dump_buffer(internal_buffer); + } + @@ -1910543,8 +1912266,8 @@ index 000000000..de7e9a6fd + img_size = rga_image_size_cal(img->vir_w, img->vir_h, img->format, + &yrgb_size, &uv_size, &v_size); + if (img_size <= 0) { -+ pr_err("Image size cal error! width = %d, height = %d, format = %s\n", -+ img->vir_w, img->vir_h, rga_get_format_name(img->format)); ++ rga_job_err(job, "Image size cal error! width = %d, height = %d, format = %s\n", ++ img->vir_w, img->vir_h, rga_get_format_name(img->format)); + return -EINVAL; + } + @@ -1910555,7 +1912278,8 @@ index 000000000..de7e9a6fd + ret = rga_mm_get_buffer(mm, job, handle, &img->yrgb_addr, + &job_buf->y_addr, yrgb_size, dir); + if (ret < 0) { -+ pr_err("handle[%d] Can't get y/rgb address info!\n", handle); ++ rga_job_err(job, "handle[%d] Can't get y/rgb address info!\n", ++ handle); + return ret; + } + } @@ -1910565,7 +1912289,7 @@ index 000000000..de7e9a6fd + ret = rga_mm_get_buffer(mm, job, handle, &img->uv_addr, + &job_buf->uv_addr, uv_size, dir); + if (ret < 0) { -+ pr_err("handle[%d] Can't get uv address info!\n", handle); ++ rga_job_err(job, "handle[%d] Can't get uv address info!\n", handle); + return ret; + } + } @@ -1910575,7 +1912299,7 @@ index 000000000..de7e9a6fd + ret = rga_mm_get_buffer(mm, job, handle, &img->v_addr, + &job_buf->v_addr, v_size, dir); + if (ret < 0) { -+ pr_err("handle[%d] Can't get uv address info!\n", handle); ++ rga_job_err(job, "handle[%d] Can't get uv address info!\n", handle); + return ret; + } + } @@ -1910585,7 +1912309,8 @@ index 000000000..de7e9a6fd + ret = rga_mm_get_buffer(mm, job, handle, &img->yrgb_addr, + &job_buf->addr, img_size, dir); + if (ret < 0) { -+ pr_err("handle[%d] Can't get y/rgb address info!\n", handle); ++ rga_job_err(job, "handle[%d] Can't get y/rgb address info!\n", ++ handle); + return ret; + } + } @@ -1910597,7 +1912322,7 @@ index 000000000..de7e9a6fd + rga_mm_is_need_mmu(job, job_buf->addr)) { + ret = rga_mm_set_mmu_base(job, img, job_buf); + if (ret < 0) { -+ pr_err("Can't set RGA2 MMU_BASE from handle!\n"); ++ rga_job_err(job, "Can't set RGA2 MMU_BASE from handle!\n"); + + rga_mm_put_channel_handle_info(mm, job, job_buf, dir); + return ret; @@ -1910621,21 +1912346,21 @@ index 000000000..de7e9a6fd + case BITBLT_MODE: + case COLOR_PALETTE_MODE: + if (unlikely(req->src.yrgb_addr <= 0)) { -+ pr_err("render_mode[0x%x] src0 channel handle[%ld] must is valid!", -+ req->render_mode, (unsigned long)req->src.yrgb_addr); ++ rga_job_err(job, "render_mode[0x%x] src0 channel handle[%ld] must is valid!", ++ req->render_mode, (unsigned long)req->src.yrgb_addr); + return -EINVAL; + } + + if (unlikely(req->dst.yrgb_addr <= 0)) { -+ pr_err("render_mode[0x%x] dst channel handle[%ld] must is valid!", -+ req->render_mode, (unsigned long)req->dst.yrgb_addr); ++ rga_job_err(job, "render_mode[0x%x] dst channel handle[%ld] must is valid!", ++ req->render_mode, (unsigned long)req->dst.yrgb_addr); + return -EINVAL; + } + + if (req->bsfilter_flag) { + if (unlikely(req->pat.yrgb_addr <= 0)) { -+ pr_err("render_mode[0x%x] src1/pat channel handle[%ld] must is valid!", -+ req->render_mode, (unsigned long)req->pat.yrgb_addr); ++ rga_job_err(job, "render_mode[0x%x] src1/pat channel handle[%ld] must is valid!", ++ req->render_mode, (unsigned long)req->pat.yrgb_addr); + return -EINVAL; + } + } @@ -1910643,8 +1912368,8 @@ index 000000000..de7e9a6fd + break; + case COLOR_FILL_MODE: + if (unlikely(req->dst.yrgb_addr <= 0)) { -+ pr_err("render_mode[0x%x] dst channel handle[%ld] must is valid!", -+ req->render_mode, (unsigned long)req->dst.yrgb_addr); ++ rga_job_err(job, "render_mode[0x%x] dst channel handle[%ld] must is valid!", ++ req->render_mode, (unsigned long)req->dst.yrgb_addr); + return -EINVAL; + } + @@ -1910653,14 +1912378,14 @@ index 000000000..de7e9a6fd + case UPDATE_PALETTE_TABLE_MODE: + case UPDATE_PATTEN_BUF_MODE: + if (unlikely(req->pat.yrgb_addr <= 0)) { -+ pr_err("render_mode[0x%x] lut/pat channel handle[%ld] must is valid!, req->render_mode", -+ req->render_mode, (unsigned long)req->pat.yrgb_addr); ++ rga_job_err(job, "render_mode[0x%x] lut/pat channel handle[%ld] must is valid!", ++ req->render_mode, (unsigned long)req->pat.yrgb_addr); + return -EINVAL; + } + + break; + default: -+ pr_err("%s, unknown render mode!\n", __func__); ++ rga_job_err(job, "%s, unknown render mode!\n", __func__); + break; + } + @@ -1910669,7 +1912394,7 @@ index 000000000..de7e9a6fd + &job->src_buffer, + DMA_TO_DEVICE); + if (ret < 0) { -+ pr_err("Can't get src buffer info from handle!\n"); ++ rga_job_err(job, "Can't get src buffer info from handle!\n"); + return ret; + } + } @@ -1910679,7 +1912404,7 @@ index 000000000..de7e9a6fd + &job->dst_buffer, + DMA_TO_DEVICE); + if (ret < 0) { -+ pr_err("Can't get dst buffer info from handle!\n"); ++ rga_job_err(job, "Can't get dst buffer info from handle!\n"); + return ret; + } + } @@ -1910701,7 +1912426,7 @@ index 000000000..de7e9a6fd + DMA_BIDIRECTIONAL); + } + if (ret < 0) { -+ pr_err("Can't get pat buffer info from handle!\n"); ++ rga_job_err(job, "Can't get pat buffer info from handle!\n"); + return ret; + } + } @@ -1910740,15 +1912465,15 @@ index 000000000..de7e9a6fd + /* Default unsupported multi-planar format */ + external_buffer = kzalloc(sizeof(*external_buffer), GFP_KERNEL); + if (external_buffer == NULL) { -+ pr_err("Cannot alloc job_buffer!\n"); ++ rga_err("Cannot alloc job_buffer!\n"); + return -ENOMEM; + } + + if (img_info->yrgb_addr) { + dma_buf = dma_buf_get(img_info->yrgb_addr); + if (IS_ERR(dma_buf)) { -+ pr_err("%s dma_buf_get fail fd[%lu]\n", -+ __func__, (unsigned long)img_info->yrgb_addr); ++ rga_err("%s dma_buf_get fail fd[%lu]\n", ++ __func__, (unsigned long)img_info->yrgb_addr); + kfree(external_buffer); + return -EINVAL; + } @@ -1910812,7 +1912537,7 @@ index 000000000..de7e9a6fd + mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 8) & 1); + ret = rga_mm_get_channel_external_buffer(mmu_flag, src0, &job->src_buffer); + if (ret < 0) { -+ pr_err("Cannot get src0 channel buffer!\n"); ++ rga_job_err(job, "Cannot get src0 channel buffer!\n"); + return ret; + } + } @@ -1910821,7 +1912546,7 @@ index 000000000..de7e9a6fd + mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 10) & 1); + ret = rga_mm_get_channel_external_buffer(mmu_flag, dst, &job->dst_buffer); + if (ret < 0) { -+ pr_err("Cannot get dst channel buffer!\n"); ++ rga_job_err(job, "Cannot get dst channel buffer!\n"); + goto error_put_buffer; + } + } @@ -1910830,7 +1912555,7 @@ index 000000000..de7e9a6fd + mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 9) & 1); + ret = rga_mm_get_channel_external_buffer(mmu_flag, src1, &job->src1_buffer); + if (ret < 0) { -+ pr_err("Cannot get src1 channel buffer!\n"); ++ rga_job_err(job, "Cannot get src1 channel buffer!\n"); + goto error_put_buffer; + } + } @@ -1910839,7 +1912564,7 @@ index 000000000..de7e9a6fd + mmu_flag = ((job->rga_command_base.mmu_info.mmu_flag >> 11) & 1); + ret = rga_mm_get_channel_external_buffer(mmu_flag, els, &job->els_buffer); + if (ret < 0) { -+ pr_err("Cannot get els channel buffer!\n"); ++ rga_job_err(job, "Cannot get els channel buffer!\n"); + goto error_put_buffer; + } + } @@ -1910856,7 +1912581,12 @@ index 000000000..de7e9a6fd +{ + if (job_buffer->addr->mm_flag & RGA_MEM_FORCE_FLUSH_CACHE && dir != DMA_NONE) + if (rga_mm_sync_dma_sg_for_cpu(job_buffer->addr, job, dir)) -+ pr_err("sync sgt for cpu error!\n"); ++ rga_job_err(job, "sync sgt for cpu error!\n"); ++ ++ if (DEBUGGER_EN(MM)) { ++ rga_job_log(job, "unmap buffer:\n"); ++ rga_mm_dump_buffer(job_buffer->addr); ++ } + + rga_mm_unmap_buffer(job_buffer->addr); + kfree(job_buffer->addr); @@ -1910875,26 +1912605,33 @@ index 000000000..de7e9a6fd + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (buffer == NULL) { -+ pr_err("%s alloc internal_buffer error!\n", __func__); ++ rga_job_err(job, "%s alloc internal_buffer error!\n", __func__); + return -ENOMEM; + } + + ret = rga_mm_map_buffer(job_buffer->ex_addr, buffer, job, write_flag); + if (ret < 0) { -+ pr_err("job buffer map failed!\n"); ++ rga_job_err(job, "job buffer map failed!\n"); + goto error_free_buffer; + } + ++ buffer->session = job->session; ++ ++ if (DEBUGGER_EN(MM)) { ++ rga_job_log(job, "map buffer:\n"); ++ rga_mm_dump_buffer(buffer); ++ } ++ + ret = rga_mm_get_buffer_info(job, buffer, &img->yrgb_addr); + if (ret < 0) { -+ pr_err("Failed to get internal buffer info!\n"); ++ rga_job_err(job, "Failed to get internal buffer info!\n"); + goto error_unmap_buffer; + } + + if (buffer->mm_flag & RGA_MEM_FORCE_FLUSH_CACHE) { + ret = rga_mm_sync_dma_sg_for_device(buffer, job, dir); + if (ret < 0) { -+ pr_err("sync sgt for device error!\n"); ++ rga_job_err(job, "sync sgt for device error!\n"); + goto error_unmap_buffer; + } + } @@ -1910907,7 +1912644,7 @@ index 000000000..de7e9a6fd + rga_mm_is_need_mmu(job, job_buffer->addr)) { + ret = rga_mm_set_mmu_base(job, img, job_buffer); + if (ret < 0) { -+ pr_err("Can't set RGA2 MMU_BASE!\n"); ++ rga_job_err(job, "Can't set RGA2 MMU_BASE!\n"); + job_buffer->addr = NULL; + goto error_unmap_buffer; + } @@ -1910945,7 +1912682,7 @@ index 000000000..de7e9a6fd + + ret = rga_mm_get_external_buffer(job); + if (ret < 0) { -+ pr_err("failed to get external buffer from job_cmd!\n"); ++ rga_job_err(job, "failed to get external buffer from job_cmd!\n"); + return ret; + } + @@ -1910956,7 +1912693,7 @@ index 000000000..de7e9a6fd + &job->src_buffer, + DMA_TO_DEVICE, false); + if (ret < 0) { -+ pr_err("src channel map job buffer failed!"); ++ rga_job_err(job, "src channel map job buffer failed!"); + goto error_unmap_buffer; + } + } @@ -1910966,7 +1912703,7 @@ index 000000000..de7e9a6fd + &job->dst_buffer, + DMA_TO_DEVICE, true); + if (ret < 0) { -+ pr_err("dst channel map job buffer failed!"); ++ rga_job_err(job, "dst channel map job buffer failed!"); + goto error_unmap_buffer; + } + } @@ -1910981,7 +1912718,7 @@ index 000000000..de7e9a6fd + &job->src1_buffer, + dir, false); + if (ret < 0) { -+ pr_err("src1 channel map job buffer failed!"); ++ rga_job_err(job, "src1 channel map job buffer failed!"); + goto error_unmap_buffer; + } + } @@ -1910991,7 +1912728,7 @@ index 000000000..de7e9a6fd + &job->els_buffer, + DMA_BIDIRECTIONAL, false); + if (ret < 0) { -+ pr_err("els channel map job buffer failed!"); ++ rga_job_err(job, "els channel map job buffer failed!"); + goto error_unmap_buffer; + } + } @@ -1911005,31 +1912742,221 @@ index 000000000..de7e9a6fd + return ret; +} + ++static void rga_mm_free_channel_fake_buffer(struct rga_job *job, ++ struct rga_job_buffer *job_buffer, ++ enum dma_data_direction dir) ++{ ++ struct rga_internal_buffer *buffer = job_buffer->addr; ++ ++ if (rga_mm_is_invalid_dma_buffer(buffer->dma_buffer)) ++ return; ++ ++ if (DEBUGGER_EN(MM)) { ++ rga_job_log(job, "free fake-buffer dump info:\n"); ++ rga_mm_dump_buffer(buffer); ++ } ++ ++ rga_dma_free(buffer->dma_buffer); ++ kfree(buffer); ++ job_buffer->addr = NULL; ++} ++ ++static int rga_mm_alloc_channel_fake_buffer(struct rga_job *job, ++ struct rga_img_info_t *img, ++ struct rga_job_buffer *job_buffer, ++ enum dma_data_direction dir) ++{ ++ int ret; ++ int size; ++ uint32_t mm_flag; ++ uint64_t phys_addr; ++ struct rga_internal_buffer *buffer; ++ struct rga_dma_buffer *dma_buf; ++ ++ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); ++ if (buffer == NULL) { ++ rga_job_err(job, "%s alloc internal_buffer error!\n", __func__); ++ return -ENOMEM; ++ } ++ ++ size = rga_image_size_cal(img->vir_w, img->vir_h, img->format, ++ NULL, NULL, NULL); ++ dma_buf = rga_dma_alloc_coherent(job->scheduler, size); ++ if (dma_buf == NULL) { ++ ret = -ENOMEM; ++ rga_job_err(job, "%s failed to alloc dma_buf.\n", __func__); ++ goto error_free_buffer; ++ } ++ ++ mm_flag = RGA_MEM_PHYSICAL_CONTIGUOUS | RGA_MEM_UNDER_4G; ++ if (job->scheduler->data->mmu != RGA_IOMMU) { ++ mm_flag |= RGA_MEM_NEED_USE_IOMMU; ++ phys_addr = 0; ++ } else { ++ phys_addr = dma_buf->dma_addr; ++ } ++ ++ if (!rga_mm_check_memory_limit(job->scheduler, mm_flag)) { ++ rga_job_err(job, "%s scheduler core[%d] unsupported mm_flag[0x%x]!\n", ++ __func__, job->scheduler->core, mm_flag); ++ ret = -EINVAL; ++ goto error_free_dma_buf; ++ } ++ ++ buffer->type = RGA_DMA_BUFFER_PTR; ++ buffer->size = dma_buf->size - dma_buf->offset; ++ buffer->mm_flag = mm_flag; ++ buffer->dma_buffer = dma_buf; ++ buffer->phys_addr = phys_addr; ++ ++ buffer->memory_parm.width = img->vir_w; ++ buffer->memory_parm.height = img->vir_h; ++ buffer->memory_parm.format = img->format; ++ buffer->memory_parm.size = size; ++ ++ ret = rga_mm_get_buffer_info(job, buffer, &img->yrgb_addr); ++ if (ret < 0) ++ goto error_free_dma_buf; ++ ++ rga_convert_addr(img, false); ++ ++ job_buffer->addr = buffer; ++ ++ if (job->scheduler->data->mmu == RGA_MMU && ++ rga_mm_is_need_mmu(job, job_buffer->addr)) { ++ ret = rga_mm_set_mmu_base(job, img, job_buffer); ++ if (ret < 0) { ++ job_buffer->addr = NULL; ++ goto error_free_dma_buf; ++ } ++ } ++ ++ if (DEBUGGER_EN(MM)) { ++ rga_job_log(job, "alloc fake-buffer dump info:\n"); ++ rga_mm_dump_buffer(buffer); ++ } ++ ++ return 0; ++ ++error_free_dma_buf: ++ rga_dma_free(dma_buf); ++ ++error_free_buffer: ++ kfree(buffer); ++ ++ return ret; ++} ++ ++static void rga_mm_free_fake_buffer(struct rga_job *job) ++{ ++ if (job->src_buffer.addr) ++ rga_mm_free_channel_fake_buffer(job, &job->src_buffer, DMA_NONE); ++ if (job->dst_buffer.addr) ++ rga_mm_free_channel_fake_buffer(job, &job->dst_buffer, DMA_FROM_DEVICE); ++ if (job->src1_buffer.addr) ++ rga_mm_free_channel_fake_buffer(job, &job->src1_buffer, DMA_NONE); ++ if (job->els_buffer.addr) ++ rga_mm_free_channel_fake_buffer(job, &job->els_buffer, DMA_NONE); ++} ++ ++static int rga_mm_alloc_fake_buffer(struct rga_job *job) ++{ ++ int ret = 0; ++ struct rga_req *req = NULL; ++ enum dma_data_direction dir; ++ ++ req = &job->rga_command_base; ++ ++ if (req->src.yrgb_addr != 0 || req->src.uv_addr != 0) { ++ ret = rga_mm_alloc_channel_fake_buffer(job, &req->src, ++ &job->src_buffer, DMA_TO_DEVICE); ++ if (ret < 0) { ++ rga_job_err(job, "%s src channel map job buffer failed!", __func__); ++ goto error_free_fake_buffer; ++ } ++ } ++ ++ if (req->dst.yrgb_addr != 0 || req->dst.uv_addr != 0) { ++ ret = rga_mm_alloc_channel_fake_buffer(job, &req->dst, ++ &job->dst_buffer, DMA_TO_DEVICE); ++ if (ret < 0) { ++ rga_job_err(job, "%s dst channel map job buffer failed!", __func__); ++ goto error_free_fake_buffer; ++ } ++ } ++ ++ if (job->rga_command_base.render_mode != UPDATE_PALETTE_TABLE_MODE && ++ (req->pat.yrgb_addr != 0 || req->pat.uv_addr != 0)) { ++ if (req->bsfilter_flag) ++ dir = DMA_BIDIRECTIONAL; ++ else ++ dir = DMA_TO_DEVICE; ++ ++ ret = rga_mm_alloc_channel_fake_buffer(job, &req->pat, ++ &job->src1_buffer, dir); ++ if (ret < 0) { ++ rga_job_err(job, "%s src1 channel map job buffer failed!", __func__); ++ goto error_free_fake_buffer; ++ } ++ } else if (req->pat.yrgb_addr != 0 || req->pat.uv_addr != 0) { ++ ret = rga_mm_alloc_channel_fake_buffer(job, &req->pat, ++ &job->els_buffer, DMA_TO_DEVICE); ++ if (ret < 0) { ++ rga_job_err(job, "%s els channel map job buffer failed!", __func__); ++ goto error_free_fake_buffer; ++ } ++ } ++ ++ rga_mm_set_mmu_flag(job); ++ ++ return 0; ++ ++error_free_fake_buffer: ++ rga_mm_free_fake_buffer(job); ++ ++ return ret; ++} ++ +int rga_mm_map_job_info(struct rga_job *job) +{ + int ret; + ktime_t timestamp = ktime_get(); + ++ if (job->flags & RGA_JOB_DEBUG_FAKE_BUFFER) { ++ ret = rga_mm_alloc_fake_buffer(job); ++ if (ret < 0) ++ return ret; ++ ++ if (DEBUGGER_EN(TIME)) ++ rga_job_log(job, "alloc fake buffer cost %lld us\n", ++ ktime_us_delta(ktime_get(), timestamp)); ++ ++ job->flags &= ~RGA_JOB_USE_HANDLE; ++ job->flags |= RGA_JOB_DEBUG_FAKE_BUFFER; ++ ++ return 0; ++ } ++ + if (job->flags & RGA_JOB_USE_HANDLE) { + ret = rga_mm_get_handle_info(job); + if (ret < 0) { -+ pr_err("failed to get buffer from handle\n"); ++ rga_job_err(job, "failed to get buffer from handle\n"); + return ret; + } + + if (DEBUGGER_EN(TIME)) -+ pr_info("request[%d], get buffer_handle info cost %lld us\n", -+ job->request_id, ktime_us_delta(ktime_get(), timestamp)); ++ rga_job_log(job, "get buffer_handle info cost %lld us\n", ++ ktime_us_delta(ktime_get(), timestamp)); + } else { + ret = rga_mm_map_buffer_info(job); + if (ret < 0) { -+ pr_err("failed to map buffer\n"); ++ rga_job_err(job, "failed to map buffer\n"); + return ret; + } + + if (DEBUGGER_EN(TIME)) -+ pr_info("request[%d], map buffer cost %lld us\n", -+ job->request_id, ktime_us_delta(ktime_get(), timestamp)); ++ rga_job_log(job, "map buffer cost %lld us\n", ++ ktime_us_delta(ktime_get(), timestamp)); + } + + return 0; @@ -1911039,18 +1912966,28 @@ index 000000000..de7e9a6fd +{ + ktime_t timestamp = ktime_get(); + ++ if (job->flags & RGA_JOB_DEBUG_FAKE_BUFFER) { ++ rga_mm_free_fake_buffer(job); ++ ++ if (DEBUGGER_EN(TIME)) ++ rga_job_log(job, "free fake buffer cost %lld us\n", ++ ktime_us_delta(ktime_get(), timestamp)); ++ ++ return; ++ } ++ + if (job->flags & RGA_JOB_USE_HANDLE) { + rga_mm_put_handle_info(job); + + if (DEBUGGER_EN(TIME)) -+ pr_info("request[%d], put buffer_handle info cost %lld us\n", -+ job->request_id, ktime_us_delta(ktime_get(), timestamp)); ++ rga_job_log(job, "put buffer_handle info cost %lld us\n", ++ ktime_us_delta(ktime_get(), timestamp)); + } else { + rga_mm_unmap_buffer_info(job); + + if (DEBUGGER_EN(TIME)) -+ pr_info("request[%d], unmap buffer cost %lld us\n", -+ job->request_id, ktime_us_delta(ktime_get(), timestamp)); ++ rga_job_log(job, "unmap buffer cost %lld us\n", ++ ktime_us_delta(ktime_get(), timestamp)); + } +} + @@ -1911070,10 +1913007,11 @@ index 000000000..de7e9a6fd + int ret = 0, new_id; + struct rga_mm *mm; + struct rga_internal_buffer *internal_buffer; ++ ktime_t timestamp = ktime_get(); + + mm = rga_drvdata->mm; + if (mm == NULL) { -+ pr_err("rga mm is null!\n"); ++ rga_err("rga mm is null!\n"); + return -EFAULT; + } + @@ -1911087,17 +1913025,19 @@ index 000000000..de7e9a6fd + mutex_unlock(&mm->lock); + + if (DEBUGGER_EN(MM)) { -+ pr_info("import existing buffer:\n"); ++ rga_buf_log(internal_buffer, "import existing buffer:\n"); + rga_mm_dump_buffer(internal_buffer); + } + + return internal_buffer->handle; + } + ++ mutex_unlock(&mm->lock); ++ + /* finally, map and cached external_buffer in rga_mm */ + internal_buffer = kzalloc(sizeof(struct rga_internal_buffer), GFP_KERNEL); + if (internal_buffer == NULL) { -+ pr_err("%s alloc internal_buffer error!\n", __func__); ++ rga_err("%s alloc internal_buffer error!\n", __func__); + + mutex_unlock(&mm->lock); + return -ENOMEM; @@ -1911110,6 +1913050,7 @@ index 000000000..de7e9a6fd + kref_init(&internal_buffer->refcount); + internal_buffer->session = session; + ++ mutex_lock(&mm->lock); + /* + * Get the user-visible handle using idr. Preload and perform + * allocation under our spinlock. @@ -1911118,8 +1913059,10 @@ index 000000000..de7e9a6fd + new_id = idr_alloc_cyclic(&mm->memory_idr, internal_buffer, 1, 0, GFP_NOWAIT); + idr_preload_end(); + if (new_id < 0) { -+ pr_err("internal_buffer alloc id failed!\n"); ++ rga_err("internal_buffer alloc id failed!\n"); + ret = new_id; ++ ++ mutex_unlock(&mm->lock); + goto FREE_INTERNAL_BUFFER; + } + @@ -1911127,15 +1913070,19 @@ index 000000000..de7e9a6fd + mm->buffer_count++; + + if (DEBUGGER_EN(MM)) { -+ pr_info("import buffer:\n"); ++ rga_buf_log(internal_buffer, "import buffer:\n"); + rga_mm_dump_buffer(internal_buffer); + } + + mutex_unlock(&mm->lock); ++ ++ if (DEBUGGER_EN(TIME)) ++ rga_buf_log(internal_buffer, "import buffer cost %lld us\n", ++ ktime_us_delta(ktime_get(), timestamp)); ++ + return internal_buffer->handle; + +FREE_INTERNAL_BUFFER: -+ mutex_unlock(&mm->lock); + kfree(internal_buffer); + + return ret; @@ -1911145,10 +1913092,11 @@ index 000000000..de7e9a6fd +{ + struct rga_mm *mm; + struct rga_internal_buffer *internal_buffer; ++ ktime_t timestamp = ktime_get(); + + mm = rga_drvdata->mm; + if (mm == NULL) { -+ pr_err("rga mm is null!\n"); ++ rga_err("rga mm is null!\n"); + return -EFAULT; + } + @@ -1911157,20 +1913105,25 @@ index 000000000..de7e9a6fd + /* Find the buffer that has been imported */ + internal_buffer = rga_mm_lookup_handle(mm, handle); + if (IS_ERR_OR_NULL(internal_buffer)) { -+ pr_err("This is not a buffer that has been imported, handle = %d\n", (int)handle); ++ rga_err("This is not a buffer that has been imported, handle = %d\n", (int)handle); + + mutex_unlock(&mm->lock); + return -ENOENT; + } + + if (DEBUGGER_EN(MM)) { -+ pr_info("release buffer:\n"); ++ rga_buf_log(internal_buffer, "release buffer:\n"); + rga_mm_dump_buffer(internal_buffer); + } + + kref_put(&internal_buffer->refcount, rga_mm_kref_release_buffer); + ++ if (DEBUGGER_EN(TIME)) ++ rga_log("handle[%d]: release buffer cost %lld us\n", ++ handle, ktime_us_delta(ktime_get(), timestamp)); ++ + mutex_unlock(&mm->lock); ++ + return 0; +} + @@ -1911182,7 +1913135,7 @@ index 000000000..de7e9a6fd + + mm = rga_drvdata->mm; + if (mm == NULL) { -+ pr_err("rga mm is null!\n"); ++ rga_err("rga mm is null!\n"); + return -EFAULT; + } + @@ -1911190,9 +1913143,9 @@ index 000000000..de7e9a6fd + + idr_for_each_entry(&mm->memory_idr, buffer, i) { + if (session == buffer->session) { -+ pr_err("[tgid:%d] Destroy handle[%d] when the user exits\n", ++ rga_err("[tgid:%d] Destroy handle[%d] when the user exits\n", + session->tgid, buffer->handle); -+ rga_mm_buffer_destroy(buffer); ++ rga_mm_force_releaser_buffer(buffer); + } + } + @@ -1911224,7 +1913177,7 @@ index 000000000..de7e9a6fd + + mutex_lock(&mm->lock); + -+ idr_for_each(&mm->memory_idr, &rga_mm_handle_remove, mm); ++ idr_for_each(&mm->memory_idr, &rga_mm_buffer_destroy_for_idr, mm); + idr_destroy(&mm->memory_idr); + + mutex_unlock(&mm->lock); @@ -1911236,10 +1913189,10 @@ index 000000000..de7e9a6fd +} diff --git a/drivers/video/rockchip/rga3/rga_policy.c b/drivers/video/rockchip/rga3/rga_policy.c new file mode 100644 -index 000000000..c87ce1881 +index 000000000..2554f4bf6 --- /dev/null +++ b/drivers/video/rockchip/rga3/rga_policy.c -@@ -0,0 +1,426 @@ +@@ -0,0 +1,512 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Rockchip Electronics Co., Ltd. @@ -1911247,8 +1913200,6 @@ index 000000000..c87ce1881 + * Author: Huang Lee + */ + -+#define pr_fmt(fmt) "rga_policy: " fmt -+ +#include "rga_job.h" +#include "rga_common.h" +#include "rga_hw_config.h" @@ -1911288,50 +1913239,52 @@ index 000000000..c87ce1881 + return feature; +} + -+static bool rga_check_csc_constant(const struct rga_hw_data *data, struct rga_req *rga_base, -+ uint32_t mode, uint32_t flag) ++static bool rga_check_csc(const struct rga_hw_data *data, struct rga_req *rga_base) +{ -+ if (mode & flag) -+ return true; ++ switch (rga_base->yuv2rgb_mode & RGA_Y2R_MASK) { ++ case RGA_Y2R_BT601_LIMIT: ++ if (!(data->csc_y2r_mode & RGA_MODE_CSC_BT601L)) ++ return false; + -+ if ((rga_base->full_csc.flag & 0x1) && (data->feature & RGA_FULL_CSC)) -+ return true; ++ break; ++ case RGA_Y2R_BT601_FULL: ++ if (!(data->csc_y2r_mode & RGA_MODE_CSC_BT601F)) ++ return false; + -+ return false; -+} ++ break; ++ case RGA_Y2R_BT709_LIMIT: ++ if (!(data->csc_y2r_mode & RGA_MODE_CSC_BT709)) ++ return false; + -+static bool rga_check_csc(const struct rga_hw_data *data, struct rga_req *rga_base) -+{ -+ switch (rga_base->yuv2rgb_mode) { -+ case 0x1: -+ return rga_check_csc_constant(data, rga_base, -+ data->csc_y2r_mode, RGA_MODE_CSC_BT601L); -+ case 0x2: -+ return rga_check_csc_constant(data, rga_base, -+ data->csc_y2r_mode, RGA_MODE_CSC_BT601F); -+ case 0x3: -+ return rga_check_csc_constant(data, rga_base, -+ data->csc_y2r_mode, RGA_MODE_CSC_BT709); -+ case 0x1 << 2: -+ return rga_check_csc_constant(data, rga_base, -+ data->csc_r2y_mode, RGA_MODE_CSC_BT601F); -+ case 0x2 << 2: -+ return rga_check_csc_constant(data, rga_base, -+ data->csc_r2y_mode, RGA_MODE_CSC_BT601L); -+ case 0x3 << 2: -+ return rga_check_csc_constant(data, rga_base, -+ data->csc_r2y_mode, RGA_MODE_CSC_BT709); ++ break; + default: + break; + } + -+ if ((rga_base->full_csc.flag & 0x1)) { -+ if (data->feature & RGA_FULL_CSC) -+ return true; -+ else ++ switch (rga_base->yuv2rgb_mode & RGA_R2Y_MASK) { ++ case RGA_R2Y_BT601_LIMIT: ++ if (!(data->csc_r2y_mode & RGA_MODE_CSC_BT601L)) ++ return false; ++ ++ break; ++ case RGA_R2Y_BT601_FULL: ++ if (!(data->csc_r2y_mode & RGA_MODE_CSC_BT601F)) ++ return false; ++ ++ break; ++ case RGA_R2Y_BT709_LIMIT: ++ if (!(data->csc_r2y_mode & RGA_MODE_CSC_BT709)) + return false; ++ ++ break; ++ default: ++ break; + } + ++ ++ if ((rga_base->full_csc.flag & 0x1) && !(data->feature & RGA_FULL_CSC)) ++ return false; ++ + return true; +} + @@ -1911366,6 +1913319,18 @@ index 000000000..c87ce1881 + formats = data->win[win_num].formats[RGA_TILE8x8_INDEX]; + format_count = data->win[win_num].formats_count[RGA_TILE8x8_INDEX]; + break; ++ case RGA_TILE4x4_MODE: ++ formats = data->win[win_num].formats[RGA_TILE4x4_INDEX]; ++ format_count = data->win[win_num].formats_count[RGA_TILE4x4_INDEX]; ++ break; ++ case RGA_RKFBC_MODE: ++ formats = data->win[win_num].formats[RGA_RKFBC64x4_INDEX]; ++ format_count = data->win[win_num].formats_count[RGA_RKFBC64x4_INDEX]; ++ break; ++ case RGA_AFBC32x8_MODE: ++ formats = data->win[win_num].formats[RGA_AFBC32x8_INDEX]; ++ format_count = data->win[win_num].formats_count[RGA_AFBC32x8_INDEX]; ++ break; + default: + return false; + } @@ -1911380,7 +1913345,8 @@ index 000000000..c87ce1881 + return false; +} + -+static bool rga_check_align(uint32_t byte_stride_align, uint32_t format, uint16_t w_stride) ++static bool rga_check_align(struct rga_job *job, ++ uint32_t byte_stride_align, uint32_t format, uint16_t w_stride) +{ + int bit_stride, pixel_stride, align, gcd; + @@ -1911396,78 +1913362,77 @@ index 000000000..c87ce1881 + if (DEBUGGER_EN(MSG)) { + gcd = GET_GCD(pixel_stride, byte_stride_align * 8); + align = GET_LCM(pixel_stride, byte_stride_align * 8, gcd) / pixel_stride; -+ pr_info("unsupported width stride %d, 0x%x should be %d aligned!", ++ rga_job_log(job, "unsupported width stride %d, 0x%x should be %d aligned!", + w_stride, format, align); + } + + return false; +} + -+static bool rga_check_src0(const struct rga_hw_data *data, -+ struct rga_img_info_t *src0) ++static bool rga_check_channel(struct rga_job *job, const struct rga_hw_data *data, ++ struct rga_img_info_t *img, ++ const char *name, int input, int swap, int win_num) +{ -+ if (!rga_check_resolution(&data->input_range, src0->act_w, src0->act_h)) -+ return false; -+ -+ if (data == &rga3_data && -+ !rga_check_resolution(&data->input_range, -+ src0->act_w + src0->x_offset, -+ src0->act_h + src0->y_offset)) -+ return false; ++ int w, h; ++ const struct rga_rect_range *range; + -+ if (!rga_check_format(data, src0->rd_mode, src0->format, 0)) -+ return false; ++ if (input) ++ range = &data->input_range; ++ else ++ range = &data->output_range; + -+ if (!rga_check_align(data->byte_stride_align, src0->format, src0->vir_w)) -+ return false; ++ if (swap) { ++ w = img->act_h; ++ h = img->act_w; ++ } else { ++ w = img->act_w; ++ h = img->act_h; ++ } + -+ return true; -+} ++ if (!rga_check_resolution(range, w, h)) { ++ if (DEBUGGER_EN(MSG)) ++ rga_job_log(job, "%s resolution check error, input range[%dx%d ~ %dx%d], [w,h] = [%d, %d]\n", ++ name, ++ data->input_range.min.width, data->input_range.min.height, ++ data->input_range.max.width, data->input_range.max.height, ++ w, h); + -+static bool rga_check_src1(const struct rga_hw_data *data, -+ struct rga_img_info_t *src1) -+{ -+ if (!rga_check_resolution(&data->input_range, src1->act_w, src1->act_h)) + return false; ++ } + + if (data == &rga3_data && + !rga_check_resolution(&data->input_range, -+ src1->act_w + src1->x_offset, -+ src1->act_h + src1->y_offset)) -+ return false; -+ -+ if (!rga_check_format(data, src1->rd_mode, src1->format, 1)) -+ return false; -+ -+ if (!rga_check_align(data->byte_stride_align, src1->format, src1->vir_w)) -+ return false; -+ -+ return true; -+} -+ -+static bool rga_check_dst(const struct rga_hw_data *data, -+ struct rga_img_info_t *dst) -+{ -+ if (!rga_check_resolution(&data->output_range, dst->act_w, dst->act_h)) -+ return false; -+ -+ if (data == &rga3_data && -+ !rga_check_resolution(&data->output_range, -+ dst->act_w + dst->x_offset, -+ dst->act_h + dst->y_offset)) ++ w + img->x_offset, ++ h + img->y_offset)) { ++ if (DEBUGGER_EN(MSG)) ++ rga_job_log(job, "%s RGA3 resolution check error, input range[%dx%d ~ %dx%d], [w+x,h+y] = [%d, %d]\n", ++ name, ++ data->input_range.min.width, data->input_range.min.height, ++ data->input_range.max.width, data->input_range.max.height, ++ w + img->x_offset, ++ h + img->y_offset); + return false; ++ } + -+ if (!rga_check_format(data, dst->rd_mode, dst->format, 2)) ++ if (!rga_check_format(data, img->rd_mode, img->format, win_num)) { ++ if (DEBUGGER_EN(MSG)) ++ rga_job_log(job, "%s format check error, mode = %#x, format = %#x\n", ++ name, img->rd_mode, img->format); + return false; ++ } + -+ if (!rga_check_align(data->byte_stride_align, dst->format, dst->vir_w)) ++ if (!rga_check_align(job, data->byte_stride_align, img->format, img->vir_w)) { ++ if (DEBUGGER_EN(MSG)) ++ rga_job_log(job, "%s align check error, byte_stride_align[%d], format[%#x], vir_w[%d]\n", ++ name, data->byte_stride_align, img->format, img->vir_w); + return false; ++ } + + return true; +} + -+static bool rga_check_scale(const struct rga_hw_data *data, -+ struct rga_req *rga_base) ++static bool rga_check_scale(struct rga_job *job, 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; @@ -1911477,30 +1913442,51 @@ index 000000000..c87ce1881 + + 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; -+ } ++ dw = dst->act_w; ++ dh = dst->act_h; + + if (sw > dw) { + if ((sw >> data->max_downscale_factor) > dw) -+ return false; ++ goto check_error; + } else if (sw < dw) { + if ((sw << data->max_upscale_factor) < dw) -+ return false; ++ goto check_error; + } + + if (sh > dh) { + if ((sh >> data->max_downscale_factor) > dh) -+ return false; ++ goto check_error; + } else if (sh < dh) { + if ((sh << data->max_upscale_factor) < dh) ++ goto check_error; ++ } ++ ++ return true; ++check_error: ++ if (DEBUGGER_EN(MSG)) ++ rga_job_log(job, "scale check error, scale limit[1/%d ~ %d], src[%d, %d], dst[%d, %d]\n", ++ (1 << data->max_downscale_factor), (1 << data->max_upscale_factor), ++ sw, sh, dw, dh); ++ ++ return false; ++} ++ ++static bool rga_check_rotate(struct rga_job *job, const struct rga_hw_data *data, ++ struct rga_req *rga_base) ++{ ++ /* rot-90 and rot-270 */ ++ if (((rga_base->rotate_mode & 0x0f) == 1) && ++ ((rga_base->sina == 65536 && rga_base->cosa == 0) || ++ (rga_base->sina == -65536 && rga_base->cosa == 0))) { ++ if (data == &rga3_data && ++ (rga_is_yuv422_packed_format(rga_base->src.format) || ++ rga_is_yuv422_semi_planar_format(rga_base->src.format))) { ++ if (DEBUGGER_EN(MSG)) ++ rga_job_log(job, "rotate check error, RGA3 unsupported YUV422 rotate 90/270, format[%s(%#x)]\n", ++ rga_get_format_name(rga_base->src.format), ++ rga_base->src.format); + return false; ++ } + } + + return true; @@ -1911523,12 +1913509,13 @@ index 000000000..c87ce1881 + int i; + int min_of_job_count = -1; + unsigned long flags; ++ int need_swap = false; + + /* assigned by userspace */ + if (rga_base->core > RGA_NONE_CORE) { + if (rga_base->core > RGA_CORE_MASK) { -+ pr_err("invalid setting core by user\n"); -+ goto finish; ++ rga_job_err(job, "invalid setting core by user\n"); ++ return -1; + } else if (rga_base->core & RGA_CORE_MASK) + specified_cores = rga_base->core; + } @@ -1911545,79 +1913532,134 @@ index 000000000..c87ce1881 + continue; + + if (DEBUGGER_EN(MSG)) -+ pr_info("start policy on core = %d", scheduler->core); ++ rga_job_log(job, "start policy on %s(%#x)", ++ rga_get_core_name(scheduler->core), scheduler->core); + + if (scheduler->data->mmu == RGA_MMU && + job->flags & RGA_JOB_UNSUPPORT_RGA_MMU) { + if (DEBUGGER_EN(MSG)) -+ pr_info("RGA2 only support under 4G memory!\n"); ++ rga_job_log(job, "RGA2 only support under 4G memory!\n"); + continue; + } + + if (feature > 0) { + if (!(feature & data->feature)) { + if (DEBUGGER_EN(MSG)) -+ pr_info("core = %d, break on feature", ++ rga_job_log(job, "%s(%#x), break on feature\n", ++ rga_get_core_name(scheduler->core), + scheduler->core); + continue; + } + } + ++ /* some mode rotate 90/270 need swap dst_width/dst_height */ ++ if (((rga_base->rotate_mode & 0x0f) == 1) && ++ ((rga_base->sina == 65536 && rga_base->cosa == 0) || ++ (rga_base->sina == -65536 && rga_base->cosa == 0))) { ++ need_swap = true; ++ } ++ + /* 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 (!(src0->rd_mode & data->win[0].rd_mode)) { + if (DEBUGGER_EN(MSG)) -+ pr_info("core = %d, ABC break on rd_mode", -+ scheduler->core); ++ rga_job_log(job, "%s(%#x), src0 break on %s(%#x)\n", ++ rga_get_core_name(scheduler->core), ++ scheduler->core, ++ rga_get_store_mode_str(src0->rd_mode), ++ src0->rd_mode); ++ continue; ++ } ++ ++ if (!(src1->rd_mode & data->win[1].rd_mode)) { ++ if (DEBUGGER_EN(MSG)) ++ rga_job_log(job, "%s(%#x), src1 break on %s(%#x)\n", ++ rga_get_core_name(scheduler->core), ++ scheduler->core, ++ rga_get_store_mode_str(src1->rd_mode), ++ src1->rd_mode); ++ continue; ++ } ++ ++ if (!(dst->rd_mode & data->win[2].rd_mode)) { ++ if (DEBUGGER_EN(MSG)) ++ rga_job_log(job, "%s(%#x), dst break on %s(%#x)\n", ++ rga_get_core_name(scheduler->core), ++ scheduler->core, ++ rga_get_store_mode_str(dst->rd_mode), ++ dst->rd_mode); + continue; + } + } else { -+ if ((!(src0->rd_mode & data->win[0].rd_mode)) || -+ (!(dst->rd_mode & data->win[2].rd_mode))) { ++ if (!(src0->rd_mode & data->win[0].rd_mode)) { + if (DEBUGGER_EN(MSG)) -+ pr_info("core = %d, ABB break on rd_mode", -+ scheduler->core); ++ rga_job_log(job, "%s(%#x), src break on %s(%#x)\n", ++ rga_get_core_name(scheduler->core), ++ scheduler->core, ++ rga_get_store_mode_str(src0->rd_mode), ++ src0->rd_mode); ++ continue; ++ } ++ ++ if (!(dst->rd_mode & data->win[2].rd_mode)) { ++ if (DEBUGGER_EN(MSG)) ++ rga_job_log(job, "%s(%#x), dst break on %s(%#x)\n", ++ rga_get_core_name(scheduler->core), ++ scheduler->core, ++ rga_get_store_mode_str(dst->rd_mode), ++ dst->rd_mode); + continue; + } + } + -+ if (!rga_check_scale(data, rga_base)) { ++ if (!rga_check_scale(job, data, rga_base)) { + if (DEBUGGER_EN(MSG)) -+ pr_info("core = %d, break on rga_check_scale", ++ rga_job_log(job, "%s(%#x), break on rga_check_scale", ++ rga_get_core_name(scheduler->core), + scheduler->core); + continue; + } + -+ if (!rga_check_src0(data, src0)) { ++ if (!rga_check_channel(job, data, src0, "src0", true, false, 0)) { + if (DEBUGGER_EN(MSG)) -+ pr_info("core = %d, break on rga_check_src0", ++ rga_job_log(job, "%s(%#x), break on src0", ++ rga_get_core_name(scheduler->core), + scheduler->core); + continue; + } + + if (src1->yrgb_addr > 0) { -+ if (!rga_check_src1(data, src1)) { ++ if (!rga_check_channel(job, data, src1, "src1", true, false, 1)) { + if (DEBUGGER_EN(MSG)) -+ pr_info("core = %d, break on rga_check_src1", ++ rga_job_log(job, "%s(%#x), break on src1", ++ rga_get_core_name(scheduler->core), + scheduler->core); + continue; + } + } + } + -+ if (!rga_check_dst(data, dst)) { ++ if (!rga_check_channel(job, data, dst, "dst", false, need_swap, 2)) { + if (DEBUGGER_EN(MSG)) -+ pr_info("core = %d, break on rga_check_dst", ++ rga_job_log(job, "%s(%#x), break on dst", ++ rga_get_core_name(scheduler->core), + scheduler->core); + continue; + } + + if (!rga_check_csc(data, rga_base)) { + if (DEBUGGER_EN(MSG)) -+ pr_info("core = %d, break on rga_check_csc", ++ rga_job_log(job, "%s(%#x), break on rga_check_csc", ++ rga_get_core_name(scheduler->core), ++ scheduler->core); ++ continue; ++ } ++ ++ if (!rga_check_rotate(job, data, rga_base)) { ++ if (DEBUGGER_EN(MSG)) ++ rga_job_log(job, "%s(%#x), break on rga_check_rotate", ++ rga_get_core_name(scheduler->core), + scheduler->core); + continue; + } @@ -1911625,13 +1913667,9 @@ index 000000000..c87ce1881 + optional_cores |= scheduler->core; + } + -+ if (DEBUGGER_EN(MSG)) -+ pr_info("optional_cores = %d\n", optional_cores); -+ + if (optional_cores == 0) { -+ core = -1; -+ pr_err("invalid function policy\n"); -+ goto finish; ++ rga_job_err(job, "no core match\n"); ++ return -1; + } + + for (i = 0; i < rga_drvdata->num_of_scheduler; i++) { @@ -1911660,9 +1913698,10 @@ index 000000000..c87ce1881 + } + + /* TODO: need consider full load */ -+finish: + if (DEBUGGER_EN(MSG)) -+ pr_info("assign core: %d\n", core); ++ rga_job_log(job, "matched cores = %#x, assign core: %s(%#x)\n", ++ optional_cores, ++ rga_get_core_name(core), core); + + return core; +}