DP_MAX_DOWNSTREAM_PORTS=0x10 is a vendor-independent constant. Signed-off-by: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> --- drivers/gpu/drm/i915/intel_drv.h | 2 -- include/drm/drm_dp_helper.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 770f9f6aad84..f110c5e79610 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1083,8 +1083,6 @@ struct intel_hdmi { }; struct intel_dp_mst_encoder; -#define DP_MAX_DOWNSTREAM_PORTS 0x10 - /* * enum link_m_n_set: * When platform provides two set of M_N registers for dp, we can diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 397896b5b21a..e0c157cde986 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -349,6 +349,8 @@ # define DP_DS_12BPC 2 # define DP_DS_16BPC 3 +#define DP_MAX_DOWNSTREAM_PORTS 0x10 + /* DP Forward error Correction Registers */ #define DP_FEC_CAPABILITY 0x090 /* 1.4 */ # define DP_FEC_CAPABLE (1 << 0) -- 2.22.0 >From 905f5dfc3689f221d7c73379257ff0713b81fb5b Mon Sep 17 00:00:00 2001 From: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> Date: Fri, 5 Jul 2019 13:08:27 +0300 Subject: [PATCH 2/6] drm: always determine branch device with drm_dp_is_branch() To: contact@xxxxxxxxxxx The helper should always be used. Signed-off-by: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> --- drivers/gpu/drm/drm_dp_helper.c | 3 +-- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 0b994d083a89..67f7f3e1997b 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -596,8 +596,7 @@ void drm_dp_downstream_debug(struct seq_file *m, int len; uint8_t rev[2]; int type = port_cap[0] & DP_DS_PORT_TYPE_MASK; - bool branch_device = dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_PRESENT; + bool branch_device = drm_dp_is_branch(dpcd); seq_printf(m, "\tDP branch device present: %s\n", branch_device ? "yes" : "no"); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index a9db16de2999..b8f8f40b4f3d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2916,7 +2916,7 @@ static bool downstream_hpd_needs_d0(struct intel_dp *intel_dp) * FIXME should really check all downstream ports... */ return intel_dp->dpcd[DP_DPCD_REV] == 0x11 && - intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT && + drm_dp_is_branch(intel_dp->dpcd) && intel_dp->downstream_ports[0] & DP_DS_PORT_HPD; } -- 2.22.0 >From d916e8a3d67f231a50d544422132e3efc3d123e4 Mon Sep 17 00:00:00 2001 From: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> Date: Thu, 27 Jun 2019 17:20:17 +0300 Subject: [PATCH 3/6] drm: report dp downstream port type as a subconnector property To: contact@xxxxxxxxxxx Currently, downstream port type is only reported in debugfs. This information should be considered important since it reflects the actual physical connector type. Some userspace (e.g. window compositors) may want to show this info to a user. The 'subconnector' property is already utilized for DVI-I and TV-out for reporting connector subtype. The initial motivation for this feature came from i2c test [1]. It is supposed to be skipped on VGA connectors, but it cannot detect VGA over DP and fails instead. v2: - Ville: utilized drm_dp_is_branch() - Ville: implement DP 1.0 downstream type info - Replaced create_dp_properties with add_dp_subconnector_property - Added dp_set_subconnector_property helper [1]: https://bugs.freedesktop.org/show_bug.cgi?id=104097 Signed-off-by: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> --- drivers/gpu/drm/drm_connector.c | 49 +++++++++++++++++++++++- drivers/gpu/drm/drm_dp_helper.c | 68 +++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 3 ++ include/drm/drm_dp_helper.h | 8 ++++ include/drm/drm_mode_config.h | 6 +++ include/uapi/drm/drm_mode.h | 22 +++++++---- 6 files changed, 146 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 068d4b05f1be..0351c650c298 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -793,7 +793,7 @@ static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { - { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I, TV-out and DP */ { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ }; @@ -810,7 +810,7 @@ static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { - { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I, TV-out and DP */ { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ @@ -819,6 +819,19 @@ static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, drm_tv_subconnector_enum_list) +static const struct drm_prop_enum_list drm_dp_subconnector_enum_list[] = { + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I, TV-out and DP */ + { DRM_MODE_SUBCONNECTOR_VGA, "VGA" }, /* DP */ + { DRM_MODE_SUBCONNECTOR_DVI, "DVI" }, /* DP */ + { DRM_MODE_SUBCONNECTOR_HDMI, "HDMI" }, /* DP */ + { DRM_MODE_SUBCONNECTOR_DP, "DP" }, /* DP */ + { DRM_MODE_SUBCONNECTOR_Wireless, "Wireless" }, /* DP */ + { DRM_MODE_SUBCONNECTOR_Native, "Native" }, /* DP */ +}; + +DRM_ENUM_NAME_FN(drm_get_dp_subconnector_name, + drm_dp_subconnector_enum_list) + static const struct drm_prop_enum_list hdmi_colorspaces[] = { /* For Default case, driver will set the colorspace */ { DRM_MODE_COLORIMETRY_DEFAULT, "Default" }, @@ -1040,6 +1053,14 @@ static const struct drm_prop_enum_list hdmi_colorspaces[] = { * can also expose this property to external outputs, in which case they * must support "None", which should be the default (since external screens * have a built-in scaler). + * + * subconnector: + * This property is used by DVI-I, TVout and DisplayPort to indicate different + * connector subtypes. Enum values more or less match with those from main + * connector types. + * For DVI-I and TVout there is also a matching property "select subconnector" + * allowing to switch between signal types. + * DP subconnector corresponds to a downstream port. */ int drm_connector_create_standard_properties(struct drm_device *dev) @@ -1128,6 +1149,30 @@ int drm_mode_create_dvi_i_properties(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); +/** + * drm_mode_add_dp_subconnector_property - create subconnector property for DP + * @connector: drm_connector to attach property + * + * Called by a driver when DP connector is created. + */ +void drm_mode_add_dp_subconnector_property(struct drm_connector *connector) +{ + struct drm_mode_config mode_config = connector->dev->mode_config; + + if (!mode_config.dp_subconnector_property) + mode_config.dp_subconnector_property = + drm_property_create_enum(connector->dev, + DRM_MODE_PROP_IMMUTABLE, + "subconnector", + drm_dp_subconnector_enum_list, + ARRAY_SIZE(drm_dp_subconnector_enum_list)); + + drm_object_attach_property(&connector->base, + mode_config.dp_subconnector_property, + DRM_MODE_SUBCONNECTOR_Unknown); +} +EXPORT_SYMBOL(drm_mode_add_dp_subconnector_property); + /** * DOC: HDMI connector properties * diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 67f7f3e1997b..c2cc479b635d 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -661,6 +661,74 @@ void drm_dp_downstream_debug(struct seq_file *m, } EXPORT_SYMBOL(drm_dp_downstream_debug); +/** + * drm_dp_subconnector_type() - get DP branch device type + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * + */ +enum drm_mode_subconnector +drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]) +{ + int type; + bool branch_device_present = drm_dp_is_branch(dpcd); + + if (!branch_device_present) + return DRM_MODE_SUBCONNECTOR_Native; + /* DP 1.0 approach */ + if (dpcd[DP_DPCD_REV] == DP_DPCD_REV_10) { + type = dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DWN_STRM_PORT_TYPE_MASK; + if (type == DP_DWN_STRM_PORT_TYPE_DP) + return DRM_MODE_SUBCONNECTOR_DP; + return DRM_MODE_SUBCONNECTOR_Unknown; + } + type = port_cap[0] & DP_DS_PORT_TYPE_MASK; + + switch (type) { + case DP_DS_PORT_TYPE_DP: + case DP_DS_PORT_TYPE_DP_DUALMODE: + return DRM_MODE_SUBCONNECTOR_DP; + case DP_DS_PORT_TYPE_VGA: + return DRM_MODE_SUBCONNECTOR_VGA; + case DP_DS_PORT_TYPE_DVI: + return DRM_MODE_SUBCONNECTOR_DVI; + case DP_DS_PORT_TYPE_HDMI: + return DRM_MODE_SUBCONNECTOR_HDMI; + case DP_DS_PORT_TYPE_WIRELESS: + return DRM_MODE_SUBCONNECTOR_Wireless; + case DP_DS_PORT_TYPE_NON_EDID: + default: + return DRM_MODE_SUBCONNECTOR_Unknown; + } +} +EXPORT_SYMBOL(drm_dp_subconnector_type); + +/** + * drm_mode_set_dp_subconnector_property - set subconnector for DP connector + * @connector: dp connector to attach property + * @status: connector status which is about to be set + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * + * Called by a driver on every detect event. + */ +void drm_dp_set_subconnector_property(struct drm_connector *connector, + enum drm_connector_status status, + const u8 *dpcd, + const u8 port_cap[4]) +{ + enum drm_mode_subconnector subconnector = DRM_MODE_SUBCONNECTOR_Unknown; + + if (status == connector_status_connected) + subconnector = drm_dp_subconnector_type(dpcd, port_cap); + drm_object_property_set_value(&connector->base, + connector->dev->mode_config.dp_subconnector_property, + subconnector); +} +EXPORT_SYMBOL(drm_dp_set_subconnector_property); + /* * I2C-over-AUX implementation */ diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 4c30d751487a..f65292112307 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1483,9 +1483,12 @@ const char *drm_get_dvi_i_subconnector_name(int val); const char *drm_get_dvi_i_select_name(int val); const char *drm_get_tv_subconnector_name(int val); const char *drm_get_tv_select_name(int val); +const char *drm_get_dp_subconnector_name(int val); const char *drm_get_content_protection_name(int val); int drm_mode_create_dvi_i_properties(struct drm_device *dev); +void drm_mode_add_dp_subconnector_property(struct drm_connector *connector); + int drm_mode_create_tv_margin_properties(struct drm_device *dev); int drm_mode_create_tv_properties(struct drm_device *dev, unsigned int num_modes, diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index e0c157cde986..d0b2ae558dba 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -26,6 +26,7 @@ #include <linux/types.h> #include <linux/i2c.h> #include <linux/delay.h> +#include <drm/drm_connector.h> /* * Unless otherwise noted, all values are from the DP 1.1a spec. Note that @@ -1374,6 +1375,13 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]); void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4], struct drm_dp_aux *aux); +enum drm_mode_subconnector +drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]); +void drm_dp_set_subconnector_property(struct drm_connector *connector, + enum drm_connector_status status, + const u8 *dpcd, + const u8 port_cap[4]); void drm_dp_aux_init(struct drm_dp_aux *aux); int drm_dp_aux_register(struct drm_dp_aux *aux); diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index f57eea0481e0..607944641837 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -680,6 +680,12 @@ struct drm_mode_config { */ struct drm_property *dvi_i_select_subconnector_property; + /** + * @dp_subconnector_property: Optional DP property to differentiate + * between different DP downstream port types. + */ + struct drm_property *dp_subconnector_property; + /** * @tv_subconnector_property: Optional TV property to differentiate * between different TV connector types. diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 5ab331e5dc23..9808464bdb63 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -332,14 +332,20 @@ struct drm_mode_get_encoder { /* This is for connectors with multiple signal types. */ /* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ enum drm_mode_subconnector { - DRM_MODE_SUBCONNECTOR_Automatic = 0, - DRM_MODE_SUBCONNECTOR_Unknown = 0, - DRM_MODE_SUBCONNECTOR_DVID = 3, - DRM_MODE_SUBCONNECTOR_DVIA = 4, - DRM_MODE_SUBCONNECTOR_Composite = 5, - DRM_MODE_SUBCONNECTOR_SVIDEO = 6, - DRM_MODE_SUBCONNECTOR_Component = 8, - DRM_MODE_SUBCONNECTOR_SCART = 9, + DRM_MODE_SUBCONNECTOR_Automatic = 0, /* DVI-I, TV */ + DRM_MODE_SUBCONNECTOR_Unknown = 0, /* DVI-I, TV, DP */ + DRM_MODE_SUBCONNECTOR_VGA = 1, /* DP */ + DRM_MODE_SUBCONNECTOR_DVI = 2, /* DP */ + DRM_MODE_SUBCONNECTOR_DVID = 3, /* DVI-I */ + DRM_MODE_SUBCONNECTOR_DVIA = 4, /* DVI-I */ + DRM_MODE_SUBCONNECTOR_Composite = 5, /* TV */ + DRM_MODE_SUBCONNECTOR_SVIDEO = 6, /* TV */ + DRM_MODE_SUBCONNECTOR_Component = 8, /* TV */ + DRM_MODE_SUBCONNECTOR_SCART = 9, /* TV */ + DRM_MODE_SUBCONNECTOR_DP = 10, /* DP */ + DRM_MODE_SUBCONNECTOR_HDMI = 11, /* DP */ + DRM_MODE_SUBCONNECTOR_Native = 15, /* DP */ + DRM_MODE_SUBCONNECTOR_Wireless = 19, /* DP */ }; #define DRM_MODE_CONNECTOR_Unknown 0 -- 2.22.0 >From b289144e63f9a24c5f5dcdbcdd18c4e8b7547449 Mon Sep 17 00:00:00 2001 From: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> Date: Thu, 27 Jun 2019 17:45:49 +0300 Subject: [PATCH 4/6] drm/i915: utilize subconnector property for DP To: contact@xxxxxxxxxxx Since DP-specific information is stored in driver's structures, every driver needs to implement subconnector property by itself. Signed-off-by: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> v2: updates to match previous commit changes Signed-off-by: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_dp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index b8f8f40b4f3d..c5b4e33be355 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5421,6 +5421,10 @@ intel_dp_detect(struct drm_connector *connector, if (status != connector_status_connected && !intel_dp->is_mst) intel_dp_unset_edid(intel_dp); + drm_dp_set_subconnector_property(connector, + status, + intel_dp->dpcd, + intel_dp->downstream_ports); return status; } @@ -6317,6 +6321,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect struct drm_i915_private *dev_priv = to_i915(connector->dev); enum port port = dp_to_dig_port(intel_dp)->base.port; + drm_mode_add_dp_subconnector_property(connector); + if (!IS_G4X(dev_priv) && port != PORT_A) intel_attach_force_audio_property(connector); -- 2.22.0 >From f7346a1833049a493a3ec2d60903ab3d8dc17d27 Mon Sep 17 00:00:00 2001 From: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> Date: Mon, 8 Jul 2019 13:26:16 +0300 Subject: [PATCH 5/6] drm/nouveau: utilize subconnector property for DP To: contact@xxxxxxxxxxx Since DP-specific information is stored in driver's structures, every driver needs to implement subconnector property by itself. Signed-off-by: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> --- drivers/gpu/drm/nouveau/nouveau_connector.c | 13 +++++++++++++ drivers/gpu/drm/nouveau/nouveau_dp.c | 9 +++++++++ drivers/gpu/drm/nouveau/nouveau_encoder.h | 1 + 3 files changed, 23 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 4116ee62adaf..728949d803af 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -636,6 +636,17 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); + if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort || + connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + enum drm_mode_subconnector subconnector = DRM_MODE_SUBCONNECTOR_Unknown; + + if (conn_status == connector_status_connected && nv_encoder) + subconnector = nv_encoder->dp.subconnector; + drm_object_property_set_value(&connector->base, + connector->dev->mode_config.dp_subconnector_property, + subconnector); + } + return conn_status; } @@ -1357,6 +1368,8 @@ nouveau_connector_create(struct drm_device *dev, kfree(nv_connector); return ERR_PTR(ret); } + + drm_mode_add_dp_subconnector_property(connector); funcs = &nouveau_connector_funcs; break; default: diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 0d052e1660f8..7a87b0f808a7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -63,6 +63,7 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder) struct nouveau_drm *drm = nouveau_drm(dev); struct nvkm_i2c_aux *aux; u8 dpcd[8]; + u8 port_cap[DP_MAX_DOWNSTREAM_PORTS] = {0}; int ret; aux = nv_encoder->aux; @@ -73,6 +74,14 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder) if (ret) return ret; + if (dpcd[DP_DPCD_REV] > 0x10) { + ret = nvkm_rdaux(aux, DP_DOWNSTREAM_PORT_0, + port_cap, DP_MAX_DOWNSTREAM_PORTS); + if (ret) + memset(port_cap, 0, DP_MAX_DOWNSTREAM_PORTS); + } + nv_encoder->dp.subconnector = drm_dp_subconnector_type(dpcd, port_cap); + nv_encoder->dp.link_bw = 27000 * dpcd[1]; nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 3517f920bf89..e17971a30221 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -63,6 +63,7 @@ struct nouveau_encoder { struct nv50_mstm *mstm; int link_nr; int link_bw; + enum drm_mode_subconnector subconnector; } dp; }; -- 2.22.0 >From 460cb675f793e1ccae77039a3911645887b50196 Mon Sep 17 00:00:00 2001 From: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> Date: Mon, 8 Jul 2019 13:48:56 +0300 Subject: [PATCH 6/6] drm/amdgpu: utilize subconnector property for DP To: contact@xxxxxxxxxxx Since DP-specific information is stored in driver's structures, every driver needs to implement subconnector property by itself. Signed-off-by: Oleg Vasilev <oleg.vasilev@xxxxxxxxx> --- drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 1 + drivers/gpu/drm/amd/amdgpu/atombios_dp.c | 18 +++++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 73b2ede773d3..b8f33aa952ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -26,6 +26,7 @@ #include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_dp_helper.h> #include <drm/drm_probe_helper.h> #include <drm/amdgpu_drm.h> #include "amdgpu.h" @@ -1407,6 +1408,10 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force) pm_runtime_put_autosuspend(connector->dev->dev); } + drm_dp_set_subconnector_property(&amdgpu_connector->base, + ret, + amdgpu_dig_connector->dpcd, + amdgpu_dig_connector->downstream_ports); return ret; } @@ -1596,6 +1601,7 @@ amdgpu_connector_add(struct amdgpu_device *adev, drm_object_attach_property(&amdgpu_connector->base.base, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_NONE); + drm_mode_add_dp_subconnector_property(&amdgpu_connector->base); break; case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_DVID: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index eb9975f4decb..cb360b44371c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -469,6 +469,7 @@ struct amdgpu_encoder { struct amdgpu_connector_atom_dig { /* displayport */ u8 dpcd[DP_RECEIVER_CAP_SIZE]; + u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; u8 dp_sink_type; int dp_clock; int dp_lane_count; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c index 6858cde9fc5d..b0d414553e71 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c @@ -334,6 +334,22 @@ static void amdgpu_atombios_dp_probe_oui(struct amdgpu_connector *amdgpu_connect buf[0], buf[1], buf[2]); } +static void amdgpu_atombios_dp_ds_ports(struct amdgpu_connector *amdgpu_connector) +{ + struct amdgpu_connector_atom_dig *dig_connector = amdgpu_connector->con_priv; + int ret; + + if (dig_connector->dpcd[DP_DPCD_REV] > 0x10) { + ret = drm_dp_dpcd_read(&amdgpu_connector->ddc_bus->aux, + DP_DOWNSTREAM_PORT_0, + dig_connector->downstream_ports, + DP_MAX_DOWNSTREAM_PORTS); + if (ret) + memset(dig_connector->downstream_ports, 0, + DP_MAX_DOWNSTREAM_PORTS); + } +} + int amdgpu_atombios_dp_get_dpcd(struct amdgpu_connector *amdgpu_connector) { struct amdgpu_connector_atom_dig *dig_connector = amdgpu_connector->con_priv; @@ -349,7 +365,7 @@ int amdgpu_atombios_dp_get_dpcd(struct amdgpu_connector *amdgpu_connector) dig_connector->dpcd); amdgpu_atombios_dp_probe_oui(amdgpu_connector); - + amdgpu_atombios_dp_ds_ports(amdgpu_connector); return 0; } -- 2.22.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx