mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
drm/rockchip: dw_hdmi: Add property to 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: Ic048fb5c004f332b60bbbeca857de4abe9c0ca08
This commit is contained in:
@@ -324,6 +324,8 @@ struct dw_hdmi {
|
||||
bool sink_is_hdmi;
|
||||
bool sink_has_audio;
|
||||
bool hpd_state;
|
||||
bool support_hdmi;
|
||||
int force_output;
|
||||
|
||||
struct delayed_work work;
|
||||
struct workqueue_struct *workqueue;
|
||||
@@ -390,6 +392,16 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
|
||||
hdmi_modb(hdmi, data << shift, mask, reg);
|
||||
}
|
||||
|
||||
static void dw_hdmi_check_output_type(struct dw_hdmi *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;
|
||||
}
|
||||
|
||||
static void repo_hpd_event(struct work_struct *p_work)
|
||||
{
|
||||
struct dw_hdmi *hdmi = container_of(p_work, struct dw_hdmi, work.work);
|
||||
@@ -2740,7 +2752,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);
|
||||
cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
|
||||
@@ -2748,7 +2760,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
dw_hdmi_update_hdr_property(connector);
|
||||
kfree(edid);
|
||||
} else {
|
||||
hdmi->sink_is_hdmi = true;
|
||||
hdmi->support_hdmi = true;
|
||||
hdmi->sink_has_audio = true;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dw_hdmi_default_modes); i++) {
|
||||
@@ -2772,6 +2784,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
|
||||
dev_info(hdmi->dev, "failed to get edid\n");
|
||||
}
|
||||
dw_hdmi_check_output_type(hdmi);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2916,6 +2929,24 @@ void dw_hdmi_set_quant_range(struct dw_hdmi *hdmi)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_set_quant_range);
|
||||
|
||||
void dw_hdmi_set_output_type(struct dw_hdmi *hdmi, u64 val)
|
||||
{
|
||||
hdmi->force_output = val;
|
||||
|
||||
dw_hdmi_check_output_type(hdmi);
|
||||
|
||||
hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP);
|
||||
dw_hdmi_setup(hdmi, &hdmi->previous_mode);
|
||||
hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_set_output_type);
|
||||
|
||||
bool dw_hdmi_get_output_whether_hdmi(struct dw_hdmi *hdmi)
|
||||
{
|
||||
return hdmi->sink_is_hdmi;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_get_output_whether_hdmi);
|
||||
|
||||
static void dw_hdmi_connector_force(struct drm_connector *connector)
|
||||
{
|
||||
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
|
||||
|
||||
@@ -116,6 +116,7 @@ struct rockchip_hdmi {
|
||||
bool unsupported_yuv_input;
|
||||
bool unsupported_deep_color;
|
||||
bool mode_changed;
|
||||
u8 force_output;
|
||||
u8 id;
|
||||
|
||||
unsigned long bus_format;
|
||||
@@ -130,6 +131,7 @@ struct rockchip_hdmi {
|
||||
struct drm_property *colorimetry_property;
|
||||
struct drm_property *quant_range;
|
||||
struct drm_property *hdr_panel_metadata_property;
|
||||
struct drm_property *output_hdmi_dvi;
|
||||
|
||||
struct drm_property_blob *hdr_panel_blob_ptr;
|
||||
|
||||
@@ -642,6 +644,7 @@ dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state,
|
||||
unsigned long tmdsclock, pixclock = mode->crtc_clock;
|
||||
unsigned int color_depth;
|
||||
bool support_dc = false;
|
||||
bool sink_is_hdmi = dw_hdmi_get_output_whether_hdmi(hdmi->hdmi);
|
||||
int max_tmds_clock = info->max_tmds_clock;
|
||||
int output_eotf;
|
||||
|
||||
@@ -702,6 +705,11 @@ dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state,
|
||||
else
|
||||
color_depth = 8;
|
||||
|
||||
if (!sink_is_hdmi) {
|
||||
*color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
|
||||
color_depth = 8;
|
||||
}
|
||||
|
||||
*eotf = TRADITIONAL_GAMMA_SDR;
|
||||
if (conn_state->hdr_output_metadata) {
|
||||
hdr_metadata = (struct hdr_output_metadata *)
|
||||
@@ -986,6 +994,12 @@ static const struct drm_prop_enum_list colorimetry_enum_list[] = {
|
||||
{ RK_HDMI_COLORIMETRY_BT2020, "ITU_2020" },
|
||||
};
|
||||
|
||||
static const struct drm_prop_enum_list output_hdmi_dvi_enum_list[] = {
|
||||
{ 0, "auto" },
|
||||
{ 1, "force_hdmi" },
|
||||
{ 2, "force_dvi" },
|
||||
};
|
||||
|
||||
static void
|
||||
dw_hdmi_rockchip_attach_properties(struct drm_connector *connector,
|
||||
unsigned int color, int version,
|
||||
@@ -1106,6 +1120,15 @@ dw_hdmi_rockchip_attach_properties(struct drm_connector *connector,
|
||||
drm_object_attach_property(&connector->base, prop, 0);
|
||||
}
|
||||
|
||||
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 = connector->dev->mode_config.hdr_output_metadata_property;
|
||||
if (version >= 0x211a)
|
||||
drm_object_attach_property(&connector->base, prop, 0);
|
||||
@@ -1159,6 +1182,12 @@ dw_hdmi_rockchip_destroy_properties(struct drm_connector *connector,
|
||||
hdmi->hdr_panel_metadata_property);
|
||||
hdmi->hdr_panel_metadata_property = NULL;
|
||||
}
|
||||
|
||||
if (hdmi->output_hdmi_dvi) {
|
||||
drm_property_destroy(connector->dev,
|
||||
hdmi->output_hdmi_dvi);
|
||||
hdmi->output_hdmi_dvi = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1195,6 +1224,12 @@ dw_hdmi_rockchip_set_property(struct drm_connector *connector,
|
||||
} else if (property == hdmi->colorimetry_property) {
|
||||
hdmi->colorimetry = val;
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DRM_ERROR("failed to set rockchip hdmi connector property %s\n", property->name);
|
||||
@@ -1260,6 +1295,9 @@ dw_hdmi_rockchip_get_property(struct drm_connector *connector,
|
||||
} else if (property == private->connector_id_prop) {
|
||||
*val = hdmi->id;
|
||||
return 0;
|
||||
} else if (property == hdmi->output_hdmi_dvi) {
|
||||
*val = hdmi->force_output;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DRM_ERROR("failed to get rockchip hdmi connector property %s\n", property->name);
|
||||
|
||||
@@ -217,5 +217,7 @@ void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data,
|
||||
bool force, bool disabled, bool rxsense);
|
||||
void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data);
|
||||
void dw_hdmi_set_quant_range(struct dw_hdmi *hdmi);
|
||||
void dw_hdmi_set_output_type(struct dw_hdmi *hdmi, u64 val);
|
||||
bool dw_hdmi_get_output_whether_hdmi(struct dw_hdmi *hdmi);
|
||||
|
||||
#endif /* __IMX_HDMI_H__ */
|
||||
|
||||
Reference in New Issue
Block a user