drm/bridge: synopsys: dw-hdmi-qp: Get uboot color format from avi regs in dsc mode

RK3588/RK3576 hdmi color format setting and dsc mode setting are
the same mask in the same register. If dsc is enabled for hdmi in
uboot, what color is hdmi output in uboot that cannot be obtained
from this register in kernel.
Since hdmi in dsc mode always sends avi infoframe, color format
of hdmi output in uboot can be read from the avi register.

Change-Id: I68157455342302338370feb9176b46e2051b4f01
Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
This commit is contained in:
Algea Cao
2025-03-31 15:07:37 +08:00
committed by Tao Huang
parent f1c83fae2e
commit db27b299b7
3 changed files with 100 additions and 44 deletions

View File

@@ -73,6 +73,15 @@
#define HDMI_CTRL_CLK_EN 0x15
#define DW_HDMI_QP_RGB 0
#define DW_HDMI_QP_YUV422 0x1
#define DW_HDMI_QP_YUV444 0x2
#define DW_HDMI_QP_YUV420 0x3
#define DW_HDMI_QP_DSC 0xb
#define IPI_FORMAT_MASK 0xf
#define IPI_COLOR_DEPTH_MASK 0xf0
static const unsigned int dw_hdmi_cable[] = {
EXTCON_DISP_HDMI,
EXTCON_NONE,
@@ -2990,20 +2999,107 @@ dw_hdmi_connector_set_property(struct drm_connector *connector,
property, val);
}
static u64 dw_hdmi_qp_get_avi_color_fmt(struct dw_hdmi_qp *hdmi, u32 depth)
{
u32 fmt;
u64 bus_format;
fmt = (hdmi_readl(hdmi, PKT_AVI_CONTENTS1) >> 13) & 0x3;
switch (fmt) {
case DW_HDMI_QP_YUV444:
if (!depth)
bus_format = MEDIA_BUS_FMT_YUV8_1X24;
else
bus_format = MEDIA_BUS_FMT_YUV10_1X30;
break;
case DW_HDMI_QP_YUV422:
bus_format = MEDIA_BUS_FMT_YUYV10_1X20;
break;
case DW_HDMI_QP_YUV420:
if (!depth)
bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
else
bus_format = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
break;
case DW_HDMI_QP_RGB:
if (!depth)
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
else
bus_format = MEDIA_BUS_FMT_RGB101010_1X30;
break;
default:
dev_err(hdmi->dev, "can't get correct color format\n");
bus_format = MEDIA_BUS_FMT_YUV8_1X24;
break;
}
return bus_format;
}
static u64 dw_hdmi_qp_get_color_fmt(struct dw_hdmi_qp *hdmi)
{
u32 fmt, depth;
u64 bus_format;
fmt = hdmi_readl(hdmi, VIDEO_INTERFACE_STATUS0);
depth = fmt & IPI_COLOR_DEPTH_MASK;
fmt = fmt & IPI_FORMAT_MASK;
switch (fmt) {
case DW_HDMI_QP_YUV444:
if (!depth)
bus_format = MEDIA_BUS_FMT_YUV8_1X24;
else
bus_format = MEDIA_BUS_FMT_YUV10_1X30;
break;
case DW_HDMI_QP_YUV422:
bus_format = MEDIA_BUS_FMT_YUYV10_1X20;
break;
case DW_HDMI_QP_YUV420:
if (!depth)
bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
else
bus_format = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
break;
case DW_HDMI_QP_RGB:
if (!depth)
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
else
bus_format = MEDIA_BUS_FMT_RGB101010_1X30;
break;
/*
* RK3588/RK3576 hdmi color format setting and dsc mode setting are
* the same mask in the same register. If dsc is enabled for hdmi in
* uboot, what color is hdmi output in uboot that cannot be obtained
* from this register in kernel.
* Since hdmi in dsc mode always sends avi infoframe, color format
* of hdmi output in uboot can be read from the avi register.
*/
case DW_HDMI_QP_DSC:
bus_format = dw_hdmi_qp_get_avi_color_fmt(hdmi, depth);
break;
default:
dev_err(hdmi->dev, "can't get correct color format\n");
bus_format = MEDIA_BUS_FMT_YUV8_1X24;
break;
}
return bus_format;
}
static void dw_hdmi_attach_properties(struct dw_hdmi_qp *hdmi)
{
u32 val;
u64 color = MEDIA_BUS_FMT_YUV8_1X24;
const struct dw_hdmi_property_ops *ops =
hdmi->plat_data->property_ops;
void *data = hdmi->plat_data->phy_data;
enum drm_connector_status connect_status =
hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
if ((connect_status == connector_status_connected) &&
hdmi->initialized) {
if (hdmi->plat_data->get_grf_color_fmt)
color = hdmi->plat_data->get_grf_color_fmt(data);
color = dw_hdmi_qp_get_color_fmt(hdmi);
val = (hdmi_readl(hdmi, PKT_VSI_CONTENTS1) >> 8) & 0xffffff;
if (val == HDMI_FORUM_OUI)
@@ -3613,6 +3709,7 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
cancel_work_sync(&hdmi->flt_work);
flush_workqueue(hdmi->workqueue);
dw_hdmi_qp_flt_ltsl(hdmi);
if (hdmi->panel)
drm_panel_unprepare(hdmi->panel);

View File

@@ -2399,45 +2399,6 @@ static void rk3588_get_grf_color_fmt(struct rockchip_hdmi *hdmi, u32 *fmt, u32 *
*fmt = *fmt & RK3588_COLOR_FORMAT_MASK;
}
static u64 rockchip_get_grf_color_fmt(void *data)
{
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
u32 fmt, depth;
u64 bus_format;
hdmi->chip_data->ops->get_grf_color_fmt(hdmi, &fmt, &depth);
switch (fmt) {
case RK3588_YUV444:
if (!depth)
bus_format = MEDIA_BUS_FMT_YUV8_1X24;
else
bus_format = MEDIA_BUS_FMT_YUV10_1X30;
break;
case RK3588_YUV422:
bus_format = MEDIA_BUS_FMT_YUYV10_1X20;
break;
case RK3588_YUV420:
if (!depth)
bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
else
bus_format = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
break;
case RK3588_RGB:
if (!depth)
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
else
bus_format = MEDIA_BUS_FMT_RGB101010_1X30;
break;
default:
dev_err(hdmi->dev, "can't get correct color format\n");
bus_format = MEDIA_BUS_FMT_YUV8_1X24;
break;
}
return bus_format;
}
static void
dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state,
struct drm_crtc_state *crtc_state,
@@ -4603,7 +4564,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
plat_data->set_hdcp2_enable = rockchip_set_hdcp2_enable;
plat_data->set_hdcp_status = rockchip_set_hdcp_status;
plat_data->set_grf_cfg = rockchip_set_grf_cfg;
plat_data->get_grf_color_fmt = rockchip_get_grf_color_fmt;
plat_data->convert_to_split_mode = drm_mode_convert_to_split_mode;
plat_data->convert_to_origin_mode = drm_mode_convert_to_origin_mode;
plat_data->dclk_set = dw_hdmi_dclk_set;

View File

@@ -273,7 +273,6 @@ struct dw_hdmi_plat_data {
void (*set_hdcp_status)(void *data, u8 status);
void (*set_hdcp2_enable)(void *data, bool enable);
void (*set_grf_cfg)(void *data);
u64 (*get_grf_color_fmt)(void *data);
void (*convert_to_split_mode)(struct drm_display_mode *mode);
void (*convert_to_origin_mode)(struct drm_display_mode *mode);
int (*dclk_set)(void *data, bool enable, int vp_id);