[Intel-gfx] [PATCH 1/2] drm: report dp downstream port type as a subconnector property
Ville Syrjälä
ville.syrjala at linux.intel.com
Tue Jul 2 12:36:08 UTC 2019
On Mon, Jul 01, 2019 at 11:00:21AM +0300, Oleg Vasilev wrote:
> 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.
>
> [1]: https://bugs.freedesktop.org/show_bug.cgi?id=104097
> Signed-off-by: Oleg Vasilev <oleg.vasilev at intel.com>
> ---
> drivers/gpu/drm/drm_connector.c | 38 +++++++++++++++++++++++++++++++--
> drivers/gpu/drm/drm_dp_helper.c | 36 +++++++++++++++++++++++++++++++
> include/drm/drm_connector.h | 2 ++
> include/drm/drm_dp_helper.h | 3 +++
> include/drm/drm_mode_config.h | 6 ++++++
> include/uapi/drm/drm_mode.h | 22 ++++++++++++-------
> 6 files changed, 97 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 068d4b05f1be..95cd51254be6 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" },
> @@ -1128,6 +1141,27 @@ int drm_mode_create_dvi_i_properties(struct drm_device *dev)
> }
> EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
>
> +/**
> + * drm_mode_create_dp_properties - create DP specific connector properties
> + * @dev: DRM device
> + *
> + * Called by a driver the first time a DP connector is made.
> + */
> +void drm_mode_create_dp_properties(struct drm_device *dev)
> +{
> + struct drm_property *dp_subconnector;
> +
> + if (dev->mode_config.dp_subconnector_property)
> + return;
> +
> + dp_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
> + "subconnector",
> + drm_dp_subconnector_enum_list,
> + ARRAY_SIZE(drm_dp_subconnector_enum_list));
> + dev->mode_config.dp_subconnector_property = dp_subconnector;
> +}
> +EXPORT_SYMBOL(drm_mode_create_dp_properties);
> +
> /**
> * DOC: HDMI connector properties
> *
> diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> index 0b994d083a89..63d8f0b8492c 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -662,6 +662,42 @@ void drm_dp_downstream_debug(struct seq_file *m,
> }
> EXPORT_SYMBOL(drm_dp_downstream_debug);
>
> +/**
> + * drm_dp_downstream_subconnector_type() - get DP branch device type
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + *
> + */
> +enum drm_mode_subconnector
> +drm_dp_downstream_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> + const u8 port_cap[4])
> +{
> + int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
> + bool branch_device_present = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> + DP_DWN_STRM_PORT_PRESENT;
drm_dp_is_branch()
> +
> + if (!branch_device_present)
> + return DRM_MODE_SUBCONNECTOR_Native;
> +
> + 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;
> + }
DPCD 1.0 doesn't have the downstream port information at 0x80.
For those you have to rely on DP_DWN_STRM_PORT_TYPE_MASK & co.
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_subconnector_type);
> +
> /*
> * I2C-over-AUX implementation
> */
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 4c30d751487a..66f0b2a59c9c 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -1483,9 +1483,11 @@ 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_create_dp_properties(struct drm_device *dev);
> 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 397896b5b21a..38792c1afed8 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1372,6 +1372,9 @@ 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_downstream_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> + 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 759d462d028b..957d99a34843 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
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Ville Syrjälä
Intel
More information about the Intel-gfx
mailing list