drm/rockchip: dw_hdmi_qp: Support rk3588 switch HDMI/DVI mode

Add property output_hdmi_dvi:
enums: auto=0 force_hdmi=1 force_dvi=2

Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
Change-Id: I395644ebf1b8eea6a41f80e1282fbc3373144503
This commit is contained in:
Algea Cao
2022-10-10 09:53:53 +08:00
committed by Tao Huang
parent e2bf2eaab8
commit 4512ef481e
3 changed files with 89 additions and 25 deletions
+53 -2
View File
@@ -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 =
+33 -23
View File
@@ -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;
+3
View File
@@ -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__ */