From ed5631fa515a297b45cef5a1330b516f56e113dc Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Thu, 28 Dec 2023 10:16:17 +0800 Subject: [PATCH] drm/bridge: dw-hdmi-qp: Support hdmi force output Support hdmi output specific resolution and color format regardless of whether hdmi is connected. Signed-off-by: Algea Cao Change-Id: I3f18aeb04427846e06b6a4397a4c6df77bbbcab2 --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 32 ++++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 87d6f830cfb9..a2d24238bfbb 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -276,7 +276,8 @@ struct dw_hdmi_qp { bool allm_enable; bool support_hdmi; bool skip_connector; - int force_output; + bool force_kernel_output; /* force kernel hdmi output specific resolution */ + int force_output; /* force hdmi/dvi output mode */ int vp_id; int old_vp_id; @@ -1678,6 +1679,9 @@ static bool dw_hdmi_support_scdc(struct dw_hdmi_qp *hdmi, if (!hdmi->ddc) return false; + if (hdmi->force_kernel_output) + return true; + /* Disable if SCDC is not supported, or if an HF-VSDB block is absent */ if (!display->hdmi.scdc.supported || !display->hdmi.scdc.scrambling.supported) @@ -2127,7 +2131,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) hdmi->force = DRM_FORCE_UNSPECIFIED; mutex_unlock(&hdmi->mutex); - if (hdmi->panel) + if (hdmi->panel || hdmi->force_kernel_output) return connector_status_connected; if (hdmi->next_bridge && hdmi->next_bridge->ops & DRM_BRIDGE_OP_DETECT) @@ -2265,6 +2269,22 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) struct drm_property_blob *edid_blob_ptr = connector->edid_blob_ptr; int i, ret = 0; + if (hdmi->force_kernel_output) { + mode = hdmi->plat_data->get_force_timing(data); + hdmi->support_hdmi = true; + hdmi->sink_is_hdmi = true; + hdmi->sink_has_audio = true; + mode = drm_mode_duplicate(connector->dev, mode); + drm_mode_debug_printmodeline(mode); + drm_mode_probed_add(connector, mode); + info->edid_hdmi_rgb444_dc_modes = 0; + info->edid_hdmi_ycbcr444_dc_modes = 0; + info->hdmi.y420_dc_modes = 0; + info->color_formats = 0; + + return 1; + } + if (hdmi->plat_data->right && hdmi->plat_data->right->next_bridge) { struct drm_bridge *bridge = hdmi->plat_data->right->next_bridge; @@ -2726,7 +2746,7 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, drm_scdc_readb(hdmi->ddc, SCDC_TMDS_CONFIG, &val); /* if plug out before hdmi bind, reset hdmi */ if (vmode->mtmdsclock >= 340000000 && vmode->mpixelclock <= 600000000 && - !(val & SCDC_TMDS_BIT_CLOCK_RATIO_BY_40)) + !(val & SCDC_TMDS_BIT_CLOCK_RATIO_BY_40) && !hdmi->force_kernel_output) hdmi->logo_plug_out = true; } @@ -2927,6 +2947,9 @@ dw_hdmi_qp_bridge_mode_valid(struct drm_bridge *bridge, struct dw_hdmi_qp *hdmi = bridge->driver_private; const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; + if (hdmi->force_kernel_output) + return MODE_OK; + if (mode->clock <= 25000) return MODE_CLOCK_RANGE; @@ -3756,6 +3779,9 @@ __dw_hdmi_probe(struct platform_device *pdev, if (ret < 0) goto err_ddc; + if (hdmi->plat_data->get_force_timing(hdmi->plat_data->phy_data)) + hdmi->force_kernel_output = true; + hdmi_writel(hdmi, 0, MAINUNIT_0_INT_MASK_N); hdmi_writel(hdmi, 0, MAINUNIT_1_INT_MASK_N); hdmi_writel(hdmi, 428571429, TIMER_BASE_CONFIG0);