mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
drm/rockchip: vop2: Support post csc color range convert
Choose post csc mode directly by the color format and color range of csc input/output. Change-Id: Ib809e5898fd8a0178758e50ae9b8dfc4b8b63335 Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
This commit is contained in:
@@ -611,6 +611,14 @@ enum vop_hdr_format {
|
|||||||
HDR_FORMAT_MAX,
|
HDR_FORMAT_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct post_csc_convert_mode {
|
||||||
|
enum drm_color_encoding color_encoding;
|
||||||
|
bool is_input_yuv;
|
||||||
|
bool is_output_yuv;
|
||||||
|
bool is_input_full_range;
|
||||||
|
bool is_output_full_range;
|
||||||
|
};
|
||||||
|
|
||||||
struct post_csc_coef {
|
struct post_csc_coef {
|
||||||
s32 csc_coef00;
|
s32 csc_coef00;
|
||||||
s32 csc_coef01;
|
s32 csc_coef01;
|
||||||
|
|||||||
@@ -619,6 +619,12 @@ struct vop2_video_port {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool skip_vsync;
|
bool skip_vsync;
|
||||||
|
/**
|
||||||
|
* @has_dci_enabled_win: Indicate dci enables on this vp.
|
||||||
|
* post csc input will be full range yuv.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool has_dci_enabled_win;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @bg_ovl_dly: The timing delay from background layer
|
* @bg_ovl_dly: The timing delay from background layer
|
||||||
@@ -5300,6 +5306,13 @@ static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_st
|
|||||||
}
|
}
|
||||||
vpstate->mst_end = rk_obj->dma_addr + rk_obj->size;
|
vpstate->mst_end = rk_obj->dma_addr + rk_obj->size;
|
||||||
|
|
||||||
|
if (win->feature & WIN_FEATURE_DCI) {
|
||||||
|
if (vpstate->dci_data)
|
||||||
|
vp->has_dci_enabled_win = true;
|
||||||
|
else
|
||||||
|
vp->has_dci_enabled_win = false;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10615,14 +10628,27 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st
|
|||||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||||
struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
|
struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
|
||||||
struct vop2 *vop2 = vp->vop2;
|
struct vop2 *vop2 = vp->vop2;
|
||||||
|
struct drm_plane *plane;
|
||||||
|
struct drm_plane_state *pstate;
|
||||||
struct post_csc_coef csc_coef;
|
struct post_csc_coef csc_coef;
|
||||||
|
struct post_csc_convert_mode convert_mode;
|
||||||
bool acm_enable;
|
bool acm_enable;
|
||||||
bool is_input_yuv = false;
|
|
||||||
bool is_output_yuv = false;
|
|
||||||
bool post_r2y_en = false;
|
bool post_r2y_en = false;
|
||||||
bool post_csc_en = false;
|
bool post_csc_en = false;
|
||||||
|
bool has_yuv_plane = false;
|
||||||
int range_type;
|
int range_type;
|
||||||
|
|
||||||
|
drm_atomic_crtc_for_each_plane(plane, crtc) {
|
||||||
|
struct vop2_win *win = to_vop2_win(plane);
|
||||||
|
|
||||||
|
pstate = win->base.state;
|
||||||
|
|
||||||
|
if (pstate->fb->format->is_yuv) {
|
||||||
|
has_yuv_plane = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!acm)
|
if (!acm)
|
||||||
acm_enable = false;
|
acm_enable = false;
|
||||||
else
|
else
|
||||||
@@ -10648,16 +10674,31 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st
|
|||||||
post_csc_en = true;
|
post_csc_en = true;
|
||||||
|
|
||||||
if (vcstate->yuv_overlay || post_r2y_en)
|
if (vcstate->yuv_overlay || post_r2y_en)
|
||||||
is_input_yuv = true;
|
convert_mode.is_input_yuv = true;
|
||||||
|
|
||||||
if (is_yuv_output(vcstate->bus_format))
|
if (is_yuv_output(vcstate->bus_format))
|
||||||
is_output_yuv = true;
|
convert_mode.is_output_yuv = true;
|
||||||
|
|
||||||
|
if (vp->has_dci_enabled_win)
|
||||||
|
convert_mode.is_input_full_range = true;
|
||||||
|
else if (has_yuv_plane)
|
||||||
|
convert_mode.is_input_full_range =
|
||||||
|
pstate->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
|
||||||
|
else
|
||||||
|
convert_mode.is_input_full_range =
|
||||||
|
vcstate->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
|
||||||
|
|
||||||
|
convert_mode.is_output_full_range =
|
||||||
|
vcstate->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
|
||||||
|
|
||||||
vcstate->post_csc_mode = vop2_convert_csc_mode(vcstate->color_encoding, vcstate->color_range, CSC_13BIT_DEPTH);
|
vcstate->post_csc_mode = vop2_convert_csc_mode(vcstate->color_encoding, vcstate->color_range, CSC_13BIT_DEPTH);
|
||||||
|
|
||||||
if (post_csc_en) {
|
if (post_csc_en) {
|
||||||
rockchip_calc_post_csc(csc, &csc_coef, vcstate->post_csc_mode, is_input_yuv,
|
if (has_yuv_plane)
|
||||||
is_output_yuv);
|
convert_mode.color_encoding = pstate->color_encoding;
|
||||||
|
else
|
||||||
|
convert_mode.color_encoding = vcstate->color_encoding;
|
||||||
|
rockchip_calc_post_csc(csc, &csc_coef, &convert_mode);
|
||||||
|
|
||||||
VOP_MODULE_SET(vop2, vp, csc_coe00, csc_coef.csc_coef00);
|
VOP_MODULE_SET(vop2, vp, csc_coe00, csc_coef.csc_coef00);
|
||||||
VOP_MODULE_SET(vop2, vp, csc_coe01, csc_coef.csc_coef01);
|
VOP_MODULE_SET(vop2, vp, csc_coe01, csc_coef.csc_coef01);
|
||||||
@@ -10673,7 +10714,7 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st
|
|||||||
VOP_MODULE_SET(vop2, vp, csc_offset2, csc_coef.csc_dc2);
|
VOP_MODULE_SET(vop2, vp, csc_offset2, csc_coef.csc_dc2);
|
||||||
|
|
||||||
range_type = csc_coef.range_type ? 0 : 1;
|
range_type = csc_coef.range_type ? 0 : 1;
|
||||||
range_type <<= is_input_yuv ? 0 : 1;
|
range_type <<= convert_mode.is_input_yuv ? 0 : 1;
|
||||||
VOP_MODULE_SET(vop2, vp, csc_mode, range_type);
|
VOP_MODULE_SET(vop2, vp, csc_mode, range_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -986,73 +986,6 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct csc_mapping {
|
|
||||||
enum vop_csc_format csc_format;
|
|
||||||
enum color_space_type rgb_color_space;
|
|
||||||
enum color_space_type yuv_color_space;
|
|
||||||
bool rgb_full_range;
|
|
||||||
bool yuv_full_range;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct csc_mapping csc_mapping_table[] = {
|
|
||||||
{
|
|
||||||
CSC_BT601L,
|
|
||||||
OPTM_CS_E_RGB,
|
|
||||||
OPTM_CS_E_XV_YCC_601,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CSC_BT709L,
|
|
||||||
OPTM_CS_E_RGB,
|
|
||||||
OPTM_CS_E_XV_YCC_709,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CSC_BT601F,
|
|
||||||
OPTM_CS_E_RGB,
|
|
||||||
OPTM_CS_E_XV_YCC_601,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CSC_BT2020L,
|
|
||||||
OPTM_CS_E_RGB_2020,
|
|
||||||
OPTM_CS_E_XV_YCC_2020,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CSC_BT709L_13BIT,
|
|
||||||
OPTM_CS_E_RGB,
|
|
||||||
OPTM_CS_E_XV_YCC_709,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CSC_BT709F_13BIT,
|
|
||||||
OPTM_CS_E_RGB,
|
|
||||||
OPTM_CS_E_XV_YCC_709,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CSC_BT2020L_13BIT,
|
|
||||||
OPTM_CS_E_RGB_2020,
|
|
||||||
OPTM_CS_E_XV_YCC_2020,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CSC_BT2020F_13BIT,
|
|
||||||
OPTM_CS_E_RGB_2020,
|
|
||||||
OPTM_CS_E_XV_YCC_2020,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct rk_pq_csc_coef r2y_for_y2y = {
|
static const struct rk_pq_csc_coef r2y_for_y2y = {
|
||||||
306, 601, 117,
|
306, 601, 117,
|
||||||
-151, -296, 446,
|
-151, -296, 446,
|
||||||
@@ -1077,30 +1010,50 @@ static const struct rk_pq_csc_coef yuv_output_swap_matrix = {
|
|||||||
0, 1, 0,
|
0, 1, 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int csc_get_mode_index(int post_csc_mode, bool is_input_yuv, bool is_output_yuv)
|
static
|
||||||
|
enum color_space_type get_color_space_type(enum drm_color_encoding color_encoding, bool is_yuv)
|
||||||
|
{
|
||||||
|
enum color_space_type color_space_type;
|
||||||
|
|
||||||
|
switch (color_encoding) {
|
||||||
|
case DRM_COLOR_YCBCR_BT601:
|
||||||
|
if (is_yuv)
|
||||||
|
color_space_type = OPTM_CS_E_XV_YCC_601;
|
||||||
|
else
|
||||||
|
color_space_type = OPTM_CS_E_RGB;
|
||||||
|
break;
|
||||||
|
case DRM_COLOR_YCBCR_BT709:
|
||||||
|
if (is_yuv)
|
||||||
|
color_space_type = OPTM_CS_E_XV_YCC_709;
|
||||||
|
else
|
||||||
|
color_space_type = OPTM_CS_E_RGB;
|
||||||
|
break;
|
||||||
|
case DRM_COLOR_YCBCR_BT2020:
|
||||||
|
if (is_yuv)
|
||||||
|
color_space_type = OPTM_CS_E_XV_YCC_2020;
|
||||||
|
else
|
||||||
|
color_space_type = OPTM_CS_E_RGB_2020;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (is_yuv)
|
||||||
|
color_space_type = OPTM_CS_E_XV_YCC_601;
|
||||||
|
else
|
||||||
|
color_space_type = OPTM_CS_E_RGB_2020;
|
||||||
|
}
|
||||||
|
|
||||||
|
return color_space_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int csc_get_mode_index(bool is_input_full_range, bool is_output_full_range,
|
||||||
|
bool is_input_yuv, bool is_output_yuv,
|
||||||
|
enum drm_color_encoding color_encoding)
|
||||||
{
|
{
|
||||||
const struct rk_csc_colorspace_info *colorspace_info;
|
const struct rk_csc_colorspace_info *colorspace_info;
|
||||||
enum color_space_type input_color_space;
|
|
||||||
enum color_space_type output_color_space;
|
|
||||||
bool is_input_full_range;
|
|
||||||
bool is_output_full_range;
|
|
||||||
int i;
|
int i;
|
||||||
|
enum color_space_type input_color_space, output_color_space;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(csc_mapping_table); i++) {
|
input_color_space = get_color_space_type(color_encoding, is_input_yuv);
|
||||||
if (post_csc_mode == csc_mapping_table[i].csc_format) {
|
output_color_space = get_color_space_type(color_encoding, is_output_yuv);
|
||||||
input_color_space = is_input_yuv ? csc_mapping_table[i].yuv_color_space :
|
|
||||||
csc_mapping_table[i].rgb_color_space;
|
|
||||||
is_input_full_range = is_input_yuv ? csc_mapping_table[i].yuv_full_range :
|
|
||||||
csc_mapping_table[i].rgb_full_range;
|
|
||||||
output_color_space = is_output_yuv ? csc_mapping_table[i].yuv_color_space :
|
|
||||||
csc_mapping_table[i].rgb_color_space;
|
|
||||||
is_output_full_range = is_output_yuv ? csc_mapping_table[i].yuv_full_range :
|
|
||||||
csc_mapping_table[i].rgb_full_range;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i >= ARRAY_SIZE(csc_mapping_table))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(g_mode_csc_coef); i++) {
|
for (i = 0; i < ARRAY_SIZE(g_mode_csc_coef); i++) {
|
||||||
colorspace_info = &g_mode_csc_coef[i].st_csc_color_info;
|
colorspace_info = &g_mode_csc_coef[i].st_csc_color_info;
|
||||||
@@ -1539,7 +1492,7 @@ static void rockchip_swap_color_channel(bool is_input_yuv, bool is_output_yuv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int rockchip_calc_post_csc(struct post_csc *csc_cfg, struct post_csc_coef *csc_simple_coef,
|
int rockchip_calc_post_csc(struct post_csc *csc_cfg, struct post_csc_coef *csc_simple_coef,
|
||||||
int csc_mode, bool is_input_yuv, bool is_output_yuv)
|
struct post_csc_convert_mode *convert_mode)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct rk_pq_csc_coef out_matrix;
|
struct rk_pq_csc_coef out_matrix;
|
||||||
@@ -1547,22 +1500,27 @@ int rockchip_calc_post_csc(struct post_csc *csc_cfg, struct post_csc_coef *csc_s
|
|||||||
const struct rk_csc_mode_coef *csc_mode_cfg;
|
const struct rk_csc_mode_coef *csc_mode_cfg;
|
||||||
int bit_num = PQ_CSC_SIMPLE_MAT_PARAM_FIX_BIT_WIDTH;
|
int bit_num = PQ_CSC_SIMPLE_MAT_PARAM_FIX_BIT_WIDTH;
|
||||||
|
|
||||||
ret = csc_get_mode_index(csc_mode, is_input_yuv, is_output_yuv);
|
ret = csc_get_mode_index(convert_mode->is_input_full_range,
|
||||||
|
convert_mode->is_output_full_range, convert_mode->is_input_yuv,
|
||||||
|
convert_mode->is_output_yuv, convert_mode->color_encoding);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
DRM_ERROR("invalid csc_mode:%d\n", csc_mode);
|
DRM_ERROR("get csc index err:\n");
|
||||||
|
DRM_ERROR("input yuv %d full_range %d,output yuv %d full_range %d\n",
|
||||||
|
convert_mode->is_input_yuv, convert_mode->is_input_full_range,
|
||||||
|
convert_mode->is_output_yuv, convert_mode->is_output_full_range);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
csc_mode_cfg = &g_mode_csc_coef[ret];
|
csc_mode_cfg = &g_mode_csc_coef[ret];
|
||||||
|
|
||||||
if (csc_cfg)
|
if (csc_cfg)
|
||||||
ret = csc_calc_adjust_output_coef(is_input_yuv, is_output_yuv, csc_cfg,
|
ret = csc_calc_adjust_output_coef(convert_mode->is_input_yuv,
|
||||||
|
convert_mode->is_output_yuv, csc_cfg,
|
||||||
csc_mode_cfg, &out_matrix, &out_dc);
|
csc_mode_cfg, &out_matrix, &out_dc);
|
||||||
else
|
else
|
||||||
ret = csc_calc_default_output_coef(csc_mode_cfg, &out_matrix, &out_dc);
|
ret = csc_calc_default_output_coef(csc_mode_cfg, &out_matrix, &out_dc);
|
||||||
|
|
||||||
rockchip_swap_color_channel(is_input_yuv, is_output_yuv, csc_simple_coef, &out_matrix,
|
rockchip_swap_color_channel(convert_mode->is_input_yuv, convert_mode->is_output_yuv,
|
||||||
&out_dc);
|
csc_simple_coef, &out_matrix, &out_dc);
|
||||||
|
|
||||||
csc_simple_coef->csc_dc0 = pq_csc_simple_round(csc_simple_coef->csc_dc0, bit_num);
|
csc_simple_coef->csc_dc0 = pq_csc_simple_round(csc_simple_coef->csc_dc0, bit_num);
|
||||||
csc_simple_coef->csc_dc1 = pq_csc_simple_round(csc_simple_coef->csc_dc1, bit_num);
|
csc_simple_coef->csc_dc1 = pq_csc_simple_round(csc_simple_coef->csc_dc1, bit_num);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "rockchip_drm_drv.h"
|
#include "rockchip_drm_drv.h"
|
||||||
#include "rockchip_drm_vop.h"
|
#include "rockchip_drm_vop.h"
|
||||||
|
|
||||||
int rockchip_calc_post_csc(struct post_csc *csc, struct post_csc_coef *csc_coef,
|
int rockchip_calc_post_csc(struct post_csc *csc_cfg, struct post_csc_coef *csc_simple_coef,
|
||||||
int csc_mode, bool is_input_yuv, bool is_output_yuv);
|
struct post_csc_convert_mode *convert_mode);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user