mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
1c21aa8f2b
Currently, YUV hardware overlays are converted to RGB using a color space conversion different than BT.601. The result is that colors of e.g. NV12 buffers don't match colors of YUV hardware overlays. In order to fix this, enable YUV2YUV and set appropriate coefficients for formats such as NV12 to be displayed correctly. This commit was tested using modetest, gstreamer and chromeos (hardware accelerated video playback). Before the commit, tests rendering with NV12 format resulted in colors not displayed correctly. Test examples (Tested on RK3399 and RK3288 boards connected to HDMI monitor): $ modetest 39@32:1920x1080@NV12 $ gst-launch-1.0 videotestrc ! video/x-raw,format=NV12 ! kmssink Signed-off-by: Daniele Castagna <dcastagna@chromium.org> [ezequiel: rebase on linux-next and massage commit log] Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com> Signed-off-by: Heiko Stuebner <heiko@sntech.de> Link: https://patchwork.freedesktop.org/patch/msgid/20190108214659.28794-1-ezequiel@collabora.com
371 lines
8.3 KiB
C
371 lines
8.3 KiB
C
/*
|
|
* Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
|
|
* Author:Mark Yao <mark.yao@rock-chips.com>
|
|
*
|
|
* This software is licensed under the terms of the GNU General Public
|
|
* License version 2, as published by the Free Software Foundation, and
|
|
* may be copied, distributed, and modified under those terms.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#ifndef _ROCKCHIP_DRM_VOP_H
|
|
#define _ROCKCHIP_DRM_VOP_H
|
|
|
|
/*
|
|
* major: IP major version, used for IP structure
|
|
* minor: big feature change under same structure
|
|
*/
|
|
#define VOP_VERSION(major, minor) ((major) << 8 | (minor))
|
|
#define VOP_MAJOR(version) ((version) >> 8)
|
|
#define VOP_MINOR(version) ((version) & 0xff)
|
|
|
|
#define NUM_YUV2YUV_COEFFICIENTS 12
|
|
|
|
enum vop_data_format {
|
|
VOP_FMT_ARGB8888 = 0,
|
|
VOP_FMT_RGB888,
|
|
VOP_FMT_RGB565,
|
|
VOP_FMT_YUV420SP = 4,
|
|
VOP_FMT_YUV422SP,
|
|
VOP_FMT_YUV444SP,
|
|
};
|
|
|
|
struct vop_reg {
|
|
uint32_t mask;
|
|
uint16_t offset;
|
|
uint8_t shift;
|
|
bool write_mask;
|
|
bool relaxed;
|
|
};
|
|
|
|
struct vop_modeset {
|
|
struct vop_reg htotal_pw;
|
|
struct vop_reg hact_st_end;
|
|
struct vop_reg hpost_st_end;
|
|
struct vop_reg vtotal_pw;
|
|
struct vop_reg vact_st_end;
|
|
struct vop_reg vpost_st_end;
|
|
};
|
|
|
|
struct vop_output {
|
|
struct vop_reg pin_pol;
|
|
struct vop_reg dp_pin_pol;
|
|
struct vop_reg edp_pin_pol;
|
|
struct vop_reg hdmi_pin_pol;
|
|
struct vop_reg mipi_pin_pol;
|
|
struct vop_reg rgb_pin_pol;
|
|
struct vop_reg dp_en;
|
|
struct vop_reg edp_en;
|
|
struct vop_reg hdmi_en;
|
|
struct vop_reg mipi_en;
|
|
struct vop_reg mipi_dual_channel_en;
|
|
struct vop_reg rgb_en;
|
|
};
|
|
|
|
struct vop_common {
|
|
struct vop_reg cfg_done;
|
|
struct vop_reg dsp_blank;
|
|
struct vop_reg data_blank;
|
|
struct vop_reg pre_dither_down;
|
|
struct vop_reg dither_down;
|
|
struct vop_reg dither_up;
|
|
struct vop_reg gate_en;
|
|
struct vop_reg mmu_en;
|
|
struct vop_reg out_mode;
|
|
struct vop_reg standby;
|
|
};
|
|
|
|
struct vop_misc {
|
|
struct vop_reg global_regdone_en;
|
|
};
|
|
|
|
struct vop_intr {
|
|
const int *intrs;
|
|
uint32_t nintrs;
|
|
|
|
struct vop_reg line_flag_num[2];
|
|
struct vop_reg enable;
|
|
struct vop_reg clear;
|
|
struct vop_reg status;
|
|
};
|
|
|
|
struct vop_scl_extension {
|
|
struct vop_reg cbcr_vsd_mode;
|
|
struct vop_reg cbcr_vsu_mode;
|
|
struct vop_reg cbcr_hsd_mode;
|
|
struct vop_reg cbcr_ver_scl_mode;
|
|
struct vop_reg cbcr_hor_scl_mode;
|
|
struct vop_reg yrgb_vsd_mode;
|
|
struct vop_reg yrgb_vsu_mode;
|
|
struct vop_reg yrgb_hsd_mode;
|
|
struct vop_reg yrgb_ver_scl_mode;
|
|
struct vop_reg yrgb_hor_scl_mode;
|
|
struct vop_reg line_load_mode;
|
|
struct vop_reg cbcr_axi_gather_num;
|
|
struct vop_reg yrgb_axi_gather_num;
|
|
struct vop_reg vsd_cbcr_gt2;
|
|
struct vop_reg vsd_cbcr_gt4;
|
|
struct vop_reg vsd_yrgb_gt2;
|
|
struct vop_reg vsd_yrgb_gt4;
|
|
struct vop_reg bic_coe_sel;
|
|
struct vop_reg cbcr_axi_gather_en;
|
|
struct vop_reg yrgb_axi_gather_en;
|
|
struct vop_reg lb_mode;
|
|
};
|
|
|
|
struct vop_scl_regs {
|
|
const struct vop_scl_extension *ext;
|
|
|
|
struct vop_reg scale_yrgb_x;
|
|
struct vop_reg scale_yrgb_y;
|
|
struct vop_reg scale_cbcr_x;
|
|
struct vop_reg scale_cbcr_y;
|
|
};
|
|
|
|
struct vop_yuv2yuv_phy {
|
|
struct vop_reg y2r_coefficients[NUM_YUV2YUV_COEFFICIENTS];
|
|
};
|
|
|
|
struct vop_win_phy {
|
|
const struct vop_scl_regs *scl;
|
|
const uint32_t *data_formats;
|
|
uint32_t nformats;
|
|
|
|
struct vop_reg enable;
|
|
struct vop_reg gate;
|
|
struct vop_reg format;
|
|
struct vop_reg rb_swap;
|
|
struct vop_reg act_info;
|
|
struct vop_reg dsp_info;
|
|
struct vop_reg dsp_st;
|
|
struct vop_reg yrgb_mst;
|
|
struct vop_reg uv_mst;
|
|
struct vop_reg yrgb_vir;
|
|
struct vop_reg uv_vir;
|
|
|
|
struct vop_reg dst_alpha_ctl;
|
|
struct vop_reg src_alpha_ctl;
|
|
struct vop_reg channel;
|
|
};
|
|
|
|
struct vop_win_yuv2yuv_data {
|
|
uint32_t base;
|
|
const struct vop_yuv2yuv_phy *phy;
|
|
struct vop_reg y2r_en;
|
|
};
|
|
|
|
struct vop_win_data {
|
|
uint32_t base;
|
|
const struct vop_win_phy *phy;
|
|
enum drm_plane_type type;
|
|
};
|
|
|
|
struct vop_data {
|
|
uint32_t version;
|
|
const struct vop_intr *intr;
|
|
const struct vop_common *common;
|
|
const struct vop_misc *misc;
|
|
const struct vop_modeset *modeset;
|
|
const struct vop_output *output;
|
|
const struct vop_win_yuv2yuv_data *win_yuv2yuv;
|
|
const struct vop_win_data *win;
|
|
unsigned int win_size;
|
|
|
|
#define VOP_FEATURE_OUTPUT_RGB10 BIT(0)
|
|
#define VOP_FEATURE_INTERNAL_RGB BIT(1)
|
|
u64 feature;
|
|
};
|
|
|
|
/* interrupt define */
|
|
#define DSP_HOLD_VALID_INTR (1 << 0)
|
|
#define FS_INTR (1 << 1)
|
|
#define LINE_FLAG_INTR (1 << 2)
|
|
#define BUS_ERROR_INTR (1 << 3)
|
|
|
|
#define INTR_MASK (DSP_HOLD_VALID_INTR | FS_INTR | \
|
|
LINE_FLAG_INTR | BUS_ERROR_INTR)
|
|
|
|
#define DSP_HOLD_VALID_INTR_EN(x) ((x) << 4)
|
|
#define FS_INTR_EN(x) ((x) << 5)
|
|
#define LINE_FLAG_INTR_EN(x) ((x) << 6)
|
|
#define BUS_ERROR_INTR_EN(x) ((x) << 7)
|
|
#define DSP_HOLD_VALID_INTR_MASK (1 << 4)
|
|
#define FS_INTR_MASK (1 << 5)
|
|
#define LINE_FLAG_INTR_MASK (1 << 6)
|
|
#define BUS_ERROR_INTR_MASK (1 << 7)
|
|
|
|
#define INTR_CLR_SHIFT 8
|
|
#define DSP_HOLD_VALID_INTR_CLR (1 << (INTR_CLR_SHIFT + 0))
|
|
#define FS_INTR_CLR (1 << (INTR_CLR_SHIFT + 1))
|
|
#define LINE_FLAG_INTR_CLR (1 << (INTR_CLR_SHIFT + 2))
|
|
#define BUS_ERROR_INTR_CLR (1 << (INTR_CLR_SHIFT + 3))
|
|
|
|
#define DSP_LINE_NUM(x) (((x) & 0x1fff) << 12)
|
|
#define DSP_LINE_NUM_MASK (0x1fff << 12)
|
|
|
|
/* src alpha ctrl define */
|
|
#define SRC_FADING_VALUE(x) (((x) & 0xff) << 24)
|
|
#define SRC_GLOBAL_ALPHA(x) (((x) & 0xff) << 16)
|
|
#define SRC_FACTOR_M0(x) (((x) & 0x7) << 6)
|
|
#define SRC_ALPHA_CAL_M0(x) (((x) & 0x1) << 5)
|
|
#define SRC_BLEND_M0(x) (((x) & 0x3) << 3)
|
|
#define SRC_ALPHA_M0(x) (((x) & 0x1) << 2)
|
|
#define SRC_COLOR_M0(x) (((x) & 0x1) << 1)
|
|
#define SRC_ALPHA_EN(x) (((x) & 0x1) << 0)
|
|
/* dst alpha ctrl define */
|
|
#define DST_FACTOR_M0(x) (((x) & 0x7) << 6)
|
|
|
|
/*
|
|
* display output interface supported by rockchip lcdc
|
|
*/
|
|
#define ROCKCHIP_OUT_MODE_P888 0
|
|
#define ROCKCHIP_OUT_MODE_P666 1
|
|
#define ROCKCHIP_OUT_MODE_P565 2
|
|
/* for use special outface */
|
|
#define ROCKCHIP_OUT_MODE_AAAA 15
|
|
|
|
/* output flags */
|
|
#define ROCKCHIP_OUTPUT_DSI_DUAL BIT(0)
|
|
|
|
enum alpha_mode {
|
|
ALPHA_STRAIGHT,
|
|
ALPHA_INVERSE,
|
|
};
|
|
|
|
enum global_blend_mode {
|
|
ALPHA_GLOBAL,
|
|
ALPHA_PER_PIX,
|
|
ALPHA_PER_PIX_GLOBAL,
|
|
};
|
|
|
|
enum alpha_cal_mode {
|
|
ALPHA_SATURATION,
|
|
ALPHA_NO_SATURATION,
|
|
};
|
|
|
|
enum color_mode {
|
|
ALPHA_SRC_PRE_MUL,
|
|
ALPHA_SRC_NO_PRE_MUL,
|
|
};
|
|
|
|
enum factor_mode {
|
|
ALPHA_ZERO,
|
|
ALPHA_ONE,
|
|
ALPHA_SRC,
|
|
ALPHA_SRC_INVERSE,
|
|
ALPHA_SRC_GLOBAL,
|
|
};
|
|
|
|
enum scale_mode {
|
|
SCALE_NONE = 0x0,
|
|
SCALE_UP = 0x1,
|
|
SCALE_DOWN = 0x2
|
|
};
|
|
|
|
enum lb_mode {
|
|
LB_YUV_3840X5 = 0x0,
|
|
LB_YUV_2560X8 = 0x1,
|
|
LB_RGB_3840X2 = 0x2,
|
|
LB_RGB_2560X4 = 0x3,
|
|
LB_RGB_1920X5 = 0x4,
|
|
LB_RGB_1280X8 = 0x5
|
|
};
|
|
|
|
enum sacle_up_mode {
|
|
SCALE_UP_BIL = 0x0,
|
|
SCALE_UP_BIC = 0x1
|
|
};
|
|
|
|
enum scale_down_mode {
|
|
SCALE_DOWN_BIL = 0x0,
|
|
SCALE_DOWN_AVG = 0x1
|
|
};
|
|
|
|
enum vop_pol {
|
|
HSYNC_POSITIVE = 0,
|
|
VSYNC_POSITIVE = 1,
|
|
DEN_NEGATIVE = 2,
|
|
DCLK_INVERT = 3
|
|
};
|
|
|
|
#define FRAC_16_16(mult, div) (((mult) << 16) / (div))
|
|
#define SCL_FT_DEFAULT_FIXPOINT_SHIFT 12
|
|
#define SCL_MAX_VSKIPLINES 4
|
|
#define MIN_SCL_FT_AFTER_VSKIP 1
|
|
|
|
static inline uint16_t scl_cal_scale(int src, int dst, int shift)
|
|
{
|
|
return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
|
|
}
|
|
|
|
static inline uint16_t scl_cal_scale2(int src, int dst)
|
|
{
|
|
return ((src - 1) << 12) / (dst - 1);
|
|
}
|
|
|
|
#define GET_SCL_FT_BILI_DN(src, dst) scl_cal_scale(src, dst, 12)
|
|
#define GET_SCL_FT_BILI_UP(src, dst) scl_cal_scale(src, dst, 16)
|
|
#define GET_SCL_FT_BIC(src, dst) scl_cal_scale(src, dst, 16)
|
|
|
|
static inline uint16_t scl_get_bili_dn_vskip(int src_h, int dst_h,
|
|
int vskiplines)
|
|
{
|
|
int act_height;
|
|
|
|
act_height = (src_h + vskiplines - 1) / vskiplines;
|
|
|
|
if (act_height == dst_h)
|
|
return GET_SCL_FT_BILI_DN(src_h, dst_h) / vskiplines;
|
|
|
|
return GET_SCL_FT_BILI_DN(act_height, dst_h);
|
|
}
|
|
|
|
static inline enum scale_mode scl_get_scl_mode(int src, int dst)
|
|
{
|
|
if (src < dst)
|
|
return SCALE_UP;
|
|
else if (src > dst)
|
|
return SCALE_DOWN;
|
|
|
|
return SCALE_NONE;
|
|
}
|
|
|
|
static inline int scl_get_vskiplines(uint32_t srch, uint32_t dsth)
|
|
{
|
|
uint32_t vskiplines;
|
|
|
|
for (vskiplines = SCL_MAX_VSKIPLINES; vskiplines > 1; vskiplines /= 2)
|
|
if (srch >= vskiplines * dsth * MIN_SCL_FT_AFTER_VSKIP)
|
|
break;
|
|
|
|
return vskiplines;
|
|
}
|
|
|
|
static inline int scl_vop_cal_lb_mode(int width, bool is_yuv)
|
|
{
|
|
int lb_mode;
|
|
|
|
if (is_yuv) {
|
|
if (width > 1280)
|
|
lb_mode = LB_YUV_3840X5;
|
|
else
|
|
lb_mode = LB_YUV_2560X8;
|
|
} else {
|
|
if (width > 2560)
|
|
lb_mode = LB_RGB_3840X2;
|
|
else if (width > 1920)
|
|
lb_mode = LB_RGB_2560X4;
|
|
else
|
|
lb_mode = LB_RGB_1920X5;
|
|
}
|
|
|
|
return lb_mode;
|
|
}
|
|
|
|
extern const struct component_ops vop_component_ops;
|
|
#endif /* _ROCKCHIP_DRM_VOP_H */
|