mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
drm/rockchip: vop2: add dolby vision supported for rk3588
The dolby vision will be supported by RK3588*-*V* SOCs, e.g., RK3588S2-DV. Signed-off-by: Sandy Huang <hjc@rock-chips.com> Change-Id: I1e8cf8f0e2b1521b858704df9a88261cec038ebb
This commit is contained in:
@@ -1613,7 +1613,7 @@ static int rockchip_drm_create_properties(struct drm_device *dev)
|
||||
struct rockchip_drm_private *private = dev->dev_private;
|
||||
|
||||
prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
|
||||
"EOTF", 0, 5);
|
||||
"EOTF", 0, HDMI_EOTF_DOVI);
|
||||
if (!prop)
|
||||
return -ENOMEM;
|
||||
private->eotf_prop = prop;
|
||||
@@ -1651,6 +1651,12 @@ static int rockchip_drm_create_properties(struct drm_device *dev)
|
||||
"PORT_ID", DRM_MODE_OBJECT_CRTC);
|
||||
private->port_id_prop = prop;
|
||||
|
||||
prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
|
||||
"DOVI_INPUT_TYPE", 0, DOVI_ENHANCE_LAYER);
|
||||
if (!prop)
|
||||
return -ENOMEM;
|
||||
private->dovi_input_type_prop = prop;
|
||||
|
||||
private->aclk_prop = drm_property_create_range(dev, 0, "ACLK", 0, UINT_MAX);
|
||||
private->bg_prop = drm_property_create_range(dev, 0, "BACKGROUND", 0, UINT_MAX);
|
||||
private->line_flag_prop = drm_property_create_range(dev, 0, "LINE_FLAG1", 0, UINT_MAX);
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#define ROCKCHIP_MAX_CONNECTOR 2
|
||||
#define ROCKCHIP_MAX_CRTC 4
|
||||
#define ROCKCHIP_MAX_LAYER 16
|
||||
|
||||
#define ROCKCHIP_MAX_DOVI_CORE 3
|
||||
|
||||
struct drm_device;
|
||||
struct drm_connector;
|
||||
@@ -61,6 +61,20 @@ struct iommu_domain;
|
||||
#define RK_IF_PROP_COLOR_FORMAT_CAPS "color_format_caps"
|
||||
#define RK_IF_PROP_ENCRYPTED "hdcp_encrypted"
|
||||
|
||||
/*
|
||||
* This is extend by rockchip, the other EOTF is defined at hdmi.h
|
||||
*
|
||||
* enum hdmi_eotf {
|
||||
* HDMI_EOTF_TRADITIONAL_GAMMA_SDR,
|
||||
* HDMI_EOTF_TRADITIONAL_GAMMA_HDR,
|
||||
* HDMI_EOTF_SMPTE_ST2084,
|
||||
* HDMI_EOTF_BT_2100_HLG,
|
||||
*};
|
||||
*/
|
||||
#define HDMI_EOTF_HDR10PLUS 0x10
|
||||
#define HDMI_EOTF_HDRVIVID 0x11
|
||||
#define HDMI_EOTF_DOVI 0x12
|
||||
|
||||
enum rockchip_drm_debug_category {
|
||||
VOP_DEBUG_PLANE = BIT(0),
|
||||
VOP_DEBUG_OVERLAY = BIT(1),
|
||||
@@ -158,6 +172,8 @@ struct rockchip_bcsh_state {
|
||||
|
||||
struct rockchip_crtc {
|
||||
struct drm_crtc crtc;
|
||||
/* @frme_count: the frame num of commit buf */
|
||||
u32 frame_count;
|
||||
#if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
|
||||
/**
|
||||
* @vop_dump_status the status of vop dump control
|
||||
@@ -553,6 +569,7 @@ struct rockchip_drm_private {
|
||||
struct drm_property *eotf_prop;
|
||||
struct drm_property *async_commit_prop;
|
||||
struct drm_property *share_id_prop;
|
||||
struct drm_property *dovi_input_type_prop;
|
||||
|
||||
/* private connector prop */
|
||||
struct drm_property *connector_id_prop;
|
||||
|
||||
@@ -70,7 +70,6 @@
|
||||
#define VOP_FEATURE_INTERNAL_RGB BIT(1)
|
||||
#define VOP_FEATURE_ALPHA_SCALE BIT(2)
|
||||
#define VOP_FEATURE_HDR10 BIT(3)
|
||||
#define VOP_FEATURE_NEXT_HDR BIT(4)
|
||||
#define VOP_FEATURE_DOVI BIT(4)
|
||||
/* a feature to splice two windows and two vps to support resolution > 4096 */
|
||||
#define VOP_FEATURE_SPLICE BIT(5)
|
||||
@@ -141,6 +140,10 @@ enum vop2_win_dly_mode {
|
||||
VOP2_DLY_MODE_DEFAULT, /**< default mode */
|
||||
VOP2_DLY_MODE_HISO_S, /** HDR in SDR out mode, as a SDR window */
|
||||
VOP2_DLY_MODE_HIHO_H, /** HDR in HDR out mode, as a HDR window */
|
||||
VOP2_DLY_MODE_DOVI_IN_CORE1, /* dovi video input, as dovi core1 */
|
||||
VOP2_DLY_MODE_DOVI_IN_CORE2, /* dovi video input, as dovi core2 */
|
||||
VOP2_DLY_MODE_NONDOVI_IN_CORE1, /* ndovi video input, as dovi core1 */
|
||||
VOP2_DLY_MODE_NONDOVI_IN_CORE2, /* ndovi video input, as dovi core2 */
|
||||
VOP2_DLY_MODE_MAX,
|
||||
};
|
||||
|
||||
@@ -615,11 +618,40 @@ struct hdrvivid_regs {
|
||||
#define RK_HDR_TYPE_MASK 0xff
|
||||
#define RK_HDR_PLAT_MASK (0xff << 8)
|
||||
|
||||
/* byte unit */
|
||||
#define VOP2_DOVI_CORE1_LUT_SIZE 5120
|
||||
#define VOP2_DOVI_TONE_SCA_AXI_TAB_SIZE (2560 * 4)
|
||||
|
||||
/* word unit */
|
||||
#define DOVI_LUT_SIZE 1280
|
||||
#define DOVI_CORE1_SIZE 242
|
||||
#define DOVI_CORE2_SIZE 43
|
||||
#define DOVI_CORE3_SIZE 256
|
||||
|
||||
enum vop_dovi_input_type {
|
||||
COMMON_LAYER = 0,
|
||||
DOVI_BASE_LAYER = 1,
|
||||
DOVI_ENHANCE_LAYER = 2,
|
||||
};
|
||||
|
||||
struct dovi_regs {
|
||||
uint32_t version;
|
||||
uint32_t valid;
|
||||
uint32_t input_mode;
|
||||
uint32_t output_mode;
|
||||
uint32_t core1_lut[DOVI_LUT_SIZE];
|
||||
uint32_t core2_lut[DOVI_LUT_SIZE];
|
||||
uint32_t core1[DOVI_CORE1_SIZE];
|
||||
uint32_t core2[DOVI_CORE2_SIZE];
|
||||
uint32_t core3[DOVI_CORE3_SIZE];
|
||||
};
|
||||
|
||||
struct hdr_extend {
|
||||
uint32_t hdr_type;
|
||||
uint32_t length;
|
||||
union {
|
||||
struct hdrvivid_regs hdrvivid_data;
|
||||
struct dovi_regs dovi_data;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -650,7 +682,7 @@ enum vop_hdr_format {
|
||||
HDR_HDR10PLUS = 8,
|
||||
RESERVED9 = 9, /* reserved for hdr hdr10+ */
|
||||
RESERVED10 = 10, /* reserved for hdr hdr10+ */
|
||||
HDR_NEXT = 11,
|
||||
HDR_DOVI = 11,
|
||||
RESERVED12 = 12, /* reserved for other dynamic hdr format */
|
||||
RESERVED13 = 13, /* reserved for other dynamic hdr format */
|
||||
HDR_FORMAT_MAX,
|
||||
@@ -883,6 +915,10 @@ struct vop2_video_port_regs {
|
||||
struct vop_reg dsp_x_mir_en;
|
||||
struct vop_reg post_dsp_out_r2y;
|
||||
struct vop_reg pre_scan_htiming;
|
||||
struct vop_reg dovi_pre_scan_en;
|
||||
struct vop_reg pre_scan_htiming1;
|
||||
struct vop_reg pre_scan_htiming2;
|
||||
struct vop_reg pre_scan_htiming3;
|
||||
struct vop_reg htotal_pw;
|
||||
struct vop_reg hact_st_end;
|
||||
struct vop_reg dsp_vtotal;
|
||||
@@ -905,6 +941,8 @@ struct vop2_video_port_regs {
|
||||
struct vop_reg dither_frc_2;
|
||||
struct vop_reg dither_up_en;
|
||||
struct vop_reg bg_dly;
|
||||
struct vop_reg dp_line_end_mode;
|
||||
struct vop_reg dp_bg_bottom_disable;
|
||||
|
||||
struct vop_reg p2i_en;
|
||||
struct vop_reg dual_channel_en;
|
||||
@@ -1050,6 +1088,37 @@ struct vop2_power_domain_regs {
|
||||
struct vop_reg pmu_status;
|
||||
};
|
||||
|
||||
struct vop2_dovi_regs {
|
||||
/* common */
|
||||
struct vop_reg enable;
|
||||
struct vop_reg interrupt_enable;
|
||||
struct vop_reg interrupt_raw;
|
||||
struct vop_reg metadata_program_st;
|
||||
struct vop_reg metadata_program_end;
|
||||
struct vop_reg metadata_copy_finish;
|
||||
|
||||
/* core1 */
|
||||
struct vop_reg bypass_composer;
|
||||
struct vop_reg bypass_csc;
|
||||
struct vop_reg bypass_cvm;
|
||||
struct vop_reg operating_mode;
|
||||
struct vop_reg pixel_rate;
|
||||
|
||||
/* core2 */
|
||||
struct vop_reg yuv2rgb_en;
|
||||
struct vop_reg yuv422to444_en;
|
||||
struct vop_reg yuv_swap;
|
||||
struct vop_reg yuv422_en;
|
||||
struct vop_reg dly_en;
|
||||
|
||||
/* core1 and core2 */
|
||||
struct vop_reg lut_mst;
|
||||
struct vop_reg lut_update;
|
||||
|
||||
/* core3 */
|
||||
struct vop_reg output_mode;
|
||||
};
|
||||
|
||||
struct vop2_dsc_regs {
|
||||
/* DSC SYS CTRL */
|
||||
struct vop_reg dsc_port_sel;
|
||||
@@ -1184,6 +1253,21 @@ struct vop2_win_data {
|
||||
const uint8_t dly[VOP2_DLY_MODE_MAX];
|
||||
};
|
||||
|
||||
struct vop2_dovi_core_data {
|
||||
const uint8_t id;
|
||||
const uint32_t ctrl_offset;
|
||||
const uint32_t srange_offset;
|
||||
const uint32_t srange_offset_from_core;
|
||||
const struct vop2_dovi_regs *regs;
|
||||
};
|
||||
|
||||
struct vop2_dovi_data {
|
||||
const uint8_t nr_dovi_cores;
|
||||
const uint8_t dovi_max_delay[2];
|
||||
const uint32_t enhance_layer_phy_id;
|
||||
const struct vop2_dovi_core_data *dovi_core_data;
|
||||
};
|
||||
|
||||
struct dsc_error_info {
|
||||
u32 dsc_error_val;
|
||||
char dsc_error_info[50];
|
||||
@@ -1481,6 +1565,10 @@ struct vop2_ctrl {
|
||||
struct vop_reg vp_intr_merge_en;
|
||||
struct vop_reg reg_done_frm;
|
||||
struct vop_reg cfg_done;
|
||||
|
||||
struct vop_reg dovi_core1_en;
|
||||
struct vop_reg dovi_core2_en;
|
||||
struct vop_reg dovi_core3_en;
|
||||
};
|
||||
|
||||
struct vop_dump_regs {
|
||||
@@ -1529,6 +1617,7 @@ struct vop2_data {
|
||||
const struct vop2_esmart_lb_map *esmart_lb_mode_map;
|
||||
const struct vop_intr *axi_intr;
|
||||
const struct vop2_ctrl *ctrl;
|
||||
const struct vop2_dovi_data *dovi;
|
||||
const struct vop2_dsc_data *dsc;
|
||||
const struct dsc_error_info *dsc_error_ecw;
|
||||
const struct dsc_error_info *dsc_error_buffer_flow;
|
||||
@@ -1581,6 +1670,9 @@ struct vop2_data {
|
||||
#define WB_YRGB_FIFO_FULL_INTR BIT(18)
|
||||
#define WB_COMPLETE_INTR BIT(19)
|
||||
#define MMU_EN_INTR BIT(20)
|
||||
#define DOLBY_CORE1_INTR BIT(21)
|
||||
#define DOLBY_CORE2_INTR BIT(22)
|
||||
#define DOLBY_CORE3_INTR BIT(23)
|
||||
|
||||
#define INTR_MASK (DSP_HOLD_VALID_INTR | FS_INTR | \
|
||||
LINE_FLAG_INTR | BUS_ERROR_INTR | \
|
||||
@@ -1590,7 +1682,8 @@ struct vop2_data {
|
||||
HWC_EMPTY_INTR | \
|
||||
POST_BUF_EMPTY_INTR | \
|
||||
DMA_FINISH_INTR | FS_FIELD_INTR | \
|
||||
FE_INTR | WB_COMPLETE_INTR | MMU_EN_INTR)
|
||||
FE_INTR | WB_COMPLETE_INTR | MMU_EN_INTR | \
|
||||
DOLBY_CORE1_INTR | DOLBY_CORE2_INTR | DOLBY_CORE3_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)
|
||||
|
||||
@@ -370,6 +370,7 @@ struct vop2_plane_state {
|
||||
uint64_t color_key;
|
||||
unsigned long offset;
|
||||
int pdaf_data_type;
|
||||
u8 dovi_input_type;
|
||||
bool async_commit;
|
||||
|
||||
struct drm_property_blob *dci_data;
|
||||
@@ -539,6 +540,12 @@ struct vop2_wb {
|
||||
|
||||
};
|
||||
|
||||
struct vop2_dovi_core {
|
||||
uint8_t id;
|
||||
struct vop2 *vop2;
|
||||
const struct vop2_dovi_regs *regs;
|
||||
};
|
||||
|
||||
struct vop2_dsc {
|
||||
uint8_t id;
|
||||
uint8_t max_slice_num;
|
||||
@@ -635,6 +642,19 @@ struct vop2_video_port {
|
||||
*/
|
||||
int hdr_en;
|
||||
|
||||
/**
|
||||
* @dovi_hdr_mode: Set when use dovi.
|
||||
*/
|
||||
bool dovi_hdr_mode;
|
||||
/**
|
||||
* @dovi_hdr_en: Set when dovi enabled.
|
||||
*/
|
||||
bool dovi_hdr_en;
|
||||
/**
|
||||
* @dovi_hdr_in: Set when dovi input.
|
||||
*/
|
||||
bool dovi_hdr_in;
|
||||
|
||||
/**
|
||||
* -----------------
|
||||
* | | |
|
||||
@@ -722,6 +742,11 @@ struct vop2_video_port {
|
||||
*/
|
||||
struct rockchip_gem_object *hdr_lut_gem_obj;
|
||||
|
||||
/**
|
||||
* @dovi_lut_gem_obj: gem obj to store dovi lut
|
||||
*/
|
||||
struct rockchip_gem_object *dovi_lut_gem_obj;
|
||||
|
||||
/**
|
||||
* @cubic_lut: cubic look up table
|
||||
*/
|
||||
@@ -856,6 +881,7 @@ struct vop2 {
|
||||
u32 version;
|
||||
struct device *dev;
|
||||
struct drm_device *drm_dev;
|
||||
struct vop2_dovi_core dovi_cores[ROCKCHIP_MAX_DOVI_CORE];
|
||||
struct vop2_dsc dscs[ROCKCHIP_MAX_CRTC];
|
||||
struct vop2_video_port vps[ROCKCHIP_MAX_CRTC];
|
||||
struct vop2_wb wb;
|
||||
@@ -962,6 +988,9 @@ struct vop2 {
|
||||
struct clk *hclk;
|
||||
struct clk *aclk;
|
||||
struct clk *pclk;
|
||||
struct clk *aclk_dovi;
|
||||
struct clk *aclk_div2_src;
|
||||
struct clk *aclk_root;
|
||||
struct reset_control *ahb_rst;
|
||||
struct reset_control *axi_rst;
|
||||
struct csu_clk *csu_aclk;
|
||||
@@ -1175,6 +1204,11 @@ static inline bool is_vop3(struct vop2 *vop2)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool vop2_is_dovi_mode(struct vop2_video_port *vp)
|
||||
{
|
||||
return vp->dovi_hdr_mode;
|
||||
}
|
||||
|
||||
static bool vop2_soc_is_rk3566(void)
|
||||
{
|
||||
return soc_is_rk3566();
|
||||
@@ -3302,6 +3336,19 @@ static void vop2_setup_csc_mode(struct vop2_video_port *vp,
|
||||
vpstate->r2y_en = 0;
|
||||
vpstate->csc_mode = 0;
|
||||
|
||||
/**
|
||||
* DOVI core1 input format must YUV422, VOP win will do:
|
||||
* [YUV420/422 -> YUV444], [YUV444 -> YUV422] -> core1
|
||||
* DOVI core2 input format must RGB
|
||||
*/
|
||||
if (vop2_is_dovi_mode(vp)) {
|
||||
if (vpstate->dovi_input_type && !is_input_yuv)
|
||||
drm_err(vp->vop2, "DOVI core1 input format must YUV format\n");
|
||||
if (!vpstate->dovi_input_type && is_input_yuv)
|
||||
drm_err(vp->vop2, "DOVI core2 input format must RGB format\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_vop3(vp->vop2)) {
|
||||
if (vpstate->hdr_in) {
|
||||
if (is_input_yuv) {
|
||||
@@ -4719,6 +4766,379 @@ static void vop2_power_off_all_pd(struct vop2 *vop2)
|
||||
}
|
||||
}
|
||||
|
||||
static bool vop2_check_dovi_core_enabled(int id, u32 valid)
|
||||
{
|
||||
if (valid & (BIT(id - 1)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The dovi always trigger error interrupt, so it's disabled by default */
|
||||
static void __maybe_unused vop2_enable_dovi_sys_irqs(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
|
||||
const struct vop_intr *intr = vp_data->intr;
|
||||
uint32_t irqs = DOLBY_CORE1_INTR | DOLBY_CORE2_INTR | DOLBY_CORE3_INTR;
|
||||
struct vop2_dovi_core *dovi_core;
|
||||
int i = 0;
|
||||
|
||||
VOP_INTR_SET_TYPE(vop2, intr, clear, irqs, 1);
|
||||
VOP_INTR_SET_TYPE(vop2, intr, enable, irqs, 1);
|
||||
|
||||
for (i = 0; i < vop2_data->dovi->nr_dovi_cores; i++) {
|
||||
dovi_core = &vop2->dovi_cores[i];
|
||||
/* enable memtadata program error and unmatched frame detect error */
|
||||
VOP_MODULE_SET(vop2, dovi_core, interrupt_enable, 3);
|
||||
}
|
||||
}
|
||||
|
||||
static int vop2_hdr_get_eotf_by_output_mode(int output_mode)
|
||||
{
|
||||
switch (output_mode) {
|
||||
case HDR_HDR10:
|
||||
return HDMI_EOTF_SMPTE_ST2084;
|
||||
case HDR_HDRVIVID:
|
||||
return HDMI_EOTF_HDRVIVID;
|
||||
case HDR_HDR10PLUS:
|
||||
return HDMI_EOTF_HDR10PLUS;
|
||||
case HDR_DOVI:
|
||||
return HDMI_EOTF_DOVI;
|
||||
case HDR_NONE:
|
||||
default:
|
||||
return HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
|
||||
}
|
||||
}
|
||||
|
||||
static void vop2_dovi_enable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
struct vop2_dovi_core *dovi_core;
|
||||
struct dovi_regs *dovi_data;
|
||||
struct hdr_extend *hdr_data;
|
||||
int i = 0;
|
||||
|
||||
if (vp->dovi_hdr_en)
|
||||
return;
|
||||
|
||||
hdr_data = (struct hdr_extend *)vcstate->hdr_ext_data->data;
|
||||
if (!hdr_data)
|
||||
return;
|
||||
dovi_data = &hdr_data->dovi_data;
|
||||
for (i = 0; i < vop2_data->dovi->nr_dovi_cores; i++) {
|
||||
dovi_core = &vop2->dovi_cores[i];
|
||||
|
||||
if (vop2_check_dovi_core_enabled(dovi_core->id, dovi_data->valid))
|
||||
VOP_MODULE_SET(vop2, dovi_core, enable, 1);
|
||||
}
|
||||
|
||||
vp->dovi_hdr_en = true;
|
||||
DRM_DEV_INFO(vop2->dev, "vp%d dovi enabled\n", vp->id);
|
||||
}
|
||||
|
||||
static int vop2_dovi_init(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
|
||||
struct hdr_extend *hdr_data;
|
||||
unsigned long aclk_rate;
|
||||
int ret = 0;
|
||||
|
||||
if (!vcstate || !vcstate->hdr_ext_data)
|
||||
return 0;
|
||||
|
||||
hdr_data = (struct hdr_extend *)vcstate->hdr_ext_data->data;
|
||||
if (!hdr_data || hdr_data->hdr_type != HDR_DOVI)
|
||||
return 0;
|
||||
|
||||
aclk_rate = clk_get_rate(vop2->aclk);
|
||||
if (!vp->dovi_lut_gem_obj) {
|
||||
vp->dovi_lut_gem_obj =
|
||||
rockchip_gem_create_object(vop2->drm_dev,
|
||||
VOP2_DOVI_TONE_SCA_AXI_TAB_SIZE * 2,
|
||||
true, 0);
|
||||
|
||||
if (IS_ERR(vp->dovi_lut_gem_obj)) {
|
||||
drm_err(vop2, "create dovi lut obj failed\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(vop2->aclk_dovi);
|
||||
if (ret < 0)
|
||||
drm_err(vop2, "failed to enable aclk_dovi - %d\n", ret);
|
||||
|
||||
ret = clk_set_parent(vop2->aclk, vop2->aclk_div2_src);
|
||||
if (ret < 0) {
|
||||
drm_err(vop2, "failed to set parent(%s) for %s\n",
|
||||
__clk_get_name(vop2->aclk_div2_src),
|
||||
__clk_get_name(vop2->aclk));
|
||||
}
|
||||
clk_set_rate(vop2->aclk_dovi, aclk_rate);
|
||||
/* vop2_enable_dovi_sys_irqs(crtc); */
|
||||
|
||||
vp->dovi_hdr_mode = true;
|
||||
vop2_dovi_enable(crtc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vop2_dovi_pre_disable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
struct vop2_dovi_core *dovi_core;
|
||||
int i;
|
||||
|
||||
if (!vp->dovi_hdr_en)
|
||||
return;
|
||||
|
||||
VOP_MODULE_SET(vop2, vp, dp_line_end_mode, 0);
|
||||
VOP_MODULE_SET(vop2, vp, dp_bg_bottom_disable, 0);
|
||||
VOP_MODULE_SET(vop2, vp, dovi_pre_scan_en, 0);
|
||||
for (i = 0; i < vop2_data->dovi->nr_dovi_cores; i++) {
|
||||
dovi_core = &vop2->dovi_cores[i];
|
||||
VOP_MODULE_SET(vop2, dovi_core, enable, 0);
|
||||
VOP_MODULE_SET(vop2, dovi_core, lut_update, 0);
|
||||
if (dovi_core->id == 2)
|
||||
VOP_MODULE_SET(vop2, dovi_core, dly_en, 0);
|
||||
}
|
||||
VOP_CTRL_SET(vop2, lut_dma_en, 0);
|
||||
}
|
||||
|
||||
static void vop2_dovi_post_disable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
int ret;
|
||||
|
||||
if (!vp->dovi_hdr_en)
|
||||
return;
|
||||
|
||||
ret = clk_set_parent(vop2->aclk, vop2->aclk_root);
|
||||
if (ret < 0)
|
||||
drm_err(vop2,
|
||||
"failed to set aclk vop parent back to aclk vop root\n");
|
||||
clk_disable_unprepare(vop2->aclk_dovi);
|
||||
if (vp->dovi_lut_gem_obj)
|
||||
rockchip_gem_free_object(&vp->dovi_lut_gem_obj->base);
|
||||
vp->dovi_lut_gem_obj = NULL;
|
||||
vp->dovi_hdr_mode = false;
|
||||
vp->dovi_hdr_en = false;
|
||||
vp->dovi_hdr_in = false;
|
||||
drm_info(vop2, "vp%d dovi disabled\n", vp->id);
|
||||
}
|
||||
|
||||
static u32 vop2_read_dovi_metadata_copy_finish(struct vop2_dovi_core *dovi_core)
|
||||
{
|
||||
struct vop2 *vop2 = dovi_core->vop2;
|
||||
|
||||
return VOP_MODULE_GET(vop2, dovi_core, metadata_copy_finish);
|
||||
}
|
||||
|
||||
static void vop2_wait_for_dovi_metadata_copy_finish(struct vop2_dovi_core *dovi_core)
|
||||
{
|
||||
struct vop2 *vop2 = dovi_core->vop2;
|
||||
bool finish;
|
||||
int ret;
|
||||
|
||||
ret = readx_poll_timeout_atomic(vop2_read_dovi_metadata_copy_finish,
|
||||
dovi_core, finish, finish == true, 0, 10 * 1000);
|
||||
if (ret)
|
||||
DRM_DEV_DEBUG(vop2->dev, "Wait dovi%d metadata copy finish timeout: 0x%x\n",
|
||||
dovi_core->id, vop2_readl(vop2, dovi_core->regs->metadata_copy_finish.offset));
|
||||
}
|
||||
|
||||
|
||||
static u32 vop2_read_dovi_core_enable(struct vop2_dovi_core *dovi_core)
|
||||
{
|
||||
struct vop2 *vop2 = dovi_core->vop2;
|
||||
|
||||
return VOP_MODULE_GET(vop2, dovi_core, enable);
|
||||
}
|
||||
|
||||
static void vop2_wait_for_dovi_core_enabled(struct vop2_dovi_core *dovi_core)
|
||||
{
|
||||
struct vop2 *vop2 = dovi_core->vop2;
|
||||
bool enable;
|
||||
int ret;
|
||||
|
||||
ret = readx_poll_timeout_atomic(vop2_read_dovi_core_enable,
|
||||
dovi_core, enable, enable == true, 0, 10 * 1000);
|
||||
if (ret)
|
||||
DRM_DEV_DEBUG(vop2->dev, "Wait dovi%d metadata copy finish timeout: 0x%x\n",
|
||||
dovi_core->id, vop2_readl(vop2, dovi_core->regs->metadata_copy_finish.offset));
|
||||
}
|
||||
|
||||
static void vop2_load_dovi_coe_table(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
|
||||
struct dovi_regs *dovi_reg_data;
|
||||
struct hdr_extend *hdr_data;
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
const struct vop2_dovi_core_data *dovi_core_data;
|
||||
struct vop2_dovi_core *dovi_core;
|
||||
u32 *dovi_lut_kvaddr;
|
||||
u32 dovi_lut_mst;
|
||||
int i = 0, j = 0;
|
||||
u32 offset = vp->rockchip_crtc.frame_count % 2 ? 0 : VOP2_DOVI_TONE_SCA_AXI_TAB_SIZE;
|
||||
|
||||
if (!vop2_is_dovi_mode(vp))
|
||||
return;
|
||||
|
||||
if (!vcstate->hdr_ext_data)
|
||||
return;
|
||||
|
||||
hdr_data = (struct hdr_extend *)vcstate->hdr_ext_data->data;
|
||||
dovi_reg_data = &hdr_data->dovi_data;
|
||||
vcstate->eotf = vop2_hdr_get_eotf_by_output_mode(dovi_reg_data->output_mode);
|
||||
|
||||
for (i = 0; i < vop2_data->dovi->nr_dovi_cores; i++) {
|
||||
dovi_core = &vop2->dovi_cores[i];
|
||||
|
||||
if (!vop2_check_dovi_core_enabled(dovi_core->id, dovi_reg_data->valid))
|
||||
continue;
|
||||
|
||||
vop2_wait_for_dovi_core_enabled(dovi_core);
|
||||
/*
|
||||
* The metadata_copy_finish maybe cleared by vop2_dovi_hanle_irqs,
|
||||
* but vop2_dovi_hanle_irqs is disabled now.
|
||||
*/
|
||||
vop2_wait_for_dovi_metadata_copy_finish(dovi_core);
|
||||
VOP_MODULE_SET(vop2, dovi_core, metadata_copy_finish, 1);
|
||||
}
|
||||
|
||||
dovi_lut_kvaddr = (u32 *)vp->dovi_lut_gem_obj->kvaddr + offset / 4;
|
||||
memcpy(dovi_lut_kvaddr, &dovi_reg_data->core1_lut, VOP2_DOVI_CORE1_LUT_SIZE);
|
||||
dovi_lut_kvaddr += VOP2_DOVI_CORE1_LUT_SIZE / 4;
|
||||
memcpy(dovi_lut_kvaddr, &dovi_reg_data->core2_lut, VOP2_DOVI_CORE1_LUT_SIZE);
|
||||
|
||||
dovi_lut_mst = vp->dovi_lut_gem_obj->dma_addr + offset;
|
||||
for (i = 0; i < vop2_data->dovi->nr_dovi_cores; i++) {
|
||||
dovi_core = &vop2->dovi_cores[i];
|
||||
|
||||
if (!vop2_check_dovi_core_enabled(dovi_core->id, dovi_reg_data->valid))
|
||||
continue;
|
||||
|
||||
if (dovi_core->id == 1)
|
||||
VOP_MODULE_SET(vop2, dovi_core, lut_mst, dovi_lut_mst);
|
||||
|
||||
if (dovi_core->id == 2)
|
||||
VOP_MODULE_SET(vop2, dovi_core, lut_mst, dovi_lut_mst + VOP2_DOVI_CORE1_LUT_SIZE);
|
||||
}
|
||||
|
||||
VOP_CTRL_SET(vop2, lut_dma_en, 1);
|
||||
|
||||
for (i = 0; i < vop2_data->dovi->nr_dovi_cores; i++) {
|
||||
dovi_core = &vop2->dovi_cores[i];
|
||||
|
||||
if (!vop2_check_dovi_core_enabled(dovi_core->id, dovi_reg_data->valid))
|
||||
continue;
|
||||
|
||||
VOP_MODULE_SET(vop2, dovi_core, lut_update, 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < vop2_data->dovi->nr_dovi_cores; i++) {
|
||||
u32 *core_data = NULL;
|
||||
int size;
|
||||
int offset;
|
||||
|
||||
dovi_core_data = &vop2_data->dovi->dovi_core_data[i];
|
||||
dovi_core = &vop2->dovi_cores[i];
|
||||
|
||||
if (!vop2_check_dovi_core_enabled(dovi_core->id, dovi_reg_data->valid))
|
||||
continue;
|
||||
|
||||
if (dovi_core->id == 1) {
|
||||
core_data = (u32 *)&dovi_reg_data->core1;
|
||||
offset = dovi_core_data->srange_offset_from_core >> 2;
|
||||
size = DOVI_CORE1_SIZE - offset;
|
||||
} else if (dovi_core->id == 2) {
|
||||
core_data = (u32 *)&dovi_reg_data->core2;
|
||||
offset = dovi_core_data->srange_offset_from_core >> 2;
|
||||
size = DOVI_CORE2_SIZE - offset;
|
||||
size -= 2; /* core2 last 2 word is reserved */
|
||||
} else if (dovi_core->id == 3) {
|
||||
core_data = (u32 *)&dovi_reg_data->core3;
|
||||
offset = dovi_core_data->srange_offset_from_core >> 2;
|
||||
size = DOVI_CORE3_SIZE - offset;
|
||||
}
|
||||
|
||||
if (!core_data)
|
||||
continue;
|
||||
|
||||
VOP_MODULE_SET(vop2, dovi_core, metadata_program_st, 1);
|
||||
vop2_writel(vop2, dovi_core_data->ctrl_offset, core_data[1]);
|
||||
/* write regs start from SRANGE_REGISTER */
|
||||
core_data += offset;
|
||||
for (j = 0; j < size; j++)
|
||||
vop2_writel(vop2, dovi_core_data->srange_offset + (j << 2), *(core_data++));
|
||||
VOP_MODULE_SET(vop2, dovi_core, metadata_program_end, 1);
|
||||
|
||||
if (dovi_core->id == 2) {
|
||||
if (dovi_reg_data->input_mode != HDR_DOVI)
|
||||
VOP_MODULE_SET(vop2, dovi_core, dly_en, 1);
|
||||
else
|
||||
VOP_MODULE_SET(vop2, dovi_core, dly_en, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void vop2_dovi_mode_config(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
|
||||
u16 hsync_len = (adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start) >> 1;
|
||||
u16 hdisplay = (adjusted_mode->crtc_hdisplay) >> 1;
|
||||
u16 hact_st = (adjusted_mode->crtc_htotal - adjusted_mode->crtc_hsync_start) >> 1;
|
||||
u16 hact_end = hact_st + hdisplay;
|
||||
u16 hfp = (adjusted_mode->crtc_hsync_start - adjusted_mode->crtc_hdisplay) >> 1;
|
||||
u16 htotal;
|
||||
|
||||
u16 vdisplay = adjusted_mode->crtc_vdisplay;
|
||||
u16 vtotal = adjusted_mode->crtc_vtotal;
|
||||
u16 vsync_len = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
|
||||
u16 vact_st = adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vsync_start;
|
||||
u16 vact_end = vact_st + vdisplay;
|
||||
u32 val = 0;
|
||||
int dovi_max_delay = vp->dovi_hdr_in ?
|
||||
vop2_data->dovi->dovi_max_delay[0] : vop2_data->dovi->dovi_max_delay[1];
|
||||
|
||||
if (!vop2_is_dovi_mode(vp)) {
|
||||
VOP_MODULE_SET(vop2, vp, dovi_pre_scan_en, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
hact_end = hact_end + dovi_max_delay;
|
||||
val = hact_st << 16 | hact_end;
|
||||
VOP_MODULE_SET(vop2, vp, pre_scan_htiming1, val);
|
||||
|
||||
hfp = hfp >= 20 ? hfp : 20;
|
||||
htotal = hact_end + hfp;
|
||||
val = htotal << 16 | hsync_len;
|
||||
VOP_MODULE_SET(vop2, vp, pre_scan_htiming, val);
|
||||
|
||||
val = vtotal << 16 | vsync_len;
|
||||
VOP_MODULE_SET(vop2, vp, pre_scan_htiming2, val);
|
||||
|
||||
val = vact_st << 16 | vact_end;
|
||||
VOP_MODULE_SET(vop2, vp, pre_scan_htiming3, val);
|
||||
|
||||
VOP_MODULE_SET(vop2, vp, dovi_pre_scan_en, 1);
|
||||
}
|
||||
|
||||
static void vop2_disable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
@@ -5182,7 +5602,9 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
|
||||
if (vp_data->feature & VOP_FEATURE_VIVID_HDR)
|
||||
VOP_MODULE_SET(vop2, vp, hdr_lut_update_en, 0);
|
||||
vop2_dovi_pre_disable(crtc);
|
||||
vop2_disable_all_planes_for_crtc(crtc);
|
||||
vop2_dovi_post_disable(crtc);
|
||||
|
||||
if (vop2->dscs[vcstate->dsc_id].enabled &&
|
||||
vop2->dscs[vcstate->dsc_id].attach_vp_id == vp->id &&
|
||||
@@ -5282,6 +5704,7 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
vcstate->output_type = 0;
|
||||
vp->splice_mode_right = false;
|
||||
vp->loader_protect = false;
|
||||
vp->enabled_win_mask = 0;
|
||||
splice_vp->splice_mode_right = false;
|
||||
memset(&vp->active_tv_state, 0, sizeof(vp->active_tv_state));
|
||||
vop2_unlock(vop2);
|
||||
@@ -6829,6 +7252,11 @@ static int vop2_atomic_plane_set_property(struct drm_plane *plane,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (property == private->dovi_input_type_prop) {
|
||||
vpstate->dovi_input_type = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DRM_ERROR("failed to set vop2 plane property id:%d, name:%s\n",
|
||||
property->base.id, property->name);
|
||||
|
||||
@@ -6881,6 +7309,11 @@ static int vop2_atomic_plane_get_property(struct drm_plane *plane,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (property == private->dovi_input_type_prop) {
|
||||
*val = vpstate->dovi_input_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DRM_ERROR("failed to get vop2 plane property id:%d, name:%s\n",
|
||||
property->base.id, property->name);
|
||||
|
||||
@@ -7326,6 +7759,27 @@ static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *hdr_to_string(int eotf)
|
||||
{
|
||||
switch (eotf) {
|
||||
case HDMI_EOTF_TRADITIONAL_GAMMA_HDR:
|
||||
return "GAMMA HDR";
|
||||
case HDMI_EOTF_SMPTE_ST2084:
|
||||
return "HDR10";
|
||||
case HDMI_EOTF_BT_2100_HLG:
|
||||
return "HLG";
|
||||
case HDMI_EOTF_HDR10PLUS:
|
||||
return "HDR10PLUS";
|
||||
case HDMI_EOTF_HDRVIVID:
|
||||
return "HDRVIVID";
|
||||
case HDMI_EOTF_DOVI:
|
||||
return "DOVI";
|
||||
case HDMI_EOTF_TRADITIONAL_GAMMA_SDR:
|
||||
default:
|
||||
return "SDR";
|
||||
}
|
||||
}
|
||||
|
||||
#define DEBUG_PRINT(args...) \
|
||||
do { \
|
||||
if (s) \
|
||||
@@ -7360,10 +7814,9 @@ static int vop2_plane_info_dump(struct seq_file *s, struct drm_plane *plane)
|
||||
&fb->format->format, rockchip_drm_modifier_to_string(fb->modifier),
|
||||
pstate->pixel_blend_mode, vpstate->global_alpha);
|
||||
DEBUG_PRINT("\tcolor: %s[%d] color-encoding[%s] color-range[%s]\n",
|
||||
vpstate->eotf ? "HDR" : "SDR", vpstate->eotf,
|
||||
hdr_to_string(vpstate->eotf), vpstate->eotf,
|
||||
rockchip_drm_get_color_encoding_name(pstate->color_encoding),
|
||||
rockchip_drm_get_color_range_name(pstate->color_range));
|
||||
|
||||
DEBUG_PRINT("\trotate: xmirror: %d ymirror: %d rotate_90: %d rotate_270: %d\n",
|
||||
vpstate->xmirror_en, vpstate->ymirror_en, vpstate->rotate_90_en,
|
||||
vpstate->rotate_270_en);
|
||||
@@ -7435,7 +7888,7 @@ static int vop2_crtc_debugfs_dump(struct drm_crtc *crtc, struct seq_file *s)
|
||||
DEBUG_PRINT("\toverlay_mode[%d] output_mode[%x] ",
|
||||
state->yuv_overlay, state->output_mode);
|
||||
DEBUG_PRINT("%s[%d] color-encoding[%s] color-range[%s]\n",
|
||||
state->eotf ? "HDR" : "SDR", state->eotf,
|
||||
hdr_to_string(state->eotf), state->eotf,
|
||||
rockchip_drm_get_color_encoding_name(state->color_encoding),
|
||||
rockchip_drm_get_color_range_name(state->color_range));
|
||||
DEBUG_PRINT(" Display mode: %dx%d%s%d\n",
|
||||
@@ -9821,6 +10274,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta
|
||||
}
|
||||
if (is_vop3(vop2))
|
||||
vop3_setup_pipe_dly(vp, NULL);
|
||||
if (vp_data->feature & VOP_FEATURE_DOVI)
|
||||
vop2_dovi_init(crtc);
|
||||
|
||||
vop2_crtc_setup_output_mode(crtc);
|
||||
|
||||
@@ -9964,6 +10419,26 @@ static void vop2_update_post_csc_info(struct vop2_video_port *vp,
|
||||
memset(&vp->csc_info, 0, sizeof(struct post_csc));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check hdr_ext_data switch from valid to NULL or
|
||||
* NULL to valid.
|
||||
* This is used to check a switch from dynamic HDR2SDR
|
||||
* or SDR2HDR output mode switch.
|
||||
*/
|
||||
static bool vop_hdr_ext_data_switch(struct drm_crtc_state *old_state,
|
||||
struct drm_crtc_state *new_state)
|
||||
{
|
||||
struct rockchip_crtc_state *new_vcstate = to_rockchip_crtc_state(new_state);
|
||||
struct rockchip_crtc_state *old_vcstate = to_rockchip_crtc_state(old_state);
|
||||
struct drm_property_blob *new_blob = new_vcstate->hdr_ext_data;
|
||||
struct drm_property_blob *old_blob = old_vcstate->hdr_ext_data;
|
||||
|
||||
if ((!old_blob && new_blob) || (!new_blob && old_blob))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
@@ -9978,6 +10453,7 @@ static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
struct rockchip_crtc_state *new_vcstate = to_rockchip_crtc_state(new_crtc_state);
|
||||
struct rockchip_crtc_state *old_vcstate = to_rockchip_crtc_state(old_crtc_state);
|
||||
struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
|
||||
bool hdr_ext_data_change;
|
||||
|
||||
if (vop2_has_feature(vop2, VOP_FEATURE_SPLICE)) {
|
||||
if (adjusted_mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
|
||||
@@ -10002,6 +10478,11 @@ static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
else
|
||||
vp->acm_state_changed = false;
|
||||
|
||||
hdr_ext_data_change = !vop_hdr_ext_data_switch(old_crtc_state, new_crtc_state) |
|
||||
new_crtc_state->active_changed;
|
||||
if (hdr_ext_data_change)
|
||||
new_crtc_state->mode_changed = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -10235,6 +10716,29 @@ static void vop3_setup_dynamic_hdr(struct vop2_video_port *vp, uint8_t win_phys_
|
||||
}
|
||||
}
|
||||
|
||||
static void vop2_setup_hdr_dovi(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
|
||||
struct dovi_regs *dovi_data;
|
||||
struct hdr_extend *hdr_data;
|
||||
|
||||
if (!vop2_data->dovi->nr_dovi_cores || !vcstate || !vcstate->hdr_ext_data)
|
||||
return;
|
||||
|
||||
hdr_data = (struct hdr_extend *)vcstate->hdr_ext_data->data;
|
||||
if (!hdr_data || hdr_data->hdr_type != HDR_DOVI)
|
||||
return;
|
||||
|
||||
dovi_data = &hdr_data->dovi_data;
|
||||
if (dovi_data->input_mode == HDR_DOVI)
|
||||
vp->dovi_hdr_in = true;
|
||||
else
|
||||
vp->dovi_hdr_in = false;
|
||||
}
|
||||
|
||||
static void vop2_setup_hdr10(struct vop2_video_port *vp, uint8_t win_phys_id)
|
||||
{
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
@@ -10549,7 +11053,7 @@ static void vop2_setup_alpha(struct vop2_video_port *vp,
|
||||
int mixer_id;
|
||||
int phys_id;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
int i, begin_layer = 0;
|
||||
bool bottom_layer_alpha_en = false;
|
||||
u32 dst_global_alpha = 0xff;
|
||||
|
||||
@@ -10590,8 +11094,24 @@ static void vop2_setup_alpha(struct vop2_video_port *vp,
|
||||
vp->hdr10_at_splice_mode && vp->id == 0)
|
||||
mixer_id++;/* fixed path for rk3588: layer1 -> hdr10_1 */
|
||||
|
||||
/*
|
||||
* vp0 begin from mix0, mix0 input is layer0 and layer1, we need to use
|
||||
* layer1 format to config mix0, the layer0 alpha[bottom_layer_alpha_en is true],
|
||||
* will use the following formulas: Cd = Cs + (1 - As) * Cd * Agd to do overlay;
|
||||
* vp1/2/3 layer0 will enter first mix src layer, so we need to init it.
|
||||
*
|
||||
* rk3588 hdr splice mode, vp1 hdr layer will be insert to layer1[vp0],
|
||||
* so we need to ignore layer0 and begin from layer1 to config mix for vp1.
|
||||
*/
|
||||
if (vp->id == 0 || vp->hdr10_at_splice_mode)
|
||||
begin_layer = 1;
|
||||
|
||||
/* dovi core1 base layer and enhance layer no need to do overlay */
|
||||
if (vop2_is_dovi_mode(vp))
|
||||
begin_layer = 2;
|
||||
|
||||
alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
|
||||
for (i = 1; i < vp->nr_layers; i++) {
|
||||
for (i = begin_layer; i < vp->nr_layers; i++) {
|
||||
zpos = &vop2_zpos[i];
|
||||
win = vop2_find_win_by_phys_id(vop2, zpos->win_phys_id);
|
||||
if (win->splice_mode_right)
|
||||
@@ -10609,7 +11129,7 @@ static void vop2_setup_alpha(struct vop2_video_port *vp,
|
||||
pixel_alpha_en = is_alpha_support(fb->format->format);
|
||||
|
||||
alpha_config.src_premulti_en = premulti_en;
|
||||
if (bottom_layer_alpha_en && i == 1) {
|
||||
if (bottom_layer_alpha_en && i == begin_layer && vp->id == 0) {/* Cd = Cs + (1 - As) * Cd * Agd */
|
||||
/**
|
||||
* The data from cluster mix is always premultiplied alpha;
|
||||
* cluster layer or esmart layer[premulti_en = 1]
|
||||
@@ -10638,6 +11158,13 @@ static void vop2_setup_alpha(struct vop2_video_port *vp,
|
||||
}
|
||||
vop2_parse_alpha(&alpha_config, &alpha);
|
||||
|
||||
/*
|
||||
* The first UI enter dovi core2 no need to do alpha blending, but
|
||||
* the alpha value need to transfer to next mix and enter core2.
|
||||
*/
|
||||
if (vop2_is_dovi_mode(vp) && i == begin_layer)
|
||||
alpha.src_color_ctrl.bits.alpha_en = false;
|
||||
|
||||
offset = (mixer_id + i - 1) * 0x10;
|
||||
vop2_writel(vop2, src_color_ctrl_offset + offset, alpha.src_color_ctrl.val);
|
||||
vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val);
|
||||
@@ -10645,7 +11172,7 @@ static void vop2_setup_alpha(struct vop2_video_port *vp,
|
||||
vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
|
||||
}
|
||||
|
||||
if (bottom_layer_alpha_en || vp->hdr_en) {
|
||||
if (bottom_layer_alpha_en || vp->hdr_en || (vop2_is_dovi_mode(vp) && vp->nr_layers > 1)) {
|
||||
/* Transfer pixel alpha to hdr mix */
|
||||
alpha_config.src_premulti_en = premulti_en;
|
||||
alpha_config.dst_premulti_en = true;
|
||||
@@ -10653,6 +11180,16 @@ static void vop2_setup_alpha(struct vop2_video_port *vp,
|
||||
alpha_config.src_glb_alpha_value = 0xff;
|
||||
alpha_config.dst_glb_alpha_value = 0xff;
|
||||
vop2_parse_alpha(&alpha_config, &alpha);
|
||||
if (vop2_is_dovi_mode(vp)) {
|
||||
/* dovi core2 output must be no pre mul alpha
|
||||
* color_mode = ALPHA_SRC_NO_PRE_MUL && factor_mode = ALPHA_ONE is
|
||||
* roughly equal to color_mode = ALPHA_SRC_PRE_MUL && factor_mode = ALPHA_NO_SATURATION,
|
||||
* but the secondary is more correctly.
|
||||
*/
|
||||
alpha.src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL;
|
||||
alpha.src_color_ctrl.bits.factor_mode = ALPHA_SRC_GLOBAL;
|
||||
alpha.src_color_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION;
|
||||
}
|
||||
|
||||
VOP_MODULE_SET(vop2, vp, hdr_src_color_ctrl,
|
||||
alpha.src_color_ctrl.val);
|
||||
@@ -10968,6 +11505,13 @@ static u16 vop2_calc_bg_ovl_and_port_mux(struct vop2_video_port *vp)
|
||||
used_layers += 1;
|
||||
if (vop2->vps[0].hdr10_at_splice_mode && i == 1)
|
||||
used_layers -= 1;
|
||||
/*
|
||||
* At RK3588 dovi mode, layer1 always used by enhance layer,
|
||||
* so the used_layers at least 3 layers, include:
|
||||
* base layer[video], enhance layer[reserved] and UI layer.
|
||||
*/
|
||||
if (vop2_is_dovi_mode(prev_vp) && used_layers < 3)
|
||||
used_layers++;
|
||||
}
|
||||
/*
|
||||
* when a window move from vp0 to vp1, or vp0 to vp2,
|
||||
@@ -11216,6 +11760,12 @@ static void vop2_setup_dly_for_vp(struct vop2_video_port *vp)
|
||||
pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
|
||||
|
||||
VOP_MODULE_SET(vop2, vp, bg_dly, bg_dly);
|
||||
/* Disable bg bottom overlay */
|
||||
if (vop2_is_dovi_mode(vp)) {
|
||||
VOP_MODULE_SET(vop2, vp, dp_line_end_mode, 1);
|
||||
VOP_MODULE_SET(vop2, vp, dp_bg_bottom_disable, 1);
|
||||
}
|
||||
/* will be rewrite at dovi_mode_config when at dovi mode */
|
||||
VOP_MODULE_SET(vop2, vp, pre_scan_htiming, pre_scan_dly);
|
||||
}
|
||||
|
||||
@@ -11249,6 +11799,18 @@ static void vop2_setup_dly_for_window(struct vop2_video_port *vp, const struct v
|
||||
} else if (vp->hdr_in && vp->hdr_out && vpstate->hdr_in) {
|
||||
dly = win->dly[VOP2_DLY_MODE_HIHO_H];
|
||||
dly -= vp->bg_ovl_dly;
|
||||
} else if (vop2_is_dovi_mode(vp)) {
|
||||
if (vp->dovi_hdr_in) {
|
||||
if (vpstate->dovi_input_type)
|
||||
dly = win->dly[VOP2_DLY_MODE_DOVI_IN_CORE1];
|
||||
else
|
||||
dly = win->dly[VOP2_DLY_MODE_DOVI_IN_CORE2];
|
||||
} else {
|
||||
if (vpstate->dovi_input_type)
|
||||
dly = win->dly[VOP2_DLY_MODE_NONDOVI_IN_CORE1];
|
||||
else
|
||||
dly = win->dly[VOP2_DLY_MODE_NONDOVI_IN_CORE2];
|
||||
}
|
||||
} else {
|
||||
dly = win->dly[VOP2_DLY_MODE_DEFAULT];
|
||||
}
|
||||
@@ -11498,6 +12060,33 @@ static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_stat
|
||||
vp->nr_layers = nr_layers;
|
||||
|
||||
sort(vop2_zpos, nr_layers, sizeof(vop2_zpos[0]), vop2_zpos_cmp, NULL);
|
||||
/*
|
||||
* At RK3588 dovi mode, the layer0 and layer1 is used for dovi layer,
|
||||
* layer0 for base layer, layer1 for enhance layer, the enhance layer
|
||||
* is option, but it's always occupy this layer, and the other layer
|
||||
* must be assigned from layer2, so copy the other layers to &vop_zpos[2].
|
||||
*/
|
||||
if (vop2->version == VOP_VERSION_RK3588 &&
|
||||
vop2_is_dovi_mode(vp) && vp->nr_layers > 1) {
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
struct vop2_zpos *vop2_zpos_tmp;
|
||||
int i = 0;
|
||||
|
||||
vop2_zpos_tmp = kmalloc_array(nr_layers - 1, sizeof(struct vop2_zpos), GFP_KERNEL);
|
||||
if (!vop2_zpos_tmp)
|
||||
goto dovi_err;
|
||||
|
||||
/* Insert esmart3 as core1 enhance layer to zpos1 */
|
||||
memcpy(vop2_zpos_tmp, &vop2_zpos[1], (nr_layers - 1) * sizeof(struct vop2_zpos));
|
||||
vp->nr_layers++;
|
||||
vop2_zpos[1].zpos = 1;
|
||||
vop2_zpos[1].win_phys_id = vop2_data->dovi->enhance_layer_phy_id;
|
||||
memcpy(&vop2_zpos[2], vop2_zpos_tmp, (nr_layers - 1) * sizeof(struct vop2_zpos));
|
||||
for (i = 0; i < nr_layers - 1; i++)
|
||||
vop2_zpos[2 + i].zpos = 2 + i;
|
||||
|
||||
kfree(vop2_zpos_tmp);
|
||||
}
|
||||
|
||||
if (!vp->hdr10_at_splice_mode) {
|
||||
if (is_vop3(vop2)) {
|
||||
@@ -11514,7 +12103,10 @@ static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_stat
|
||||
vop3_setup_alpha(vp, vop2_zpos);
|
||||
vop3_setup_pipe_dly(vp, vop2_zpos);
|
||||
} else {
|
||||
vop2_setup_hdr10(vp, vop2_zpos[0].win_phys_id);
|
||||
if (!vop2_is_dovi_mode(vp))
|
||||
vop2_setup_hdr10(vp, vop2_zpos[0].win_phys_id);
|
||||
else
|
||||
vop2_setup_hdr_dovi(crtc);
|
||||
vop2_setup_alpha(vp, vop2_zpos);
|
||||
vop2_setup_dly_for_vp(vp);
|
||||
vop2_setup_dly_for_window(vp, vop2_zpos);
|
||||
@@ -11529,7 +12121,8 @@ static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_stat
|
||||
vop2_setup_port_mux(vp);
|
||||
if (!vp->hdr10_at_splice_mode)
|
||||
vop2_setup_layer_mixer_for_vp(splice_vp, vop2_zpos_splice);
|
||||
vop2_setup_hdr10(splice_vp, vop2_zpos_splice[0].win_phys_id);
|
||||
if (!vop2_is_dovi_mode(vp))
|
||||
vop2_setup_hdr10(splice_vp, vop2_zpos_splice[0].win_phys_id);
|
||||
vop2_setup_alpha(splice_vp, vop2_zpos_splice);
|
||||
vop2_setup_dly_for_vp(splice_vp);
|
||||
vop2_setup_dly_for_window(splice_vp, vop2_zpos_splice);
|
||||
@@ -11570,6 +12163,7 @@ static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_stat
|
||||
}
|
||||
}
|
||||
|
||||
dovi_err:
|
||||
if (vcstate->splice_mode)
|
||||
kfree(vop2_zpos_splice);
|
||||
out:
|
||||
@@ -11971,6 +12565,11 @@ static void vop2_cfg_update(struct drm_crtc *crtc,
|
||||
if (vp_data->feature & VOP_FEATURE_OVERSCAN)
|
||||
vop2_post_config(crtc);
|
||||
|
||||
if (vop2_is_dovi_mode(vp) && vp->enabled_win_mask) {
|
||||
vop2_dovi_mode_config(crtc);
|
||||
vop2_load_dovi_coe_table(crtc);
|
||||
}
|
||||
|
||||
spin_unlock(&vop2->reg_lock);
|
||||
|
||||
if (vp_data->feature & VOP_FEATURE_POST_CSC) {
|
||||
@@ -12069,7 +12668,9 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_stat
|
||||
struct vop2_wb *wb = &vop2->wb;
|
||||
struct drm_writeback_connector *wb_conn = &wb->conn;
|
||||
struct drm_connector_state *conn_state = wb_conn->base.state;
|
||||
bool wb_mode = conn_state && conn_state->writeback_job && conn_state->writeback_job->fb;
|
||||
bool wb_oneframe_mode = VOP_MODULE_GET(vop2, wb, one_frame_mode);
|
||||
bool dovi_mode = vop2_is_dovi_mode(vp) && vp->enabled_win_mask;
|
||||
|
||||
#if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
|
||||
if (vp->rockchip_crtc.vop_dump_status == DUMP_KEEP ||
|
||||
@@ -12079,7 +12680,13 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_stat
|
||||
}
|
||||
#endif
|
||||
|
||||
if (conn_state && conn_state->writeback_job && conn_state->writeback_job->fb && !wb_oneframe_mode) {
|
||||
if ((wb_mode && !wb_oneframe_mode) || dovi_mode) {
|
||||
/**
|
||||
* Avoid commit time close to vsync when enable writeback or dovi mode.
|
||||
* For writeback may be lost writeback frame when close to vsync,
|
||||
* For dovi mode may be appear dovi config and plane config take effect
|
||||
* at different frame.
|
||||
*/
|
||||
u16 vtotal = VOP_MODULE_GET(vop2, vp, dsp_vtotal);
|
||||
u32 current_line = vop2_read_vcnt(vp);
|
||||
|
||||
@@ -12156,6 +12763,7 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_stat
|
||||
if (vp->mcu_timing.mcu_pix_total)
|
||||
VOP_MODULE_SET(vop2, vp, mcu_hold_mode, 0);
|
||||
|
||||
vp->rockchip_crtc.frame_count++;
|
||||
spin_unlock_irqrestore(&vop2->irq_lock, flags);
|
||||
|
||||
/*
|
||||
@@ -12730,6 +13338,35 @@ static void vop2_wb_handler(struct vop2_video_port *vp)
|
||||
spin_unlock_irqrestore(&wb->job_lock, flags);
|
||||
}
|
||||
|
||||
static void vop2_dovi_hanle_irqs(struct drm_crtc *crtc, uint32_t active_irqs)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
struct vop2_dovi_core *dovi_core;
|
||||
u32 val = 0;
|
||||
|
||||
if (active_irqs & DOLBY_CORE1_INTR) {
|
||||
dovi_core = &vop2->dovi_cores[0];
|
||||
val = VOP_MODULE_GET(vop2, dovi_core, interrupt_raw);
|
||||
VOP_MODULE_SET(vop2, dovi_core, interrupt_raw, val);
|
||||
drm_dbg(vop2, "dovi core1 irq: 0x%x\n", val);
|
||||
}
|
||||
|
||||
if (active_irqs & DOLBY_CORE2_INTR) {
|
||||
dovi_core = &vop2->dovi_cores[1];
|
||||
val = VOP_MODULE_GET(vop2, dovi_core, interrupt_raw);
|
||||
VOP_MODULE_SET(vop2, dovi_core, interrupt_raw, val);
|
||||
drm_dbg(vop2, "dovi core2 irq: 0x%x\n", val);
|
||||
}
|
||||
|
||||
if (active_irqs & DOLBY_CORE3_INTR) {
|
||||
dovi_core = &vop2->dovi_cores[2];
|
||||
val = VOP_MODULE_GET(vop2, dovi_core, interrupt_raw);
|
||||
VOP_MODULE_SET(vop2, dovi_core, interrupt_raw, val);
|
||||
drm_dbg(vop2, "dovi core3 irq: 0x%x\n", val);
|
||||
}
|
||||
}
|
||||
|
||||
static void vop2_dsc_isr(struct vop2 *vop2)
|
||||
{
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
@@ -12859,6 +13496,12 @@ static irqreturn_t vop2_isr(int irq, void *data)
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (active_irqs & (DOLBY_CORE1_INTR | DOLBY_CORE2_INTR | DOLBY_CORE3_INTR)) {
|
||||
vop2_dovi_hanle_irqs(crtc, active_irqs);
|
||||
active_irqs &= ~(DOLBY_CORE1_INTR | DOLBY_CORE2_INTR | DOLBY_CORE3_INTR);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (active_irqs & POST_BUF_EMPTY_INTR) {
|
||||
vop2_handle_post_buf_empty(crtc);
|
||||
DRM_DEV_ERROR_RATELIMITED(vop2->dev, "POST_BUF_EMPTY irq err at vp%d\n", vp->id);
|
||||
@@ -13212,6 +13855,9 @@ static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, unsigned lon
|
||||
else
|
||||
drm_object_attach_property(&win->base.base, private->share_id_prop,
|
||||
win->base.base.id);
|
||||
|
||||
drm_object_attach_property(&win->base.base, private->dovi_input_type_prop, 0);
|
||||
|
||||
if (win->supported_rotations)
|
||||
drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0,
|
||||
DRM_MODE_ROTATE_0 | win->supported_rotations);
|
||||
@@ -13412,7 +14058,7 @@ static int vop2_crtc_create_feature_property(struct vop2 *vop2, struct drm_crtc
|
||||
static const struct drm_prop_enum_list props[] = {
|
||||
{ ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE, "ALPHA_SCALE" },
|
||||
{ ROCKCHIP_DRM_CRTC_FEATURE_HDR10, "HDR10" },
|
||||
{ ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR, "NEXT_HDR" },
|
||||
{ ROCKCHIP_DRM_CRTC_FEATURE_DOVI, "DOVI" },
|
||||
{ ROCKCHIP_DRM_CRTC_FEATURE_VIVID_HDR, "VIVID_HDR" },
|
||||
};
|
||||
|
||||
@@ -13420,8 +14066,8 @@ static int vop2_crtc_create_feature_property(struct vop2 *vop2, struct drm_crtc
|
||||
feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE);
|
||||
if (vp_data->feature & VOP_FEATURE_HDR10)
|
||||
feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_HDR10);
|
||||
if (vp_data->feature & VOP_FEATURE_NEXT_HDR)
|
||||
feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR);
|
||||
if (vp_data->feature & VOP_FEATURE_DOVI)
|
||||
feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_DOVI);
|
||||
if (vp_data->feature & VOP_FEATURE_VIVID_HDR)
|
||||
feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_VIVID_HDR);
|
||||
|
||||
@@ -13817,7 +14463,7 @@ static int vop2_create_crtc(struct vop2 *vop2, uint8_t enabled_vp_mask)
|
||||
"Failed to init %s with SR helpers %d, ignoring\n",
|
||||
crtc->name, ret);
|
||||
|
||||
if (vp_data->feature & VOP_FEATURE_VIVID_HDR)
|
||||
if (vp_data->feature & (VOP_FEATURE_VIVID_HDR | VOP_FEATURE_DOVI))
|
||||
vop2_crtc_create_hdr_property(vop2, crtc);
|
||||
if (vp_data->feature & VOP_FEATURE_POST_ACM)
|
||||
vop2_crtc_create_post_acm_property(vop2, crtc);
|
||||
@@ -13950,6 +14596,22 @@ static int vop2_pd_data_init(struct vop2 *vop2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vop2_dovi_data_init(struct vop2 *vop2)
|
||||
{
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
const struct vop2_dovi_core_data *dovi_core_data;
|
||||
struct vop2_dovi_core *dovi_core;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vop2_data->dovi->nr_dovi_cores; i++) {
|
||||
dovi_core = &vop2->dovi_cores[i];
|
||||
dovi_core_data = &vop2_data->dovi->dovi_core_data[i];
|
||||
dovi_core->id = dovi_core_data->id;
|
||||
dovi_core->regs = dovi_core_data->regs;
|
||||
dovi_core->vop2 = vop2;
|
||||
}
|
||||
}
|
||||
|
||||
static void vop2_dsc_data_init(struct vop2 *vop2)
|
||||
{
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
@@ -14668,6 +15330,24 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
|
||||
return PTR_ERR(vop2->pclk);
|
||||
}
|
||||
|
||||
vop2->aclk_dovi = devm_clk_get_optional(vop2->dev, "aclk_dovi");
|
||||
if (IS_ERR(vop2->aclk_dovi)) {
|
||||
DRM_DEV_ERROR(vop2->dev, "failed to get aclk dovi source\n");
|
||||
return PTR_ERR(vop2->aclk_dovi);
|
||||
}
|
||||
|
||||
vop2->aclk_div2_src = devm_clk_get_optional(vop2->dev, "aclk_vop_div2_src");
|
||||
if (IS_ERR(vop2->aclk_div2_src)) {
|
||||
DRM_DEV_ERROR(vop2->dev, "failed to get aclk div2 src\n");
|
||||
return PTR_ERR(vop2->aclk_div2_src);
|
||||
}
|
||||
|
||||
vop2->aclk_root = devm_clk_get_optional(vop2->dev, "aclk_vop_root");
|
||||
if (IS_ERR(vop2->aclk_root)) {
|
||||
DRM_DEV_ERROR(vop2->dev, "failed to get aclk vop root\n");
|
||||
return PTR_ERR(vop2->aclk_root);
|
||||
}
|
||||
|
||||
vop2->ahb_rst = devm_reset_control_get_optional(vop2->dev, "ahb");
|
||||
if (IS_ERR(vop2->ahb_rst)) {
|
||||
DRM_DEV_ERROR(vop2->dev, "failed to get ahb reset\n");
|
||||
@@ -14776,6 +15456,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vop2_dovi_data_init(vop2);
|
||||
vop2_dsc_data_init(vop2);
|
||||
|
||||
registered_num_crtcs = vop2_create_crtc(vop2, enabled_vp_mask);
|
||||
|
||||
@@ -680,6 +680,10 @@ static const int rk3568_vop_intrs[] = {
|
||||
POST_BUF_EMPTY_INTR,
|
||||
FS_FIELD_INTR,
|
||||
DSP_HOLD_VALID_INTR,
|
||||
0, 0, 0, 0, 0,
|
||||
DOLBY_CORE1_INTR,
|
||||
DOLBY_CORE2_INTR,
|
||||
DOLBY_CORE3_INTR,
|
||||
};
|
||||
|
||||
static const struct vop_intr rk3568_vp0_intr = {
|
||||
@@ -722,6 +726,88 @@ static const struct vop_intr rk3588_vp3_intr = {
|
||||
.clear = VOP_REG_MASK(RK3588_VP3_INT_CLR, 0xffff, 0),
|
||||
};
|
||||
|
||||
static const struct vop2_dovi_regs rk3588_vop_dovi_core1_regs = {
|
||||
.enable = VOP_REG(RK3568_OVL_CTRL, 0x1, 8),
|
||||
.interrupt_raw = VOP_REG(RK3588_DOLBY_CORE1_INTR_RAW_REG, 0xf, 0),
|
||||
.interrupt_enable = VOP_REG(RK3588_DOLBY_CORE1_INTR_ENABLE_REG, 0xf, 0),
|
||||
.metadata_program_st = VOP_REG(RK3588_DOLBY_CORE1_METADATA_PROGRAM_ST, 0x1, 0),
|
||||
.metadata_program_end = VOP_REG(RK3588_DOLBY_CORE1_METADATA_PROGRAM_END, 0x1, 0),
|
||||
.metadata_copy_finish = VOP_REG(RK3588_DOLBY_CORE1_INTR_RAW_REG, 0x1, 2),
|
||||
|
||||
.bypass_composer = VOP_REG(RK3588_DOLBY_CORE1_CONTROL_REG, 0x1, 0),
|
||||
.bypass_csc = VOP_REG(RK3588_DOLBY_CORE1_CONTROL_REG, 0x1, 1),
|
||||
.bypass_cvm = VOP_REG(RK3588_DOLBY_CORE1_CONTROL_REG, 0x1, 2),
|
||||
.operating_mode = VOP_REG(RK3588_DOLBY_CORE1_CONTROL_REG, 0x1, 3),
|
||||
.pixel_rate = VOP_REG(RK3588_DOLBY_CORE1_CONTROL_REG, 0xf, 4),
|
||||
|
||||
.lut_update = VOP_REG(RK3568_OVL_CTRL, 0x1, 11),
|
||||
.lut_mst = VOP_REG(RK3588_DOLBY_LUT_MST, 0xffffffff, 0),
|
||||
};
|
||||
|
||||
static const struct vop2_dovi_regs rk3588_vop_dovi_core2_regs = {
|
||||
.enable = VOP_REG(RK3568_OVL_CTRL, 0x1, 9),
|
||||
.interrupt_raw = VOP_REG(RK3588_DOLBY_CORE2_INTR_RAW_REG, 0xf, 0),
|
||||
.interrupt_enable = VOP_REG(RK3588_DOLBY_CORE2_INTR_ENABLE_REG, 0xf, 0),
|
||||
.metadata_program_st = VOP_REG(RK3588_DOLBY_CORE2_METADATA_PROGRAM_ST, 0x1, 0),
|
||||
.metadata_program_end = VOP_REG(RK3588_DOLBY_CORE2_METADATA_PROGRAM_END, 0x1, 0),
|
||||
.metadata_copy_finish = VOP_REG(RK3588_DOLBY_CORE2_INTR_RAW_REG, 0x1, 2),
|
||||
|
||||
.bypass_cvm = VOP_REG(RK3588_DOLBY_CORE2_CONTROL_REG, 0x1, 0),
|
||||
.yuv2rgb_en = VOP_REG(RK3588_DOLBY_CORE2_CONTROL_REG, 0x1, 1),
|
||||
.yuv422to444_en = VOP_REG(RK3588_DOLBY_CORE2_CONTROL_REG, 0x1, 2),
|
||||
.yuv_swap = VOP_REG(RK3568_OVL_CTRL, 0x1, 6),
|
||||
.yuv422_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 7),
|
||||
|
||||
.lut_update = VOP_REG(RK3568_OVL_CTRL, 0x1, 12),
|
||||
.lut_mst = VOP_REG(RK3568_HDR_LUT_MST, 0xffffffff, 0),
|
||||
|
||||
.dly_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 13),
|
||||
};
|
||||
|
||||
static const struct vop2_dovi_regs rk3588_vop_dovi_core3_regs = {
|
||||
.enable = VOP_REG(RK3568_OVL_CTRL, 0x1, 10),
|
||||
.interrupt_raw = VOP_REG(RK3588_DOLBY_CORE3_INTR_RAW_REG, 0xf, 0),
|
||||
.interrupt_enable = VOP_REG(RK3588_DOLBY_CORE3_INTR_ENABLE_REG, 0xf, 0),
|
||||
.metadata_program_st = VOP_REG(RK3588_DOLBY_CORE3_METADATA_PROGRAM_ST, 0x1, 0),
|
||||
.metadata_program_end = VOP_REG(RK3588_DOLBY_CORE3_METADATA_PROGRAM_END, 0x1, 0),
|
||||
.metadata_copy_finish = VOP_REG(RK3588_DOLBY_CORE3_INTR_RAW_REG, 0x1, 2),
|
||||
|
||||
.output_mode = VOP_REG(RK3588_DOLBY_CORE3_CONTROL_REG, 0xf, 0),
|
||||
};
|
||||
|
||||
static const struct vop2_dovi_core_data rk3588_vop_dovi_core_data[3] = {
|
||||
{
|
||||
.id = 1,
|
||||
.ctrl_offset = RK3588_DOLBY_CORE1_CONTROL_REG,
|
||||
.srange_offset = RK3588_DOLBY_CORE1_SRANGE_REG,
|
||||
.srange_offset_from_core = 0x18,
|
||||
.regs = &rk3588_vop_dovi_core1_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = 2,
|
||||
.ctrl_offset = RK3588_DOLBY_CORE2_CONTROL_REG,
|
||||
.srange_offset = RK3588_DOLBY_CORE2_SRANGE_REG,
|
||||
.srange_offset_from_core = 0x18,
|
||||
.regs = &rk3588_vop_dovi_core2_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = 3,
|
||||
.ctrl_offset = RK3588_DOLBY_CORE3_CONTROL_REG,
|
||||
.srange_offset = RK3588_DOLBY_CORE3_SRANGE_REG,
|
||||
.srange_offset_from_core = 0x18,
|
||||
.regs = &rk3588_vop_dovi_core3_regs,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct vop2_dovi_data rk3588_vop_dovi_data = {
|
||||
.nr_dovi_cores = ROCKCHIP_MAX_DOVI_CORE,
|
||||
.dovi_max_delay = { 54, 24 },
|
||||
.enhance_layer_phy_id = ROCKCHIP_VOP2_ESMART3,
|
||||
.dovi_core_data = rk3588_vop_dovi_core_data,
|
||||
};
|
||||
|
||||
static const struct vop2_dsc_regs rk3588_vop_dsc_8k_regs = {
|
||||
/* DSC SYS CTRL */
|
||||
.dsc_port_sel = VOP_REG(RK3588_DSC_8K_SYS_CTRL, 0x3, 0),
|
||||
@@ -1863,11 +1949,13 @@ static const struct vop2_video_port_regs rk3588_vop_vp0_regs = {
|
||||
.dclk_core_div = VOP_REG(RK3568_VP0_CLK_CTRL, 0x3, 0),
|
||||
.dclk_out_div = VOP_REG(RK3568_VP0_CLK_CTRL, 0x3, 2),
|
||||
.pre_scan_htiming = VOP_REG(RK3568_VP0_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
|
||||
.dovi_pre_scan_en = VOP_REG(RK3568_VP0_PRE_SCAN_HTIMING, 0x1, 15),
|
||||
.pre_scan_htiming1 = VOP_REG(RK3588_VP0_PRE_SCAN_HTIMING1, 0x1fff1fff, 0),
|
||||
.pre_scan_htiming2 = VOP_REG(RK3588_VP0_PRE_SCAN_HTIMING2, 0x1fff1fff, 0),
|
||||
.pre_scan_htiming3 = VOP_REG(RK3588_VP0_PRE_SCAN_HTIMING3, 0x1fff1fff, 0),
|
||||
.dp_line_end_mode = VOP_REG(RK3568_VP0_BG_MIX_CTRL, 0x1, 4),
|
||||
.dp_bg_bottom_disable = VOP_REG(RK3568_VP0_BG_MIX_CTRL, 0x1, 5),
|
||||
.bg_dly = VOP_REG(RK3568_VP0_BG_MIX_CTRL, 0xff, 24),
|
||||
.hpost_st_end = VOP_REG(RK3568_VP0_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
|
||||
.vpost_st_end = VOP_REG(RK3568_VP0_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
|
||||
.post_scl_factor = VOP_REG(RK3568_VP0_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
|
||||
.post_scl_ctrl = VOP_REG(RK3568_VP0_POST_SCL_CTRL, 0x3, 0),
|
||||
.htotal_pw = VOP_REG(RK3568_VP0_DSP_HTOTAL_HS_END, 0xffffffff, 0),
|
||||
.hact_st_end = VOP_REG(RK3568_VP0_DSP_HACT_ST_END, 0xffffffff, 0),
|
||||
.dsp_vtotal = VOP_REG(RK3568_VP0_DSP_VTOTAL_VS_END, 0x1fff, 16),
|
||||
@@ -1965,10 +2053,6 @@ static const struct vop2_video_port_regs rk3588_vop_vp1_regs = {
|
||||
.dclk_out_div = VOP_REG(RK3568_VP1_CLK_CTRL, 0x3, 2),
|
||||
.pre_scan_htiming = VOP_REG(RK3568_VP1_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
|
||||
.bg_dly = VOP_REG(RK3568_VP1_BG_MIX_CTRL, 0xff, 24),
|
||||
.hpost_st_end = VOP_REG(RK3568_VP1_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
|
||||
.vpost_st_end = VOP_REG(RK3568_VP1_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
|
||||
.post_scl_factor = VOP_REG(RK3568_VP1_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
|
||||
.post_scl_ctrl = VOP_REG(RK3568_VP1_POST_SCL_CTRL, 0x3, 0),
|
||||
.htotal_pw = VOP_REG(RK3568_VP1_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
|
||||
.hact_st_end = VOP_REG(RK3568_VP1_DSP_HACT_ST_END, 0x1fff1fff, 0),
|
||||
.dsp_vtotal = VOP_REG(RK3568_VP1_DSP_VTOTAL_VS_END, 0x1fff, 16),
|
||||
@@ -2062,10 +2146,6 @@ static const struct vop2_video_port_regs rk3588_vop_vp2_regs = {
|
||||
.dclk_out_div = VOP_REG(RK3568_VP2_CLK_CTRL, 0x3, 2),
|
||||
.pre_scan_htiming = VOP_REG(RK3568_VP2_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
|
||||
.bg_dly = VOP_REG(RK3568_VP2_BG_MIX_CTRL, 0xff, 24),
|
||||
.hpost_st_end = VOP_REG(RK3568_VP2_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
|
||||
.vpost_st_end = VOP_REG(RK3568_VP2_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
|
||||
.post_scl_factor = VOP_REG(RK3568_VP2_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
|
||||
.post_scl_ctrl = VOP_REG(RK3568_VP2_POST_SCL_CTRL, 0x3, 0),
|
||||
.htotal_pw = VOP_REG(RK3568_VP2_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
|
||||
.hact_st_end = VOP_REG(RK3568_VP2_DSP_HACT_ST_END, 0x1fff1fff, 0),
|
||||
.dsp_vtotal = VOP_REG(RK3568_VP2_DSP_VTOTAL_VS_END, 0x1fff, 16),
|
||||
@@ -2129,10 +2209,6 @@ static const struct vop2_video_port_regs rk3588_vop_vp3_regs = {
|
||||
.dclk_out_div = VOP_REG(RK3568_VP3_CLK_CTRL, 0x3, 2),
|
||||
.pre_scan_htiming = VOP_REG(RK3588_VP3_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
|
||||
.bg_dly = VOP_REG(RK3588_VP3_BG_MIX_CTRL, 0xff, 24),
|
||||
.hpost_st_end = VOP_REG(RK3588_VP3_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
|
||||
.vpost_st_end = VOP_REG(RK3588_VP3_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
|
||||
.post_scl_factor = VOP_REG(RK3588_VP3_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
|
||||
.post_scl_ctrl = VOP_REG(RK3588_VP3_POST_SCL_CTRL, 0x3, 0),
|
||||
.htotal_pw = VOP_REG(RK3588_VP3_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
|
||||
.hact_st_end = VOP_REG(RK3588_VP3_DSP_HACT_ST_END, 0x1fff1fff, 0),
|
||||
.dsp_vtotal = VOP_REG(RK3588_VP3_DSP_VTOTAL_VS_END, 0x1fff, 16),
|
||||
@@ -2174,7 +2250,7 @@ static const struct vop2_video_port_data rk3588_vop_video_ports[] = {
|
||||
.lut_dma_rid = 0xd,
|
||||
.soc_id = { 0x3588, 0x3588 },
|
||||
.feature = VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_ALPHA_SCALE |
|
||||
VOP_FEATURE_HDR10 | VOP_FEATURE_NEXT_HDR,
|
||||
VOP_FEATURE_HDR10 | VOP_FEATURE_DOVI,
|
||||
.gamma_lut_len = 1024,
|
||||
.cubic_lut_len = 729, /* 9x9x9 */
|
||||
.dclk_max = 2400000000,
|
||||
@@ -4203,7 +4279,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3),
|
||||
.max_upscale_factor = 4,
|
||||
.max_downscale_factor = 4,
|
||||
.dly = { 4, 26, 29 },
|
||||
.dly = { 4, 26, 29, 4, 35, 3, 5 },
|
||||
.type = DRM_PLANE_TYPE_OVERLAY,
|
||||
.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | WIN_FEATURE_SPLICE_LEFT,
|
||||
},
|
||||
@@ -4257,7 +4333,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3),
|
||||
.max_upscale_factor = 4,
|
||||
.max_downscale_factor = 4,
|
||||
.dly = { 4, 26, 29 },
|
||||
.dly = { 4, 26, 29, 4, 35, 3, 5 },
|
||||
.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN,
|
||||
},
|
||||
|
||||
@@ -4311,7 +4387,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3),
|
||||
.max_upscale_factor = 4,
|
||||
.max_downscale_factor = 4,
|
||||
.dly = { 4, 26, 29 },
|
||||
.dly = { 4, 26, 29, 4, 35, 3, 5 },
|
||||
.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | WIN_FEATURE_SPLICE_LEFT,
|
||||
},
|
||||
|
||||
@@ -4364,7 +4440,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3),
|
||||
.max_upscale_factor = 4,
|
||||
.max_downscale_factor = 4,
|
||||
.dly = { 4, 26, 29 },
|
||||
.dly = { 4, 26, 29, 4, 35, 3, 5 },
|
||||
.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN,
|
||||
},
|
||||
|
||||
@@ -4418,7 +4494,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3),
|
||||
.max_upscale_factor = 8,
|
||||
.max_downscale_factor = 8,
|
||||
.dly = { 23, 45, 48 },
|
||||
.dly = { 23, 45, 48, 23, 54, 22, 24 },
|
||||
.feature = WIN_FEATURE_SPLICE_LEFT | WIN_FEATURE_MULTI_AREA,
|
||||
},
|
||||
|
||||
@@ -4448,7 +4524,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3),
|
||||
.max_upscale_factor = 8,
|
||||
.max_downscale_factor = 8,
|
||||
.dly = { 23, 45, 48 },
|
||||
.dly = { 23, 45, 48, 23, 54, 22, 24 },
|
||||
.feature = WIN_FEATURE_SPLICE_LEFT | WIN_FEATURE_MULTI_AREA,
|
||||
},
|
||||
|
||||
@@ -4477,7 +4553,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3),
|
||||
.max_upscale_factor = 8,
|
||||
.max_downscale_factor = 8,
|
||||
.dly = { 23, 45, 48 },
|
||||
.dly = { 23, 45, 48, 23, 54, 22, 24 },
|
||||
.feature = WIN_FEATURE_MULTI_AREA,
|
||||
},
|
||||
|
||||
@@ -4506,7 +4582,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3),
|
||||
.max_upscale_factor = 8,
|
||||
.max_downscale_factor = 8,
|
||||
.dly = { 23, 45, 48 },
|
||||
.dly = { 23, 45, 48, 23, 54, 22, 24 },
|
||||
.feature = WIN_FEATURE_MULTI_AREA,
|
||||
},
|
||||
};
|
||||
@@ -4801,6 +4877,9 @@ static const struct vop2_ctrl rk3588_vop_ctrl = {
|
||||
.wb_dma_finish_and_en = VOP_REG(RK3588_SYS_VAR_FREQ_CTRL, 0x1, 3),
|
||||
.ovl_cfg_done_port = VOP_REG(RK3568_OVL_CTRL, 0x3, 30),
|
||||
.ovl_port_mux_cfg_done_imd = VOP_REG(RK3568_OVL_CTRL, 0x1, 28),
|
||||
.dovi_core3_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 10),
|
||||
.dovi_core2_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 9),
|
||||
.dovi_core1_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 8),
|
||||
.ovl_port_mux_cfg = VOP_REG(RK3568_OVL_PORT_SEL, 0xffff, 0),
|
||||
.if_ctrl_cfg_done_imd = VOP_REG(RK3568_DSP_IF_POL, 0x1, 28),
|
||||
.version = VOP_REG(RK3568_VERSION_INFO, 0xffff, 16),
|
||||
@@ -5243,6 +5322,7 @@ static const struct vop2_data rk3588_vop = {
|
||||
.vo1_grf = &rk3588_vo1_grf_ctrl,
|
||||
.axi_intr = rk3568_vop_axi_intr,
|
||||
.nr_axi_intr = ARRAY_SIZE(rk3568_vop_axi_intr),
|
||||
.dovi = &rk3588_vop_dovi_data,
|
||||
.dsc = rk3588_vop_dsc_data,
|
||||
.dsc_error_ecw = dsc_ecw,
|
||||
.dsc_error_buffer_flow = dsc_buffer_flow,
|
||||
|
||||
@@ -1142,6 +1142,9 @@
|
||||
#define RK3576_VP0_POST_CRC 0xC28
|
||||
#define RK3568_VP0_DSP_BG 0xC2C
|
||||
#define RK3568_VP0_PRE_SCAN_HTIMING 0xC30
|
||||
#define RK3588_VP0_PRE_SCAN_HTIMING1 0xC34
|
||||
#define RK3588_VP0_PRE_SCAN_HTIMING2 0xC38
|
||||
#define RK3588_VP0_PRE_SCAN_HTIMING3 0xC3c
|
||||
#define RK3568_VP0_POST_DSP_HACT_INFO 0xC34
|
||||
#define RK3568_VP0_POST_DSP_VACT_INFO 0xC38
|
||||
#define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C
|
||||
@@ -1326,6 +1329,7 @@
|
||||
#define RK3568_OVL_CTRL 0x600
|
||||
#define RK3568_OVL_LAYER_SEL 0x604
|
||||
#define RK3568_OVL_PORT_SEL 0x608
|
||||
#define RK3588_DOLBY_LUT_MST 0x60c
|
||||
#define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610
|
||||
#define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614
|
||||
#define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618
|
||||
@@ -1781,6 +1785,28 @@
|
||||
#define RK3568_HDR_OETF_DX_POW1 0x2200
|
||||
#define RK3568_HDR_OETF_XN1 0x2300
|
||||
|
||||
/* DOLBY register definition */
|
||||
#define RK3588_DOLBY_CORE1_CONTROL_REG 0x3004
|
||||
#define RK3588_DOLBY_CORE1_METADATA_PROGRAM_ST 0x3008
|
||||
#define RK3588_DOLBY_CORE1_METADATA_PROGRAM_END 0x300C
|
||||
#define RK3588_DOLBY_CORE1_INTR_RAW_REG 0x3010
|
||||
#define RK3588_DOLBY_CORE1_INTR_ENABLE_REG 0x3014
|
||||
#define RK3588_DOLBY_CORE1_SRANGE_REG 0x3018
|
||||
|
||||
#define RK3588_DOLBY_CORE2_CONTROL_REG 0x3404
|
||||
#define RK3588_DOLBY_CORE2_METADATA_PROGRAM_ST 0x3408
|
||||
#define RK3588_DOLBY_CORE2_METADATA_PROGRAM_END 0x340C
|
||||
#define RK3588_DOLBY_CORE2_INTR_RAW_REG 0x3410
|
||||
#define RK3588_DOLBY_CORE2_INTR_ENABLE_REG 0x3414
|
||||
#define RK3588_DOLBY_CORE2_SRANGE_REG 0x3418
|
||||
|
||||
#define RK3588_DOLBY_CORE3_CONTROL_REG 0x3504
|
||||
#define RK3588_DOLBY_CORE3_METADATA_PROGRAM_ST 0x3508
|
||||
#define RK3588_DOLBY_CORE3_METADATA_PROGRAM_END 0x350C
|
||||
#define RK3588_DOLBY_CORE3_INTR_RAW_REG 0x3510
|
||||
#define RK3588_DOLBY_CORE3_INTR_ENABLE_REG 0x3514
|
||||
#define RK3588_DOLBY_CORE3_SRANGE_REG 0x3518
|
||||
|
||||
/* DSC register definition */
|
||||
#define RK3588_DSC_8K_PPS0_3 0x4000
|
||||
#define RK3588_DSC_8K_CTRL0 0x40A0
|
||||
|
||||
@@ -90,7 +90,6 @@ enum drm_rockchip_gem_cpu_acquire_type {
|
||||
enum rockchip_crtc_feture {
|
||||
ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE,
|
||||
ROCKCHIP_DRM_CRTC_FEATURE_HDR10,
|
||||
ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR,
|
||||
ROCKCHIP_DRM_CRTC_FEATURE_DOVI,
|
||||
ROCKCHIP_DRM_CRTC_FEATURE_VIVID_HDR,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user