Commit 42f2562c authored by Ville Syrjälä's avatar Ville Syrjälä
Browse files

drm/dp: Pimp drm_dp_downstream_max_bpc()



Deal with more cases in drm_dp_downstream_max_bpc():
- DPCD 1.0 -> assume 8bpc for non-DP
- DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything
- DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap
- anything else -> assume 8bpc

v2: Use Returns: for kdoc (Lyude)

Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-8-ville.syrjala@linux.intel.com


Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 38784f6f
Loading
Loading
Loading
Loading
+36 −23
Original line number Diff line number Diff line
@@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
EXPORT_SYMBOL(drm_dp_downstream_max_clock);

/**
 * drm_dp_downstream_max_bpc() - extract branch device max
 * drm_dp_downstream_max_bpc() - extract downstream facing port max
 *                               bits per component
 * @dpcd: DisplayPort configuration data
 * @port_cap: port capabilities
 *
 * See also:
 * drm_dp_read_downstream_info()
 * drm_dp_downstream_max_clock()
 * @port_cap: downstream facing port capabilities
 * @edid: EDID
 *
 * Returns: Max bpc on success or 0 if max bpc not defined
 */
int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
			      const u8 port_cap[4])
			      const u8 port_cap[4],
			      const struct edid *edid)
{
	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
		DP_DETAILED_CAP_INFO_AVAILABLE;
	int bpc;
	if (!drm_dp_is_branch(dpcd))
		return 0;

	if (!detailed_cap_info)
	if (dpcd[DP_DPCD_REV] < 0x11) {
		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
		case DP_DWN_STRM_PORT_TYPE_DP:
			return 0;
		default:
			return 8;
		}
	}

	switch (type) {
	case DP_DS_PORT_TYPE_VGA:
	case DP_DS_PORT_TYPE_DVI:
	case DP_DS_PORT_TYPE_HDMI:
	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
	case DP_DS_PORT_TYPE_DP:
		return 0;
	case DP_DS_PORT_TYPE_DP_DUALMODE:
		bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
		if (is_edid_digital_input_dp(edid))
			return 0;
		fallthrough;
	case DP_DS_PORT_TYPE_HDMI:
	case DP_DS_PORT_TYPE_DVI:
	case DP_DS_PORT_TYPE_VGA:
		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
			return 8;

		switch (bpc) {
		switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
		case DP_DS_8BPC:
			return 8;
		case DP_DS_10BPC:
@@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
			return 12;
		case DP_DS_16BPC:
			return 16;
		default:
			return 8;
		}
		fallthrough;
		break;
	default:
		return 0;
		return 8;
	}
}
EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
@@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id);
 * @m: pointer for debugfs file
 * @dpcd: DisplayPort configuration data
 * @port_cap: port capabilities
 * @edid: EDID
 * @aux: DisplayPort AUX channel
 *
 */
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)
			     const u8 port_cap[4],
			     const struct edid *edid,
			     struct drm_dp_aux *aux)
{
	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
				 DP_DETAILED_CAP_INFO_AVAILABLE;
@@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m,
				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
		}

		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);

		if (bpc > 0)
			seq_printf(m, "\t\tMax bpc: %d\n", bpc);
+2 −1
Original line number Diff line number Diff line
@@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m,
{
	struct intel_encoder *intel_encoder = intel_attached_encoder(intel_connector);
	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
	const struct drm_property_blob *edid = intel_connector->base.edid_blob_ptr;

	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
	seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
@@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m,
		intel_panel_info(m, &intel_connector->panel);

	drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
				&intel_dp->aux);
				edid ? edid->data : NULL, &intel_dp->aux);
}

static void intel_dp_mst_info(struct seq_file *m,
+1 −1
Original line number Diff line number Diff line
@@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)

	intel_dp->dfp.max_bpc =
		drm_dp_downstream_max_bpc(intel_dp->dpcd,
					  intel_dp->downstream_ports);
					  intel_dp->downstream_ports, edid);

	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
		    connector->base.base.id, connector->base.name,
+7 −3
Original line number Diff line number Diff line
@@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
				const u8 port_cap[4]);
int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
			      const u8 port_cap[4]);
			      const u8 port_cap[4],
			      const struct edid *edid);
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);
void drm_dp_downstream_debug(struct seq_file *m,
			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
			     const u8 port_cap[4],
			     const struct edid *edid,
			     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]);