mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
drm/rockchip: vop2: update DSC config for HDMI 8kp60 RGB output
Signed-off-by: Sandy Huang <hjc@rock-chips.com> Change-Id: Id80e3ced8899843e42e2fcaf1954fdad71f0cef1
This commit is contained in:
@@ -722,6 +722,7 @@ struct vop2_dsc_regs {
|
||||
struct vop_reg dsc_flush;
|
||||
struct vop_reg dsc_cfg_done;
|
||||
struct vop_reg dsc_init_dly_num;
|
||||
struct vop_reg scan_timing_para_imd_en;
|
||||
struct vop_reg dsc_htotal_pw;
|
||||
struct vop_reg dsc_hact_st_end;
|
||||
struct vop_reg dsc_vtotal_pw;
|
||||
@@ -831,6 +832,8 @@ struct vop2_dsc_data {
|
||||
uint8_t id;
|
||||
uint8_t pd_id;
|
||||
uint8_t max_slice_num;
|
||||
uint8_t max_linebuf_depth; /* used to generate the bitstream */
|
||||
uint8_t min_bits_per_pixel; /* bit num after encoder compress */
|
||||
const char *dsc_txp_clk_src_name;
|
||||
const char *dsc_txp_clk_name;
|
||||
const char *dsc_pxl_clk_name;
|
||||
|
||||
@@ -454,7 +454,10 @@ struct vop2_wb {
|
||||
struct vop2_dsc {
|
||||
uint8_t id;
|
||||
uint8_t max_slice_num;
|
||||
uint8_t max_linebuf_depth; /* used to generate the bitstream */
|
||||
uint8_t min_bits_per_pixel; /* bit num after encoder compress */
|
||||
bool enabled;
|
||||
char attach_vp_id;
|
||||
const struct vop2_dsc_regs *regs;
|
||||
struct vop2_power_domain *pd;
|
||||
};
|
||||
@@ -3181,6 +3184,8 @@ static void vop2_crtc_disable_dsc(struct vop2 *vop2, u8 dsc_id)
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_mer, 1);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_en, 0);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_cfg_done, 1);
|
||||
|
||||
dsc->attach_vp_id = -1;
|
||||
}
|
||||
|
||||
static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
@@ -3198,7 +3203,9 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
vop2_lock(vop2);
|
||||
DRM_DEV_INFO(vop2->dev, "Crtc atomic disable vp%d\n", vp->id);
|
||||
drm_crtc_vblank_off(crtc);
|
||||
if (vcstate->dsc_enable && vop2->data->nr_dscs) {
|
||||
if (vop2->dscs[vcstate->dsc_id].enabled &&
|
||||
vop2->dscs[vcstate->dsc_id].attach_vp_id == vp->id &&
|
||||
vop2->data->nr_dscs) {
|
||||
if (dual_channel) {
|
||||
vop2_crtc_disable_dsc(vop2, 0);
|
||||
vop2_crtc_disable_dsc(vop2, 1);
|
||||
@@ -3207,7 +3214,9 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
}
|
||||
}
|
||||
vop2_disable_all_planes_for_crtc(crtc);
|
||||
if (vcstate->dsc_enable && vop2->data->nr_dscs && vop2->dscs[vcstate->dsc_id].pd) {
|
||||
if (vop2->dscs[vcstate->dsc_id].enabled &&
|
||||
vop2->dscs[vcstate->dsc_id].attach_vp_id == vp->id &&
|
||||
vop2->data->nr_dscs && vop2->dscs[vcstate->dsc_id].pd) {
|
||||
if (dual_channel) {
|
||||
vop2_power_domain_put(vop2->dscs[0].pd);
|
||||
vop2_power_domain_put(vop2->dscs[1].pd);
|
||||
@@ -5311,7 +5320,12 @@ static int vop2_calc_dsc_clk(struct drm_crtc *crtc)
|
||||
vcstate->dsc_pxl_clk_rate = v_pixclk;
|
||||
do_div(vcstate->dsc_pxl_clk_rate, (vcstate->dsc_slice_num * k));
|
||||
|
||||
vcstate->dsc_cds_clk_rate = vcstate->dsc_pxl_clk_rate >> 1;
|
||||
/* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel)
|
||||
* cds_dat_width = 96;
|
||||
* bits_per_pixel = [8-12];
|
||||
* As only support 1/2/4 div, so we set dsc_cds = crtc_clock / 8;
|
||||
*/
|
||||
vcstate->dsc_cds_clk_rate = adjusted_mode->crtc_clock / 8 * 1000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5379,6 +5393,13 @@ static void vop2_crtc_load_pps(struct drm_crtc *crtc, u8 dsc_id)
|
||||
|
||||
memcpy(&config_pps, pps, sizeof(config_pps));
|
||||
|
||||
if ((config_pps.pps_3 & 0xf) > dsc->max_linebuf_depth) {
|
||||
config_pps.pps_3 &= 0xf0;
|
||||
config_pps.pps_3 |= dsc->max_linebuf_depth;
|
||||
DRM_WARN("DSC%d max_linebuf_depth is: %d, current set value is: %d\n",
|
||||
dsc_id, dsc->max_linebuf_depth, config_pps.pps_3 & 0xf);
|
||||
}
|
||||
|
||||
for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
|
||||
config_pps.rc_range_parameters[i] =
|
||||
(pps->rc_range_parameters[i] >> 3 & 0x1f) |
|
||||
@@ -5402,7 +5423,6 @@ static void vop2_crtc_enable_dsc(struct drm_crtc *crtc, struct drm_crtc_state *o
|
||||
u16 hdisplay = adjusted_mode->crtc_hdisplay;
|
||||
u16 htotal = adjusted_mode->crtc_htotal;
|
||||
u16 hact_st = adjusted_mode->crtc_htotal - adjusted_mode->crtc_hsync_start;
|
||||
u16 hact_end = hact_st + hdisplay;
|
||||
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;
|
||||
@@ -5432,6 +5452,7 @@ static void vop2_crtc_enable_dsc(struct drm_crtc *crtc, struct drm_crtc_state *o
|
||||
vop2_power_domain_get(dsc->pd);
|
||||
|
||||
VOP_MODULE_SET(vop2, dsc, rst_deassert, 1);
|
||||
VOP_MODULE_SET(vop2, dsc, scan_timing_para_imd_en, 1);
|
||||
|
||||
/* read current dsc register and backup to regsbak */
|
||||
offset = dsc->regs->dsc_en.offset;
|
||||
@@ -5448,13 +5469,16 @@ static void vop2_crtc_enable_dsc(struct drm_crtc *crtc, struct drm_crtc_state *o
|
||||
dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE;
|
||||
}
|
||||
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_man_mode, 0);
|
||||
if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_man_mode, 0);
|
||||
else
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_man_mode, 1);
|
||||
dsc_cds_clk = vop2_clk_get(vop2, dsc_data->dsc_cds_clk_name);
|
||||
dsc_pxl_clk = vop2_clk_get(vop2, dsc_data->dsc_pxl_clk_name);
|
||||
dsc_txp_clk = vop2_clk_get(vop2, dsc_data->dsc_txp_clk_name);
|
||||
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_interface_mode, dsc_interface_mode);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_pixel_num, vcstate->dsc_pixel_num >> 1);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_pixel_num, vcstate->dsc_pixel_num >> 1);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_txp_clk_div, dsc_txp_clk->div_val);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_pxl_clk_div, dsc_pxl_clk->div_val);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_cds_clk_div, dsc_cds_clk->div_val);
|
||||
@@ -5462,10 +5486,37 @@ static void vop2_crtc_enable_dsc(struct drm_crtc *crtc, struct drm_crtc_state *o
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_halt_en, mipi_ds_mode);
|
||||
|
||||
if (!mipi_ds_mode) {
|
||||
u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end;
|
||||
u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16;
|
||||
u64 dsc_cds_rate = vcstate->dsc_cds_clk_rate;
|
||||
u32 v_pixclk_mhz = adjusted_mode->crtc_clock / 1000; /* video timing pixclk */
|
||||
u32 dly_num, dsc_cds_rate_mhz, val = 0;
|
||||
|
||||
if (target_bpp >> 4 < dsc->min_bits_per_pixel)
|
||||
DRM_ERROR("Unsupported bpp less than: %d\n", dsc->min_bits_per_pixel);
|
||||
|
||||
/*
|
||||
* dly_num = 3 * T(one-line) / T (dsc_cds)
|
||||
* T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz
|
||||
* T (dsc_cds) = 1 / dsc_cds_rate_mhz
|
||||
* dly_num = 3 * htotal * dsc_cds_rate_mhz / v_pixclk_mhz;
|
||||
*/
|
||||
do_div(dsc_cds_rate, 1000000); /* hz to Mhz */
|
||||
dsc_cds_rate_mhz = dsc_cds_rate;
|
||||
dly_num = 3 * htotal * dsc_cds_rate_mhz / v_pixclk_mhz;
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_init_dly_mode, 0);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_init_dly_num, 4);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_htotal_pw, htotal << 16 | hsync_len);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_hact_st_end, hact_end << 16 | hact_st);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_init_dly_num, dly_num);
|
||||
|
||||
dsc_hsync = hsync_len / 2;
|
||||
dsc_htotal = htotal / (1 << dsc_cds_clk->div_val);
|
||||
val = dsc_htotal << 16 | dsc_hsync;
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_htotal_pw, val);
|
||||
|
||||
dsc_hact_st = hact_st / 2;
|
||||
dsc_hact_end = (hdisplay * target_bpp >> 4) / 24 + dsc_hact_st;
|
||||
val = dsc_hact_end << 16 | dsc_hact_st;
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_hact_st_end, val);
|
||||
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_vtotal_pw, vtotal << 16 | vsync_len);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_vact_st_end, vact_end << 16 | vact_st);
|
||||
}
|
||||
@@ -5479,11 +5530,18 @@ static void vop2_crtc_enable_dsc(struct drm_crtc *crtc, struct drm_crtc_state *o
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_mer, 0);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_epb, 0);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_epl, 1);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_nslc, vcstate->dsc_slice_num >> 1);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_nslc, ilog2(vcstate->dsc_slice_num));
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_sbo, 1);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_ifep, dsc_sink_cap->version_minor == 2 ? 1 : 0);
|
||||
VOP_MODULE_SET(vop2, dsc, dsc_pps_upd, 1);
|
||||
|
||||
DRM_DEV_INFO(vop2->dev, "DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n",
|
||||
dsc->id,
|
||||
vcstate->dsc_txp_clk_rate, dsc_txp_clk->div_val,
|
||||
vcstate->dsc_pxl_clk_rate, dsc_pxl_clk->div_val,
|
||||
vcstate->dsc_cds_clk_rate, dsc_cds_clk->div_val);
|
||||
|
||||
dsc->attach_vp_id = vp->id;
|
||||
dsc->enabled = true;
|
||||
}
|
||||
|
||||
@@ -5611,12 +5669,12 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state
|
||||
|
||||
vcstate->dsc_id = vcstate->output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1;
|
||||
vcstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k;
|
||||
vcstate->dsc_pixel_num = vcstate->dsc_slice_num >= 4 ? 4 : vcstate->dsc_slice_num >= 2 ? 2 : 1;
|
||||
vcstate->dsc_pixel_num = vcstate->dsc_slice_num > 4 ? 4 : vcstate->dsc_slice_num;
|
||||
|
||||
vop2_calc_dsc_clk(crtc);
|
||||
DRM_DEV_INFO(vop2->dev, "Enable DSC%d slice:%dx%d\n",
|
||||
DRM_DEV_INFO(vop2->dev, "Enable DSC%d slice:%dx%d, slice num:%d\n",
|
||||
vcstate->dsc_id, dsc_sink_cap->slice_width,
|
||||
dsc_sink_cap->slice_height);
|
||||
dsc_sink_cap->slice_height, vcstate->dsc_slice_num);
|
||||
}
|
||||
|
||||
vop2_initial(crtc);
|
||||
@@ -8056,7 +8114,10 @@ static void vop2_dsc_data_init(struct vop2 *vop2)
|
||||
dsc_data = &vop2_data->dsc[i];
|
||||
dsc->id = dsc_data->id;
|
||||
dsc->max_slice_num = dsc_data->max_slice_num;
|
||||
dsc->max_linebuf_depth = dsc_data->max_linebuf_depth;
|
||||
dsc->min_bits_per_pixel = dsc_data->min_bits_per_pixel;
|
||||
dsc->regs = dsc_data->regs;
|
||||
dsc->attach_vp_id = -1;
|
||||
if (dsc_data->pd_id)
|
||||
dsc->pd = vop2_find_pd_by_id(vop2, dsc_data->pd_id);
|
||||
}
|
||||
|
||||
@@ -470,10 +470,11 @@ static const struct vop2_dsc_regs rk3588_vop_dsc_8k_regs = {
|
||||
.dsc_flush = VOP_REG(RK3588_DSC_8K_RST, 0x1, 16),
|
||||
.dsc_cfg_done = VOP_REG(RK3588_DSC_8K_CFG_DONE, 0x1, 0),
|
||||
.dsc_init_dly_num = VOP_REG(RK3588_DSC_8K_INIT_DLY, 0xffff, 0),
|
||||
.dsc_htotal_pw = VOP_REG(RK3588_DSC_8K_HTOTAL_HS_END, 0x1, 0),
|
||||
.dsc_hact_st_end = VOP_REG(RK3588_DSC_8K_HACT_ST_END, 0x1, 0),
|
||||
.dsc_vtotal_pw = VOP_REG(RK3588_DSC_8K_VTOTAL_VS_END, 0x1, 0),
|
||||
.dsc_vact_st_end = VOP_REG(RK3588_DSC_8K_VACT_ST_END, 0x1, 0),
|
||||
.scan_timing_para_imd_en = VOP_REG(RK3588_DSC_8K_INIT_DLY, 0x1, 16),
|
||||
.dsc_htotal_pw = VOP_REG(RK3588_DSC_8K_HTOTAL_HS_END, 0xffffffff, 0),
|
||||
.dsc_hact_st_end = VOP_REG(RK3588_DSC_8K_HACT_ST_END, 0xffffffff, 0),
|
||||
.dsc_vtotal_pw = VOP_REG(RK3588_DSC_8K_VTOTAL_VS_END, 0xffffffff, 0),
|
||||
.dsc_vact_st_end = VOP_REG(RK3588_DSC_8K_VACT_ST_END, 0xffffffff, 0),
|
||||
.dsc_error_status = VOP_REG(RK3588_DSC_8K_STATUS, 0x1, 0),
|
||||
|
||||
/* DSC encoder */
|
||||
@@ -509,10 +510,11 @@ static const struct vop2_dsc_regs rk3588_vop_dsc_4k_regs = {
|
||||
.dsc_flush = VOP_REG(RK3588_DSC_4K_RST, 0x1, 16),
|
||||
.dsc_cfg_done = VOP_REG(RK3588_DSC_4K_CFG_DONE, 0x1, 0),
|
||||
.dsc_init_dly_num = VOP_REG(RK3588_DSC_4K_INIT_DLY, 0xffff, 0),
|
||||
.dsc_htotal_pw = VOP_REG(RK3588_DSC_4K_HTOTAL_HS_END, 0x1, 0),
|
||||
.dsc_hact_st_end = VOP_REG(RK3588_DSC_4K_HACT_ST_END, 0x1, 0),
|
||||
.dsc_vtotal_pw = VOP_REG(RK3588_DSC_4K_VTOTAL_VS_END, 0x1, 0),
|
||||
.dsc_vact_st_end = VOP_REG(RK3588_DSC_4K_VACT_ST_END, 0x1, 0),
|
||||
.scan_timing_para_imd_en = VOP_REG(RK3588_DSC_4K_INIT_DLY, 0x1, 16),
|
||||
.dsc_htotal_pw = VOP_REG(RK3588_DSC_4K_HTOTAL_HS_END, 0xffffffff, 0),
|
||||
.dsc_hact_st_end = VOP_REG(RK3588_DSC_4K_HACT_ST_END, 0xffffffff, 0),
|
||||
.dsc_vtotal_pw = VOP_REG(RK3588_DSC_4K_VTOTAL_VS_END, 0xffffffff, 0),
|
||||
.dsc_vact_st_end = VOP_REG(RK3588_DSC_4K_VACT_ST_END, 0xffffffff, 0),
|
||||
.dsc_error_status = VOP_REG(RK3588_DSC_4K_STATUS, 0x1, 0),
|
||||
|
||||
/* DSC encoder */
|
||||
@@ -586,6 +588,8 @@ static const struct vop2_dsc_data rk3588_vop_dsc_data[] = {
|
||||
.id = 0,
|
||||
.pd_id = VOP2_PD_DSC_8K,
|
||||
.max_slice_num = 8,
|
||||
.max_linebuf_depth = 11,
|
||||
.min_bits_per_pixel = 9,
|
||||
.dsc_txp_clk_src_name = "dsc_8k_txp_clk_src",
|
||||
.dsc_txp_clk_name = "dsc_8k_txp_clk",
|
||||
.dsc_pxl_clk_name = "dsc_8k_pxl_clk",
|
||||
@@ -597,6 +601,8 @@ static const struct vop2_dsc_data rk3588_vop_dsc_data[] = {
|
||||
.id = 1,
|
||||
.pd_id = VOP2_PD_DSC_4K,
|
||||
.max_slice_num = 2,
|
||||
.max_linebuf_depth = 11,
|
||||
.min_bits_per_pixel = 9,
|
||||
.dsc_txp_clk_src_name = "dsc_4k_txp_clk_src",
|
||||
.dsc_txp_clk_name = "dsc_4k_txp_clk",
|
||||
.dsc_pxl_clk_name = "dsc_4k_pxl_clk",
|
||||
|
||||
Reference in New Issue
Block a user