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:
@@ -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 =
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
Reference in New Issue
Block a user