diff options
| -rw-r--r-- | drivers/gpu/drm/drm_dp_helper.c | 54 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_edid.c | 28 | ||||
| -rw-r--r-- | include/drm/drm_dp_helper.h | 12 | ||||
| -rw-r--r-- | include/drm/drm_edid.h | 4 | 
4 files changed, 98 insertions, 0 deletions
| diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 5d8c9bd700c9..63ac94c54e95 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -809,6 +809,60 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);  /** + * drm_dp_downstream_mode() - return a mode for downstream facing port + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * + * Provides a suitable mode for downstream facing ports without EDID. + * + * Returns: A new drm_display_mode on success or NULL on failure + */ +struct drm_display_mode * +drm_dp_downstream_mode(struct drm_device *dev, +		       const u8 dpcd[DP_RECEIVER_CAP_SIZE], +		       const u8 port_cap[4]) + +{ +	u8 vic; + +	if (!drm_dp_is_branch(dpcd)) +		return NULL; + +	if (dpcd[DP_DPCD_REV] < 0x11) +		return NULL; + +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) { +	case DP_DS_PORT_TYPE_NON_EDID: +		switch (port_cap[0] & DP_DS_NON_EDID_MASK) { +		case DP_DS_NON_EDID_720x480i_60: +			vic = 6; +			break; +		case DP_DS_NON_EDID_720x480i_50: +			vic = 21; +			break; +		case DP_DS_NON_EDID_1920x1080i_60: +			vic = 5; +			break; +		case DP_DS_NON_EDID_1920x1080i_50: +			vic = 20; +			break; +		case DP_DS_NON_EDID_1280x720_60: +			vic = 4; +			break; +		case DP_DS_NON_EDID_1280x720_50: +			vic = 19; +			break; +		default: +			return NULL; +		} +		return drm_display_mode_from_cea_vic(dev, vic); +	default: +		return NULL; +	} +} +EXPORT_SYMBOL(drm_dp_downstream_mode); + +/**   * drm_dp_downstream_id() - identify branch device   * @aux: DisplayPort AUX channel   * @id: DisplayPort branch device id diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 6840f0530a38..a82f37d44258 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3738,6 +3738,34 @@ drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)  	bitmap_set(hdmi->y420_cmdb_modes, vic, 1);  } +/** + * drm_display_mode_from_cea_vic() - return a mode for CEA VIC + * @dev: DRM device + * @vic: CEA VIC of the mode + * + * Creates a new mode matching the specified CEA VIC. + * + * Returns: A new drm_display_mode on success or NULL on failure + */ +struct drm_display_mode * +drm_display_mode_from_cea_vic(struct drm_device *dev, +			      u8 video_code) +{ +	const struct drm_display_mode *cea_mode; +	struct drm_display_mode *newmode; + +	cea_mode = cea_mode_for_vic(video_code); +	if (!cea_mode) +		return NULL; + +	newmode = drm_mode_duplicate(dev, cea_mode); +	if (!newmode) +		return NULL; + +	return newmode; +} +EXPORT_SYMBOL(drm_display_mode_from_cea_vic); +  static int  do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)  { diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 6812a3e0de8d..fbba4a0f7366 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -28,6 +28,8 @@  #include <linux/types.h>  #include <drm/drm_connector.h> +struct drm_device; +  /*   * Unless otherwise noted, all values are from the DP 1.1a spec.  Note that   * DP and DPCD versions are independent.  Differences from 1.0 are not noted, @@ -385,6 +387,13 @@  # define DP_DS_PORT_TYPE_DP_DUALMODE        5  # define DP_DS_PORT_TYPE_WIRELESS           6  # define DP_DS_PORT_HPD			    (1 << 3) +# define DP_DS_NON_EDID_MASK		    (0xf << 4) +# define DP_DS_NON_EDID_720x480i_60	    (1 << 4) +# define DP_DS_NON_EDID_720x480i_50	    (2 << 4) +# define DP_DS_NON_EDID_1920x1080i_60	    (3 << 4) +# define DP_DS_NON_EDID_1920x1080i_50	    (4 << 4) +# define DP_DS_NON_EDID_1280x720_60	    (5 << 4) +# define DP_DS_NON_EDID_1280x720_50	    (7 << 4)  /* offset 1 for VGA is maximum megapixels per second / 8 */  /* offset 1 for DVI/HDMI is maximum TMDS clock in Mbps / 2.5 */  /* offset 2 for VGA/DVI/HDMI */ @@ -1654,6 +1663,9 @@ int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],  			      const u8 port_cap[4],  			      const struct edid *edid); +struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev, +						const u8 dpcd[DP_RECEIVER_CAP_SIZE], +						const u8 port_cap[4]);  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], diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index cfa4f5af49af..b27a0e2169c8 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -517,4 +517,8 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name,  struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,  					   int hsize, int vsize, int fresh,  					   bool rb); +struct drm_display_mode * +drm_display_mode_from_cea_vic(struct drm_device *dev, +			      u8 video_code); +  #endif /* __DRM_EDID_H__ */ | 
