diff --git a/drivers/amlogic/media/common/ge2d/ge2d_hw.c b/drivers/amlogic/media/common/ge2d/ge2d_hw.c index 406bcbd1f6df..fff3adb41c00 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_hw.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_hw.c @@ -504,8 +504,10 @@ void ge2d_set_src2_dst_gen(struct ge2d_src2_dst_gen_s *cfg) ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->dst_pic_struct, 14, 2); } -void ge2d_set_dp_gen(struct ge2d_dp_gen_s *cfg) +void ge2d_set_dp_gen(struct ge2d_config_s *config) { + struct ge2d_dp_gen_s *cfg = &config->dp_gen; + unsigned int antiflick_color_filter_n1[] = {0, 8, 16, 32}; unsigned int antiflick_color_filter_n2[] = {128, 112, 96, 64}; unsigned int antiflick_color_filter_n3[] = {0, 8, 16, 32}; @@ -595,7 +597,6 @@ void ge2d_set_dp_gen(struct ge2d_dp_gen_s *cfg) ((cfg->antiflick_color_filter_n1[3] & 0xff) << 0) ); - ge2d_reg_write(GE2D_ANTIFLICK_ALPHA_FILT0, ((cfg->antiflick_alpha_filter_th[0] & 0xff) << 24) | ((cfg->antiflick_alpha_filter_n3[0] & 0xff) << 16) | @@ -624,107 +625,135 @@ void ge2d_set_dp_gen(struct ge2d_dp_gen_s *cfg) ); } else ge2d_reg_set_bits(GE2D_ANTIFLICK_CTRL0, 0, 31, 1); - if (cfg->use_matrix_default & MATRIX_YCC_TO_RGB) { - /* ycbcr(16-235) to rgb(0-255) */ - cfg->matrix_coef[0] = 0x4a8; - cfg->matrix_coef[1] = 0; - cfg->matrix_coef[2] = 0x662; - cfg->matrix_coef[3] = 0x4a8; - cfg->matrix_coef[4] = 0x1e6f; - cfg->matrix_coef[5] = 0x1cbf; - cfg->matrix_coef[6] = 0x4a8; - cfg->matrix_coef[7] = 0x811; - cfg->matrix_coef[8] = 0x0; - cfg->matrix_offset[0] = 0; - cfg->matrix_offset[1] = 0; - cfg->matrix_offset[2] = 0; - cfg->matrix_sat_in_en = 1; - cfg->matrix_minus_16_ctrl = 0x4; - cfg->matrix_sign_ctrl = 0x3; - } else if (cfg->use_matrix_default & MATRIX_RGB_TO_YCC) { - if (cfg->use_matrix_default & MATRIX_BT_709) { - /* VDIN_MATRIX_RGB_YUV709 */ - /* 0 0.183 0.614 0.062 16 */ - /* 0 -0.101 -0.338 0.439 128 */ - /* 0 0.439 -0.399 -0.04 128 */ - cfg->matrix_coef[0] = 0xbb; - cfg->matrix_coef[1] = 0x275; - cfg->matrix_coef[2] = 0x3f; - cfg->matrix_coef[3] = 0x1f99; - cfg->matrix_coef[4] = 0x1ea6; - cfg->matrix_coef[5] = 0x1c2; - cfg->matrix_coef[6] = 0x1c2; - cfg->matrix_coef[7] = 0x1e67; - cfg->matrix_coef[8] = 0x1fd7; - } else { - /* rgb(0-255) to ycbcr(16-235) */ - /* 0.257 0.504 0.098 */ - /* -0.148 -0.291 0.439 */ - /* 0.439 -0.368 -0.071 */ - cfg->matrix_coef[0] = 0x107; - cfg->matrix_coef[1] = 0x204; - cfg->matrix_coef[2] = 0x64; - cfg->matrix_coef[3] = 0x1f68; - cfg->matrix_coef[4] = 0x1ed6; - cfg->matrix_coef[5] = 0x1c2; - cfg->matrix_coef[6] = 0x1c2; - cfg->matrix_coef[7] = 0x1e87; - cfg->matrix_coef[8] = 0x1fb7; + + if (cfg->use_matrix_default & MATRIX_CUSTOM) { + struct ge2d_matrix_s *matrix = &config->matrix_custom; + + ge2d_log_dbg("using matrix_custom\n"); + cfg->matrix_coef[0] = matrix->coef0; + cfg->matrix_coef[1] = matrix->coef1; + cfg->matrix_coef[2] = matrix->coef2; + cfg->matrix_coef[3] = matrix->coef3; + cfg->matrix_coef[4] = matrix->coef4; + cfg->matrix_coef[5] = matrix->coef5; + cfg->matrix_coef[6] = matrix->coef6; + cfg->matrix_coef[7] = matrix->coef7; + cfg->matrix_coef[8] = matrix->coef8; + cfg->matrix_offset[0] = matrix->offset0; + cfg->matrix_offset[1] = matrix->offset1; + cfg->matrix_offset[2] = matrix->offset2; + cfg->matrix_sat_in_en = matrix->sat_in_en; + + ge2d_reg_write(GE2D_MATRIX_PRE_OFFSET, + (matrix->pre_offset0 << 20) | + (matrix->pre_offset1 << 10) | + matrix->pre_offset2); + } else { + if (cfg->use_matrix_default & MATRIX_YCC_TO_RGB) { + /* ycbcr(16-235) to rgb(0-255) */ + cfg->matrix_coef[0] = 0x4a8; + cfg->matrix_coef[1] = 0; + cfg->matrix_coef[2] = 0x662; + cfg->matrix_coef[3] = 0x4a8; + cfg->matrix_coef[4] = 0x1e6f; + cfg->matrix_coef[5] = 0x1cbf; + cfg->matrix_coef[6] = 0x4a8; + cfg->matrix_coef[7] = 0x811; + cfg->matrix_coef[8] = 0x0; + cfg->matrix_offset[0] = 0; + cfg->matrix_offset[1] = 0; + cfg->matrix_offset[2] = 0; + cfg->matrix_sat_in_en = 1; + cfg->matrix_minus_16_ctrl = 0x4; + cfg->matrix_sign_ctrl = 0x3; + } else if (cfg->use_matrix_default & MATRIX_RGB_TO_YCC) { + if (cfg->use_matrix_default & MATRIX_BT_709) { + /* VDIN_MATRIX_RGB_YUV709 */ + /* 0 0.183 0.614 0.062 16 */ + /* 0 -0.101 -0.338 0.439 128 */ + /* 0 0.439 -0.399 -0.04 128 */ + cfg->matrix_coef[0] = 0xbb; + cfg->matrix_coef[1] = 0x275; + cfg->matrix_coef[2] = 0x3f; + cfg->matrix_coef[3] = 0x1f99; + cfg->matrix_coef[4] = 0x1ea6; + cfg->matrix_coef[5] = 0x1c2; + cfg->matrix_coef[6] = 0x1c2; + cfg->matrix_coef[7] = 0x1e67; + cfg->matrix_coef[8] = 0x1fd7; + } else { + /* rgb(0-255) to ycbcr(16-235) */ + /* 0.257 0.504 0.098 */ + /* -0.148 -0.291 0.439 */ + /* 0.439 -0.368 -0.071 */ + cfg->matrix_coef[0] = 0x107; + cfg->matrix_coef[1] = 0x204; + cfg->matrix_coef[2] = 0x64; + cfg->matrix_coef[3] = 0x1f68; + cfg->matrix_coef[4] = 0x1ed6; + cfg->matrix_coef[5] = 0x1c2; + cfg->matrix_coef[6] = 0x1c2; + cfg->matrix_coef[7] = 0x1e87; + cfg->matrix_coef[8] = 0x1fb7; + } + cfg->matrix_offset[0] = 16; + cfg->matrix_offset[1] = 128; + cfg->matrix_offset[2] = 128; + cfg->matrix_sat_in_en = 0; + cfg->matrix_minus_16_ctrl = 0; + cfg->matrix_sign_ctrl = 0; + } else if (cfg->use_matrix_default & + MATRIX_FULL_RANGE_YCC_TO_RGB) { + /* ycbcr (0-255) to rgb(0-255) */ + /* 1, 0, 1.402 */ + /* 1, -0.34414, -0.71414 */ + /* 1, 1.772 0 */ + cfg->matrix_coef[0] = 0x400; + cfg->matrix_coef[1] = 0; + cfg->matrix_coef[2] = 0x59c; + cfg->matrix_coef[3] = 0x400; + cfg->matrix_coef[4] = 0x1ea0; + cfg->matrix_coef[5] = 0x1d25; + cfg->matrix_coef[6] = 0x400; + cfg->matrix_coef[7] = 0x717; + cfg->matrix_coef[8] = 0; + cfg->matrix_offset[0] = 0; + cfg->matrix_offset[1] = 0; + cfg->matrix_offset[2] = 0; + cfg->matrix_sat_in_en = 0; + cfg->matrix_minus_16_ctrl = 0; + cfg->matrix_sign_ctrl = 0x3; + } else if (cfg->use_matrix_default & + MATRIX_RGB_TO_FULL_RANGE_YCC) { + cfg->matrix_coef[0] = 0x132; + cfg->matrix_coef[1] = 0x259; + cfg->matrix_coef[2] = 0x75; + cfg->matrix_coef[3] = 0x1f53; + cfg->matrix_coef[4] = 0x1ead; + cfg->matrix_coef[5] = 0x200; + cfg->matrix_coef[6] = 0x200; + cfg->matrix_coef[7] = 0x1e53; + cfg->matrix_coef[8] = 0x1fad; + cfg->matrix_offset[0] = 0; + cfg->matrix_offset[1] = 128; + cfg->matrix_offset[2] = 128; + cfg->matrix_sat_in_en = 0; + cfg->matrix_minus_16_ctrl = 0; + cfg->matrix_sign_ctrl = 0; } - cfg->matrix_offset[0] = 16; - cfg->matrix_offset[1] = 128; - cfg->matrix_offset[2] = 128; - cfg->matrix_sat_in_en = 0; - cfg->matrix_minus_16_ctrl = 0; - cfg->matrix_sign_ctrl = 0; - } else if (cfg->use_matrix_default & MATRIX_FULL_RANGE_YCC_TO_RGB) { - /* ycbcr (0-255) to rgb(0-255) */ - /* 1, 0, 1.402 */ - /* 1, -0.34414, -0.71414 */ - /* 1, 1.772 0 */ - cfg->matrix_coef[0] = 0x400; - cfg->matrix_coef[1] = 0; - cfg->matrix_coef[2] = 0x59c; - cfg->matrix_coef[3] = 0x400; - cfg->matrix_coef[4] = 0x1ea0; - cfg->matrix_coef[5] = 0x1d25; - cfg->matrix_coef[6] = 0x400; - cfg->matrix_coef[7] = 0x717; - cfg->matrix_coef[8] = 0; - cfg->matrix_offset[0] = 0; - cfg->matrix_offset[1] = 0; - cfg->matrix_offset[2] = 0; - cfg->matrix_sat_in_en = 0; - cfg->matrix_minus_16_ctrl = 0; - cfg->matrix_sign_ctrl = 0x3; - } else if (cfg->use_matrix_default & MATRIX_RGB_TO_FULL_RANGE_YCC) { - cfg->matrix_coef[0] = 0x132; - cfg->matrix_coef[1] = 0x259; - cfg->matrix_coef[2] = 0x75; - cfg->matrix_coef[3] = 0x1f53; - cfg->matrix_coef[4] = 0x1ead; - cfg->matrix_coef[5] = 0x200; - cfg->matrix_coef[6] = 0x200; - cfg->matrix_coef[7] = 0x1e53; - cfg->matrix_coef[8] = 0x1fad; - cfg->matrix_offset[0] = 0; - cfg->matrix_offset[1] = 128; - cfg->matrix_offset[2] = 128; - cfg->matrix_sat_in_en = 0; - cfg->matrix_minus_16_ctrl = 0; - cfg->matrix_sign_ctrl = 0; + + if (cfg->matrix_minus_16_ctrl) + ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET, 0x1f0, 20, 9); + else + ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET, 0, 20, 9); + + if (cfg->matrix_sign_ctrl & 3) + ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET, + ((0x180 << 10) | 0x180), 0, 20); + else + ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET, 0, 0, 20); } - if (cfg->matrix_minus_16_ctrl) - ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET, 0x1f0, 20, 9); - else - ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET, 0, 20, 9); - - if (cfg->matrix_sign_ctrl & 3) - ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET, - ((0x180 << 10) | 0x180), 0, 20); - else - ge2d_reg_set_bits(GE2D_MATRIX_PRE_OFFSET, 0, 0, 20); ge2d_reg_write(GE2D_MATRIX_COEF00_01, (cfg->matrix_coef[0] << 16) | (cfg->matrix_coef[1] << 0) @@ -761,7 +790,6 @@ void ge2d_set_dp_gen(struct ge2d_dp_gen_s *cfg) (cfg->matrix_offset[2] << 0) ); - ge2d_reg_set_bits(GE2D_GEN_CTRL1, cfg->src1_gb_alpha, 0, 8); ge2d_reg_set_bits(GE2D_GEN_CTRL2, cfg->src1_gb_alpha_en, 29, 1); diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index f6146f838281..ec4e96cc1faf 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -437,7 +437,7 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq) ge2d_set_src2_dst_gen(&cfg->src2_dst_gen); break; case UPDATE_DP_GEN: - ge2d_set_dp_gen(&cfg->dp_gen); + ge2d_set_dp_gen(cfg); break; case UPDATE_SCALE_COEF: ge2d_set_src1_scale_coef(cfg->v_scale_coef_type, @@ -2478,6 +2478,8 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, /* context->config.src1_data.ddr_burst_size_cb = 3; */ /* context->config.src1_data.ddr_burst_size_cr = 3; */ /* context->config.src2_dst_data.ddr_burst_size= 3; */ + memcpy(&context->config.matrix_custom, &ge2d_config_mem->matrix_custom, + sizeof(struct ge2d_matrix_s)); return 0; } diff --git a/drivers/amlogic/media/common/ge2d/ge2dgen.c b/drivers/amlogic/media/common/ge2d/ge2dgen.c index c3dbbb2360b6..f6febd4e8b97 100644 --- a/drivers/amlogic/media/common/ge2d/ge2dgen.c +++ b/drivers/amlogic/media/common/ge2d/ge2dgen.c @@ -46,6 +46,13 @@ static inline void _set_src1_format(struct ge2d_src1_data_s *src1_data_cfg, else src1_data_cfg->deep_color = 0; + if ((format_src & GE2D_MATRIX_CUSTOM) || + (format_dst & GE2D_MATRIX_CUSTOM)) { + dp_gen_cfg->use_matrix_default = MATRIX_CUSTOM; + dp_gen_cfg->conv_matrix_en = 1; + return; + } + if ((format_src & GE2D_FORMAT_YUV) && ((format_dst & GE2D_FORMAT_YUV) == 0)) { dp_gen_cfg->use_matrix_default = @@ -102,24 +109,6 @@ static inline void _set_dst_format( src2_dst_data_cfg->dst_mode_8b_sel = (format_dst >> 6) & 3; src2_dst_gen_cfg->dst_pic_struct = (format_dst >> 3) & 3; - if ((format_src & GE2D_FORMAT_YUV) && - ((format_dst & GE2D_FORMAT_YUV) == 0)) { - dp_gen_cfg->use_matrix_default = - (format_src & GE2D_FORMAT_FULL_RANGE) ? - MATRIX_FULL_RANGE_YCC_TO_RGB : MATRIX_YCC_TO_RGB; - dp_gen_cfg->conv_matrix_en = 1; - } else if (((format_src & GE2D_FORMAT_YUV) == 0) && - (format_dst & GE2D_FORMAT_YUV)) { - dp_gen_cfg->use_matrix_default = - (format_dst & GE2D_FORMAT_FULL_RANGE) ? - MATRIX_RGB_TO_FULL_RANGE_YCC : MATRIX_RGB_TO_YCC; - dp_gen_cfg->use_matrix_default |= - ((format_dst & GE2D_FORMAT_BT_STANDARD) ? - MATRIX_BT_709 : MATRIX_BT_601); - dp_gen_cfg->conv_matrix_en = 1; - } else - dp_gen_cfg->conv_matrix_en = 0; - y_yc_ratio = (format_dst >> 0) & 1; /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ @@ -139,6 +128,31 @@ static inline void _set_dst_format( } else src2_dst_data_cfg->dst2_enable = 0; /* #endif */ + + if ((format_src & GE2D_MATRIX_CUSTOM) || + (format_dst & GE2D_MATRIX_CUSTOM)) { + dp_gen_cfg->use_matrix_default = MATRIX_CUSTOM; + dp_gen_cfg->conv_matrix_en = 1; + return; + } + + if ((format_src & GE2D_FORMAT_YUV) && + ((format_dst & GE2D_FORMAT_YUV) == 0)) { + dp_gen_cfg->use_matrix_default = + (format_src & GE2D_FORMAT_FULL_RANGE) ? + MATRIX_FULL_RANGE_YCC_TO_RGB : MATRIX_YCC_TO_RGB; + dp_gen_cfg->conv_matrix_en = 1; + } else if (((format_src & GE2D_FORMAT_YUV) == 0) && + (format_dst & GE2D_FORMAT_YUV)) { + dp_gen_cfg->use_matrix_default = + (format_dst & GE2D_FORMAT_FULL_RANGE) ? + MATRIX_RGB_TO_FULL_RANGE_YCC : MATRIX_RGB_TO_YCC; + dp_gen_cfg->use_matrix_default |= + ((format_dst & GE2D_FORMAT_BT_STANDARD) ? + MATRIX_BT_709 : MATRIX_BT_601); + dp_gen_cfg->conv_matrix_en = 1; + } else + dp_gen_cfg->conv_matrix_en = 0; } void ge2dgen_src(struct ge2d_context_s *wq, diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index 3ba1a52358eb..9e704d275ef9 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -135,11 +135,12 @@ enum ge2d_memtype_s { #define MATRIX_BT_STANDARD (1 << 4) #define MATRIX_BT_601 (0 << 4) #define MATRIX_BT_709 (1 << 4) +#define MATRIX_CUSTOM BIT(5) #define GE2D_FORMAT_BT_STANDARD (1 << 28) #define GE2D_FORMAT_BT601 (0 << 28) #define GE2D_FORMAT_BT709 (1 << 28) - +#define GE2D_MATRIX_CUSTOM BIT(29) #define GE2D_ENDIAN_SHIFT 24 #define GE2D_ENDIAN_MASK (0x1 << GE2D_ENDIAN_SHIFT) @@ -641,6 +642,26 @@ struct ge2d_dma_cfg_s { void *dma_cfg; }; +struct ge2d_matrix_s { + unsigned int pre_offset0; + unsigned int pre_offset1; + unsigned int pre_offset2; + unsigned int coef0; + unsigned int coef1; + unsigned int coef2; + unsigned int coef3; + unsigned int coef4; + unsigned int coef5; + unsigned int coef6; + unsigned int coef7; + unsigned int coef8; + unsigned int offset0; + unsigned int offset1; + unsigned int offset2; + /* input y/cb/cr saturation enable */ + unsigned char sat_in_en; +}; + struct ge2d_config_s { struct ge2d_gen_s gen; struct ge2d_src1_data_s src1_data; @@ -657,6 +678,7 @@ struct ge2d_config_s { struct ge2d_dma_cfg_s src_dma_cfg[MAX_PLANE]; struct ge2d_dma_cfg_s src2_dma_cfg[MAX_PLANE]; struct ge2d_dma_cfg_s dst_dma_cfg[MAX_PLANE]; + struct ge2d_matrix_s matrix_custom; }; struct ge2d_dma_buf_s { @@ -1019,10 +1041,12 @@ struct compat_config_para_ex_ion_s { struct config_para_ex_memtype_s { int ge2d_magic; struct config_para_ex_ion_s _ge2d_config_ex; - /* memtype*/ + /* memtype */ unsigned int src1_mem_alloc_type; unsigned int src2_mem_alloc_type; unsigned int dst_mem_alloc_type; + /* for customized matrix */ + struct ge2d_matrix_s matrix_custom; }; struct config_ge2d_para_ex_s { @@ -1041,6 +1065,8 @@ struct compat_config_para_ex_memtype_s { unsigned int src1_mem_alloc_type; unsigned int src2_mem_alloc_type; unsigned int dst_mem_alloc_type; + /* for customized matrix */ + struct ge2d_matrix_s matrix_custom; }; struct compat_config_ge2d_para_ex_s { @@ -1152,7 +1178,7 @@ extern void ge2d_set_src1_data(struct ge2d_src1_data_s *cfg); extern void ge2d_set_src1_gen(struct ge2d_src1_gen_s *cfg); extern void ge2d_set_src2_dst_data(struct ge2d_src2_dst_data_s *cfg); extern void ge2d_set_src2_dst_gen(struct ge2d_src2_dst_gen_s *cfg); -extern void ge2d_set_dp_gen(struct ge2d_dp_gen_s *cfg); +void ge2d_set_dp_gen(struct ge2d_config_s *config); extern void ge2d_set_cmd(struct ge2d_cmd_s *cfg); extern void ge2d_wait_done(void); extern void ge2d_set_src1_scale_coef(unsigned int v_filt_type,