diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 59965f85109c..927be632b9a4 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -253,6 +253,8 @@ struct dw_hdmi_qp { bool frl_switch; bool cec_enable; bool allm_enable; + bool support_hdmi; + int force_output; struct mutex mutex; /* for state below and previous_mode */ struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */ @@ -1980,6 +1982,25 @@ dw_hdmi_update_hdr_property(struct drm_connector *connector) return ret; } +static bool dw_hdmi_qp_check_output_type_changed(struct dw_hdmi_qp *hdmi) +{ + bool sink_hdmi; + + sink_hdmi = hdmi->sink_is_hdmi; + + if (hdmi->force_output == 1) + hdmi->sink_is_hdmi = true; + else if (hdmi->force_output == 2) + hdmi->sink_is_hdmi = false; + else + hdmi->sink_is_hdmi = hdmi->support_hdmi; + + if (sink_hdmi != hdmi->sink_is_hdmi) + return true; + + return false; +} + static int dw_hdmi_connector_get_modes(struct drm_connector *connector) { struct dw_hdmi_qp *hdmi = @@ -2001,7 +2022,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", edid->width_cm, edid->height_cm); - hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); + hdmi->support_hdmi = drm_detect_hdmi_monitor(edid); hdmi->sink_has_audio = drm_detect_monitor_audio(edid); drm_connector_update_edid_property(connector, edid); if (hdmi->cec_notifier) @@ -2036,7 +2057,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) } kfree(edid); } else { - hdmi->sink_is_hdmi = true; + hdmi->support_hdmi = true; hdmi->sink_has_audio = true; if (hdmi->plat_data->split_mode) { @@ -2073,6 +2094,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) dev_info(hdmi->dev, "failed to get edid\n"); } + dw_hdmi_qp_check_output_type_changed(hdmi); return ret; } @@ -2318,6 +2340,35 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, return 0; } +void dw_hdmi_qp_set_output_type(struct dw_hdmi_qp *hdmi, u64 val) +{ + hdmi->force_output = val; + + if (!dw_hdmi_qp_check_output_type_changed(hdmi)) + return; + + if (hdmi->disabled) + return; + + if (!hdmi->sink_is_hdmi) + hdmi_modb(hdmi, OPMODE_DVI, OPMODE_DVI, LINK_CONFIG0); + else + hdmi_modb(hdmi, 0, OPMODE_DVI, LINK_CONFIG0); +} +EXPORT_SYMBOL_GPL(dw_hdmi_qp_set_output_type); + +bool dw_hdmi_qp_get_output_whether_hdmi(struct dw_hdmi_qp *hdmi) +{ + return hdmi->sink_is_hdmi; +} +EXPORT_SYMBOL_GPL(dw_hdmi_qp_get_output_whether_hdmi); + +int dw_hdmi_qp_get_output_type_cap(struct dw_hdmi_qp *hdmi) +{ + return hdmi->support_hdmi; +} +EXPORT_SYMBOL_GPL(dw_hdmi_qp_get_output_type_cap); + static void dw_hdmi_connector_force(struct drm_connector *connector) { struct dw_hdmi_qp *hdmi = diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index d1af980127b1..69801ca30474 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -1766,6 +1766,8 @@ dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state, if (!hdmi->is_hdmi_qp) sink_is_hdmi = dw_hdmi_get_output_whether_hdmi(hdmi->hdmi); + else + sink_is_hdmi = dw_hdmi_qp_get_output_whether_hdmi(hdmi->hdmi_qp); *color_format = RK_IF_FORMAT_RGB; @@ -2448,25 +2450,25 @@ dw_hdmi_rockchip_attach_properties(struct drm_connector *connector, } hdmi->enable_allm = allm_en; + prop = drm_property_create_enum(connector->dev, 0, + "output_hdmi_dvi", + output_hdmi_dvi_enum_list, + ARRAY_SIZE(output_hdmi_dvi_enum_list)); + if (prop) { + hdmi->output_hdmi_dvi = prop; + drm_object_attach_property(&connector->base, prop, 0); + } + + prop = drm_property_create_enum(connector->dev, 0, + "output_type_capacity", + output_type_cap_list, + ARRAY_SIZE(output_type_cap_list)); + if (prop) { + hdmi->output_type_capacity = prop; + drm_object_attach_property(&connector->base, prop, 0); + } + if (!hdmi->is_hdmi_qp) { - prop = drm_property_create_enum(connector->dev, 0, - "output_hdmi_dvi", - output_hdmi_dvi_enum_list, - ARRAY_SIZE(output_hdmi_dvi_enum_list)); - if (prop) { - hdmi->output_hdmi_dvi = prop; - drm_object_attach_property(&connector->base, prop, 0); - } - - prop = drm_property_create_enum(connector->dev, 0, - "output_type_capacity", - output_type_cap_list, - ARRAY_SIZE(output_type_cap_list)); - if (prop) { - hdmi->output_type_capacity = prop; - drm_object_attach_property(&connector->base, prop, 0); - } - prop = drm_property_create_enum(connector->dev, 0, "hdmi_quant_range", quant_range_enum_list, @@ -2600,10 +2602,15 @@ dw_hdmi_rockchip_set_property(struct drm_connector *connector, } else if (property == config->hdr_output_metadata_property) { return 0; } else if (property == hdmi->output_hdmi_dvi) { - if (hdmi->force_output != val) - hdmi->color_changed++; - hdmi->force_output = val; - dw_hdmi_set_output_type(hdmi->hdmi, val); + if (!hdmi->is_hdmi_qp) { + if (hdmi->force_output != val) + hdmi->color_changed++; + hdmi->force_output = val; + dw_hdmi_set_output_type(hdmi->hdmi, val); + } else { + hdmi->force_output = val; + dw_hdmi_qp_set_output_type(hdmi->hdmi_qp, val); + } return 0; } else if (property == hdmi->colordepth_capacity) { return 0; @@ -2684,7 +2691,10 @@ dw_hdmi_rockchip_get_property(struct drm_connector *connector, *val = hdmi->force_output; return 0; } else if (property == hdmi->output_type_capacity) { - *val = dw_hdmi_get_output_type_cap(hdmi->hdmi); + if (!hdmi->is_hdmi_qp) + *val = dw_hdmi_get_output_type_cap(hdmi->hdmi); + else + *val = dw_hdmi_qp_get_output_type_cap(hdmi->hdmi_qp); return 0; } else if (property == hdmi->user_split_mode_prop) { *val = hdmi->user_split_mode; diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 35b4889b01dc..3e2c6ecb6575 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -321,5 +321,8 @@ void dw_hdmi_qp_audio_enable(struct dw_hdmi_qp *hdmi); void dw_hdmi_qp_audio_disable(struct dw_hdmi_qp *hdmi); int dw_hdmi_qp_set_plugged_cb(struct dw_hdmi_qp *hdmi, hdmi_codec_plugged_cb fn, struct device *codec_dev); +void dw_hdmi_qp_set_output_type(struct dw_hdmi_qp *hdmi, u64 val); +bool dw_hdmi_qp_get_output_whether_hdmi(struct dw_hdmi_qp *hdmi); +int dw_hdmi_qp_get_output_type_cap(struct dw_hdmi_qp *hdmi); #endif /* __IMX_HDMI_H__ */