mirror of
https://github.com/LibreELEC/LibreELEC.tv
synced 2025-09-24 19:46:01 +07:00
227 lines
7.5 KiB
Diff
227 lines
7.5 KiB
Diff
From 40e1477f3aec58161f90a476a2672500dac9ecf6 Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
Date: Fri, 20 Dec 2019 08:12:43 +0000
|
|
Subject: [PATCH 22/59] WIP/1000: drm/rockchip: add yuv444 support
|
|
|
|
---
|
|
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 29 ++++++++++++++++++++-
|
|
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 29 +++++++++++++++++++++
|
|
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 6 +++++
|
|
drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 19 ++++++++++++++
|
|
4 files changed, 82 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
|
index 8134add505e0..07a8796b1f47 100644
|
|
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
|
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
|
|
@@ -69,6 +69,7 @@ struct rockchip_hdmi_chip_data {
|
|
u32 lcdsel_big;
|
|
u32 lcdsel_lit;
|
|
int max_tmds_clock;
|
|
+ bool ycbcr_444_allowed;
|
|
};
|
|
|
|
struct rockchip_hdmi {
|
|
@@ -402,10 +403,22 @@ static bool is_rgb(u32 format)
|
|
}
|
|
}
|
|
|
|
+static bool is_yuv444(u32 format)
|
|
+{
|
|
+ switch (format) {
|
|
+ case MEDIA_BUS_FMT_YUV10_1X30:
|
|
+ case MEDIA_BUS_FMT_YUV8_1X24:
|
|
+ return true;
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
static bool is_10bit(u32 format)
|
|
{
|
|
switch (format) {
|
|
case MEDIA_BUS_FMT_RGB101010_1X30:
|
|
+ case MEDIA_BUS_FMT_YUV10_1X30:
|
|
return true;
|
|
default:
|
|
return false;
|
|
@@ -422,12 +435,22 @@ dw_hdmi_rockchip_bridge_atomic_check(struct drm_bridge *bridge,
|
|
struct drm_atomic_state *state = bridge_state->base.state;
|
|
struct drm_crtc_state *old_crtc_state;
|
|
struct rockchip_crtc_state *old_state;
|
|
+ struct drm_bridge *next_bridge;
|
|
+ struct drm_bridge_state *next_bridge_state;
|
|
u32 format = bridge_state->output_bus_cfg.format;
|
|
|
|
s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
|
|
s->output_type = DRM_MODE_CONNECTOR_HDMIA;
|
|
s->output_bpc = 10;
|
|
s->bus_format = format;
|
|
+
|
|
+ next_bridge = drm_bridge_get_next_bridge(bridge);
|
|
+ if (next_bridge) {
|
|
+ next_bridge_state = drm_atomic_get_new_bridge_state(state,
|
|
+ next_bridge);
|
|
+ format = next_bridge_state->output_bus_cfg.format;
|
|
+ }
|
|
+
|
|
s->bus_width = is_10bit(format) ? 10 : 8;
|
|
|
|
old_crtc_state = drm_atomic_get_old_crtc_state(state, conn_state->crtc);
|
|
@@ -461,7 +484,10 @@ static u32 *dw_hdmi_rockchip_get_input_bus_fmts(struct drm_bridge *bridge,
|
|
if (!has_10bit && is_10bit(output_fmt))
|
|
return NULL;
|
|
|
|
- if (!is_rgb(output_fmt))
|
|
+ if (is_yuv444(output_fmt)) {
|
|
+ if (!hdmi->chip_data->ycbcr_444_allowed)
|
|
+ return NULL;
|
|
+ } else if (!is_rgb(output_fmt))
|
|
return NULL;
|
|
|
|
input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL);
|
|
@@ -616,6 +642,7 @@ static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = {
|
|
static struct rockchip_hdmi_chip_data rk3328_chip_data = {
|
|
.lcdsel_grf_reg = -1,
|
|
.max_tmds_clock = 594000,
|
|
+ .ycbcr_444_allowed = true,
|
|
};
|
|
|
|
static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = {
|
|
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
|
|
index ea6dd61b4c1c..784599231a6a 100644
|
|
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
|
|
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
|
|
@@ -344,6 +344,17 @@ static int vop_convert_afbc_format(uint32_t format)
|
|
}
|
|
}
|
|
|
|
+static bool is_yuv_output(uint32_t bus_format)
|
|
+{
|
|
+ switch (bus_format) {
|
|
+ case MEDIA_BUS_FMT_YUV8_1X24:
|
|
+ case MEDIA_BUS_FMT_YUV10_1X30:
|
|
+ return true;
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src,
|
|
uint32_t dst, bool is_horizontal,
|
|
int vsu_mode, int *vskiplines)
|
|
@@ -1382,6 +1393,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
|
|
u16 vact_end = vact_st + vdisplay;
|
|
uint32_t pin_pol, val;
|
|
int dither_bpc = s->output_bpc ? s->output_bpc : 10;
|
|
+ bool yuv_output = is_yuv_output(s->bus_format);
|
|
int ret;
|
|
|
|
if (old_state && old_state->self_refresh_active) {
|
|
@@ -1447,6 +1459,8 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
|
|
!(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10))
|
|
s->output_mode = ROCKCHIP_OUT_MODE_P888;
|
|
|
|
+ VOP_REG_SET(vop, common, dsp_data_swap, yuv_output ? 2 : 0);
|
|
+
|
|
if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8)
|
|
VOP_REG_SET(vop, common, pre_dither_down, 1);
|
|
else
|
|
@@ -1462,6 +1476,21 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
|
|
|
|
VOP_REG_SET(vop, common, out_mode, s->output_mode);
|
|
|
|
+ VOP_REG_SET(vop, common, overlay_mode, yuv_output);
|
|
+ VOP_REG_SET(vop, common, dsp_out_yuv, yuv_output);
|
|
+
|
|
+ /*
|
|
+ * Background color is 10bit depth if vop version >= 3.5
|
|
+ */
|
|
+ if (!yuv_output)
|
|
+ val = 0;
|
|
+ else if (VOP_MAJOR(vop_data->version) == 3 &&
|
|
+ VOP_MINOR(vop_data->version) >= 5)
|
|
+ val = 0x20010200;
|
|
+ else
|
|
+ val = 0x801080;
|
|
+ VOP_REG_SET(vop, common, dsp_background, val);
|
|
+
|
|
VOP_REG_SET(vop, modeset, htotal_pw, (htotal << 16) | hsync_len);
|
|
val = hact_st << 16;
|
|
val |= hact_end;
|
|
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
|
|
index f04c9731ae7b..1fa0ecdf734c 100644
|
|
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
|
|
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
|
|
@@ -125,10 +125,16 @@ struct vop_common {
|
|
struct vop_reg dma_stop;
|
|
struct vop_reg out_mode;
|
|
struct vop_reg standby;
|
|
+
|
|
+ struct vop_reg overlay_mode;
|
|
+ struct vop_reg dsp_data_swap;
|
|
+ struct vop_reg dsp_out_yuv;
|
|
+ struct vop_reg dsp_background;
|
|
};
|
|
|
|
struct vop_misc {
|
|
struct vop_reg global_regdone_en;
|
|
+ struct vop_reg win_channel[4];
|
|
};
|
|
|
|
struct vop_intr {
|
|
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
|
|
index be237c844c49..234e03edae12 100644
|
|
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
|
|
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
|
|
@@ -727,6 +727,11 @@ static const struct vop_common rk3288_common = {
|
|
.dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18),
|
|
.out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
|
|
.cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0),
|
|
+
|
|
+ .overlay_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 16),
|
|
+ .dsp_data_swap = VOP_REG(RK3288_DSP_CTRL0, 0x1f, 12),
|
|
+ .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2),
|
|
+ .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0),
|
|
};
|
|
|
|
/*
|
|
@@ -952,6 +957,11 @@ static const struct vop_common rk3399_common = {
|
|
.dsp_blank = VOP_REG(RK3399_DSP_CTRL0, 0x3, 18),
|
|
.out_mode = VOP_REG(RK3399_DSP_CTRL0, 0xf, 0),
|
|
.cfg_done = VOP_REG_SYNC(RK3399_REG_CFG_DONE, 0x1, 0),
|
|
+
|
|
+ .overlay_mode = VOP_REG(RK3399_SYS_CTRL, 0x1, 16),
|
|
+ .dsp_data_swap = VOP_REG(RK3399_DSP_CTRL0, 0x1f, 12),
|
|
+ .dsp_out_yuv = VOP_REG(RK3288_POST_SCL_CTRL, 0x1, 2),
|
|
+ .dsp_background = VOP_REG(RK3288_DSP_BG, 0xffffffff, 0),
|
|
};
|
|
|
|
static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win01_data = {
|
|
@@ -1146,6 +1156,10 @@ static const struct vop_output rk3328_output = {
|
|
|
|
static const struct vop_misc rk3328_misc = {
|
|
.global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11),
|
|
+
|
|
+ .win_channel[0] = VOP_REG(RK3328_WIN0_CTRL2, 0xff, 0),
|
|
+ .win_channel[1] = VOP_REG(RK3328_WIN1_CTRL2, 0xff, 0),
|
|
+ .win_channel[2] = VOP_REG(RK3328_WIN2_CTRL2, 0xff, 0),
|
|
};
|
|
|
|
static const struct vop_common rk3328_common = {
|
|
@@ -1158,6 +1172,11 @@ static const struct vop_common rk3328_common = {
|
|
.dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18),
|
|
.out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0),
|
|
.cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0),
|
|
+
|
|
+ .overlay_mode = VOP_REG(RK3328_SYS_CTRL, 0x1, 16),
|
|
+ .dsp_data_swap = VOP_REG(RK3328_DSP_CTRL0, 0x1f, 12),
|
|
+ .dsp_out_yuv = VOP_REG(RK3328_POST_SCL_CTRL, 0x1, 2),
|
|
+ .dsp_background = VOP_REG(RK3328_DSP_BG, 0xffffffff, 0),
|
|
};
|
|
|
|
static const struct vop_intr rk3328_vop_intr = {
|
|
--
|
|
2.34.1
|
|
|