diff options
Diffstat (limited to 'drivers/gpu/drm/display')
| -rw-r--r-- | drivers/gpu/drm/display/Kconfig | 52 | ||||
| -rw-r--r-- | drivers/gpu/drm/display/Makefile | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/display/drm_dp_helper.c | 41 | ||||
| -rw-r--r-- | drivers/gpu/drm/display/drm_dp_helper_internal.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/display/drm_dp_mst_topology.c | 42 | ||||
| -rw-r--r-- | drivers/gpu/drm/display/drm_dp_mst_topology_internal.h | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/display/drm_dp_tunnel.c | 17 | 
7 files changed, 114 insertions, 50 deletions
| diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig index c0f56888c328..864a6488bfdf 100644 --- a/drivers/gpu/drm/display/Kconfig +++ b/drivers/gpu/drm/display/Kconfig @@ -1,15 +1,36 @@  # SPDX-License-Identifier: MIT -config DRM_DP_AUX_BUS +config DRM_DISPLAY_HELPER  	tristate  	depends on DRM -	depends on OF || COMPILE_TEST +	help +	  DRM helpers for display adapters. -config DRM_DISPLAY_HELPER +config DRM_DISPLAY_DP_AUX_BUS  	tristate  	depends on DRM +	depends on OF || COMPILE_TEST + +config DRM_DISPLAY_DP_AUX_CEC +	bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support" +	depends on DRM && DRM_DISPLAY_HELPER +	select DRM_DISPLAY_DP_HELPER +	select CEC_CORE  	help -	  DRM helpers for display adapters. +	  Choose this option if you want to enable HDMI CEC support for +	  DisplayPort/USB-C to HDMI adapters. + +	  Note: not all adapters support this feature, and even for those +	  that do support this they often do not hook up the CEC pin. + +config DRM_DISPLAY_DP_AUX_CHARDEV +	bool "DRM DP AUX Interface" +	depends on DRM && DRM_DISPLAY_HELPER +	select DRM_DISPLAY_DP_HELPER +	help +	  Choose this option to enable a /dev/drm_dp_auxN node that allows to +	  read and write values to arbitrary DPCD registers on the DP aux +	  channel.  config DRM_DISPLAY_DP_HELPER  	bool @@ -25,7 +46,7 @@ config DRM_DISPLAY_DP_TUNNEL  	  DP tunnel features like the Bandwidth Allocation mode to maximize the  	  BW utilization for display streams on Thunderbolt links. -config DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE +config DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG  	bool "Enable debugging the DP tunnel state"  	depends on REF_TRACKER  	depends on DRM_DISPLAY_DP_TUNNEL @@ -49,24 +70,3 @@ config DRM_DISPLAY_HDMI_HELPER  	depends on DRM_DISPLAY_HELPER  	help  	  DRM display helpers for HDMI. - -config DRM_DP_AUX_CHARDEV -	bool "DRM DP AUX Interface" -	depends on DRM && DRM_DISPLAY_HELPER -	select DRM_DISPLAY_DP_HELPER -	help -	  Choose this option to enable a /dev/drm_dp_auxN node that allows to -	  read and write values to arbitrary DPCD registers on the DP aux -	  channel. - -config DRM_DP_CEC -	bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support" -	depends on DRM && DRM_DISPLAY_HELPER -	select DRM_DISPLAY_DP_HELPER -	select CEC_CORE -	help -	  Choose this option if you want to enable HDMI CEC support for -	  DisplayPort/USB-C to HDMI adapters. - -	  Note: not all adapters support this feature, and even for those -	  that do support this they often do not hook up the CEC pin. diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile index 7ca61333c669..17d2cc73ff56 100644 --- a/drivers/gpu/drm/display/Makefile +++ b/drivers/gpu/drm/display/Makefile @@ -1,6 +1,6 @@  # SPDX-License-Identifier: MIT -obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o +obj-$(CONFIG_DRM_DISPLAY_DP_AUX_BUS) += drm_dp_aux_bus.o  drm_display_helper-y := drm_display_helper_mod.o  drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += \ @@ -14,7 +14,7 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o  drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \  	drm_hdmi_helper.o \  	drm_scdc_helper.o -drm_display_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o -drm_display_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o +drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV) += drm_dp_aux_dev.o +drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_AUX_CEC) += drm_dp_cec.o  obj-$(CONFIG_DRM_DISPLAY_HELPER) += drm_display_helper.o diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index f5d4be897866..79a615667aab 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -2113,7 +2113,7 @@ EXPORT_SYMBOL(drm_dp_aux_init);   * drm_dp_aux_register() in &drm_connector_funcs.late_register, and likewise to   * call drm_dp_aux_unregister() in &drm_connector_funcs.early_unregister.   * Functions which don't follow this will likely Oops when - * %CONFIG_DRM_DP_AUX_CHARDEV is enabled. + * %CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV is enabled.   *   * For devices where the AUX channel is a device that exists independently of   * the &drm_device that uses it, such as SoCs and bridge devices, it is @@ -2281,6 +2281,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {  	{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) },  	/* Synaptics DP1.4 MST hubs require DSC for some modes on which it applies HBLANK expansion. */  	{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) }, +	/* MediaTek panels (at least in U3224KBA) require DSC for modes with a short HBLANK on UHBR links. */ +	{ OUI(0x00, 0x0C, 0xE7), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) },  	/* Apple MacBookPro 2017 15 inch eDP Retina panel reports too low DP_MAX_LINK_RATE */  	{ OUI(0x00, 0x10, 0xfa), DEVICE_ID(101, 68, 21, 101, 98, 97), false, BIT(DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS) },  }; @@ -2948,6 +2950,43 @@ void drm_dp_vsc_sdp_log(struct drm_printer *p, const struct drm_dp_vsc_sdp *vsc)  }  EXPORT_SYMBOL(drm_dp_vsc_sdp_log); +void drm_dp_as_sdp_log(struct drm_printer *p, const struct drm_dp_as_sdp *as_sdp) +{ +	drm_printf(p, "DP SDP: AS_SDP, revision %u, length %u\n", +		   as_sdp->revision, as_sdp->length); +	drm_printf(p, "    vtotal: %d\n", as_sdp->vtotal); +	drm_printf(p, "    target_rr: %d\n", as_sdp->target_rr); +	drm_printf(p, "    duration_incr_ms: %d\n", as_sdp->duration_incr_ms); +	drm_printf(p, "    duration_decr_ms: %d\n", as_sdp->duration_decr_ms); +	drm_printf(p, "    operation_mode: %d\n", as_sdp->mode); +} +EXPORT_SYMBOL(drm_dp_as_sdp_log); + +/** + * drm_dp_as_sdp_supported() - check if adaptive sync sdp is supported + * @aux: DisplayPort AUX channel + * @dpcd: DisplayPort configuration data + * + * Returns true if adaptive sync sdp is supported, else returns false + */ +bool drm_dp_as_sdp_supported(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ +	u8 rx_feature; + +	if (dpcd[DP_DPCD_REV] < DP_DPCD_REV_13) +		return false; + +	if (drm_dp_dpcd_readb(aux, DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1, +			      &rx_feature) != 1) { +		drm_dbg_dp(aux->drm_dev, +			   "Failed to read DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1\n"); +		return false; +	} + +	return (rx_feature & DP_ADAPTIVE_SYNC_SDP_SUPPORTED); +} +EXPORT_SYMBOL(drm_dp_as_sdp_supported); +  /**   * drm_dp_vsc_sdp_supported() - check if vsc sdp is supported   * @aux: DisplayPort AUX channel diff --git a/drivers/gpu/drm/display/drm_dp_helper_internal.h b/drivers/gpu/drm/display/drm_dp_helper_internal.h index 8917fc3af9ec..737949a2820f 100644 --- a/drivers/gpu/drm/display/drm_dp_helper_internal.h +++ b/drivers/gpu/drm/display/drm_dp_helper_internal.h @@ -5,7 +5,7 @@  struct drm_dp_aux; -#ifdef CONFIG_DRM_DP_AUX_CHARDEV +#ifdef CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV  int drm_dp_aux_dev_init(void);  void drm_dp_aux_dev_exit(void);  int drm_dp_aux_register_devnode(struct drm_dp_aux *aux); diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 03d528209426..3577786b5db2 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -2274,7 +2274,7 @@ drm_dp_mst_port_add_connector(struct drm_dp_mst_branch *mstb,  	if (port->pdt != DP_PEER_DEVICE_NONE &&  	    drm_dp_mst_is_end_device(port->pdt, port->mcs) && -	    port->port_num >= DP_MST_LOGICAL_PORT_0) +	    drm_dp_mst_port_is_logical(port))  		port->cached_edid = drm_edid_read_ddc(port->connector,  						      &port->aux.ddc); @@ -3608,24 +3608,30 @@ fixed20_12 drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr,  EXPORT_SYMBOL(drm_dp_get_vc_payload_bw);  /** - * drm_dp_read_mst_cap() - check whether or not a sink supports MST + * drm_dp_read_mst_cap() - Read the sink's MST mode capability   * @aux: The DP AUX channel to use   * @dpcd: A cached copy of the DPCD capabilities for this sink   * - * Returns: %True if the sink supports MST, %false otherwise + * Returns: enum drm_dp_mst_mode to indicate MST mode capability   */ -bool drm_dp_read_mst_cap(struct drm_dp_aux *aux, -			 const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +enum drm_dp_mst_mode drm_dp_read_mst_cap(struct drm_dp_aux *aux, +					 const u8 dpcd[DP_RECEIVER_CAP_SIZE])  {  	u8 mstm_cap;  	if (dpcd[DP_DPCD_REV] < DP_DPCD_REV_12) -		return false; +		return DRM_DP_SST;  	if (drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &mstm_cap) != 1) -		return false; +		return DRM_DP_SST; + +	if (mstm_cap & DP_MST_CAP) +		return DRM_DP_MST; -	return mstm_cap & DP_MST_CAP; +	if (mstm_cap & DP_SINGLE_STREAM_SIDEBAND_MSG) +		return DRM_DP_SST_SIDEBAND_MSG; + +	return DRM_DP_SST;  }  EXPORT_SYMBOL(drm_dp_read_mst_cap); @@ -4213,7 +4219,7 @@ drm_dp_mst_detect_port(struct drm_connector *connector,  	case DP_PEER_DEVICE_SST_SINK:  		ret = connector_status_connected;  		/* for logical ports - cache the EDID */ -		if (port->port_num >= DP_MST_LOGICAL_PORT_0 && !port->cached_edid) +		if (drm_dp_mst_port_is_logical(port) && !port->cached_edid)  			port->cached_edid = drm_edid_read_ddc(connector, &port->aux.ddc);  		break;  	case DP_PEER_DEVICE_DP_LEGACY_CONV: @@ -5977,7 +5983,7 @@ static bool drm_dp_mst_is_virtual_dpcd(struct drm_dp_mst_port *port)  		return false;  	/* Virtual DP Sink (Internal Display Panel) */ -	if (port->port_num >= 8) +	if (drm_dp_mst_port_is_logical(port))  		return true;  	/* DP-to-HDMI Protocol Converter */ @@ -6005,6 +6011,22 @@ static bool drm_dp_mst_is_virtual_dpcd(struct drm_dp_mst_port *port)  }  /** + * drm_dp_mst_aux_for_parent() - Get the AUX device for an MST port's parent + * @port: MST port whose parent's AUX device is returned + * + * Return the AUX device for @port's parent or NULL if port's parent is the + * root port. + */ +struct drm_dp_aux *drm_dp_mst_aux_for_parent(struct drm_dp_mst_port *port) +{ +	if (!port->parent || !port->parent->port_parent) +		return NULL; + +	return &port->parent->port_parent->aux; +} +EXPORT_SYMBOL(drm_dp_mst_aux_for_parent); + +/**   * drm_dp_mst_dsc_aux_for_port() - Find the correct aux for DSC   * @port: The port to check. A leaf of the MST tree with an attached display.   * diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology_internal.h b/drivers/gpu/drm/display/drm_dp_mst_topology_internal.h index a785ccbfdd73..f41c34e26be2 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology_internal.h +++ b/drivers/gpu/drm/display/drm_dp_mst_topology_internal.h @@ -10,7 +10,9 @@  #ifndef _DRM_DP_MST_HELPER_INTERNAL_H_  #define _DRM_DP_MST_HELPER_INTERNAL_H_ -#include <drm/display/drm_dp_mst_helper.h> +struct drm_dp_sideband_msg_req_body; +struct drm_dp_sideband_msg_tx; +struct drm_printer;  void  drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req, diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c b/drivers/gpu/drm/display/drm_dp_tunnel.c index 120e0de674c1..48b2df120086 100644 --- a/drivers/gpu/drm/display/drm_dp_tunnel.c +++ b/drivers/gpu/drm/display/drm_dp_tunnel.c @@ -191,7 +191,7 @@ struct drm_dp_tunnel_mgr {  	struct drm_dp_tunnel_group *groups;  	wait_queue_head_t bw_req_queue; -#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE +#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG  	struct ref_tracker_dir ref_tracker;  #endif  }; @@ -385,7 +385,7 @@ static void tunnel_put(struct drm_dp_tunnel *tunnel)  	kref_put(&tunnel->kref, free_tunnel);  } -#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE +#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG  static void track_tunnel_ref(struct drm_dp_tunnel *tunnel,  			     struct ref_tracker **tracker)  { @@ -436,8 +436,8 @@ EXPORT_SYMBOL(drm_dp_tunnel_get);  /**   * drm_dp_tunnel_put - Put a reference for a DP tunnel - * @tunnel - Tunnel object - * @tracker - Debug tracker for the reference + * @tunnel: Tunnel object + * @tracker: Debug tracker for the reference   *   * Put a reference for @tunnel along with its debug *@tracker, which   * was obtained with drm_dp_tunnel_get(). @@ -1170,7 +1170,7 @@ int drm_dp_tunnel_alloc_bw(struct drm_dp_tunnel *tunnel, int bw)  EXPORT_SYMBOL(drm_dp_tunnel_alloc_bw);  /** - * drm_dp_tunnel_atomic_get_allocated_bw - Get the BW allocated for a DP tunnel + * drm_dp_tunnel_get_allocated_bw - Get the BW allocated for a DP tunnel   * @tunnel: Tunnel object   *   * Get the current BW allocated for @tunnel. After the tunnel is created / @@ -1603,7 +1603,7 @@ static void cleanup_group(struct drm_dp_tunnel_group *group)  	drm_atomic_private_obj_fini(&group->base);  } -#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE +#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG  static void check_unique_stream_ids(const struct drm_dp_tunnel_group_state *group_state)  {  	const struct drm_dp_tunnel_state *tunnel_state; @@ -1881,7 +1881,7 @@ static void destroy_mgr(struct drm_dp_tunnel_mgr *mgr)  		drm_WARN_ON(mgr->dev, !list_empty(&mgr->groups[i].tunnels));  	} -#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE +#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG  	ref_tracker_dir_exit(&mgr->ref_tracker);  #endif @@ -1892,6 +1892,7 @@ static void destroy_mgr(struct drm_dp_tunnel_mgr *mgr)  /**   * drm_dp_tunnel_mgr_create - Create a DP tunnel manager   * @dev: DRM device object + * @max_group_count: Maximum number of tunnel groups   *   * Creates a DP tunnel manager for @dev.   * @@ -1918,7 +1919,7 @@ drm_dp_tunnel_mgr_create(struct drm_device *dev, int max_group_count)  		return NULL;  	} -#ifdef CONFIG_DRM_DISPLAY_DEBUG_DP_TUNNEL_STATE +#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG  	ref_tracker_dir_init(&mgr->ref_tracker, 16, "dptun");  #endif | 
