b/drivers/gpu/drm/i915/intel_display.c
@@ -12018,12 +12018,24 @@ connected_sink_compute_bpp(struct
intel_connector *connector,
if (connector->base.display_info.bpc == 0) {
int type = connector->base.connector_type;
int clamp_bpp = 24;
+ int legacy_bpc = 0;
/* Fall back to 18 bpp when DP sink capability is unknown. */
if (type == DRM_MODE_CONNECTOR_DisplayPort ||
type == DRM_MODE_CONNECTOR_eDP)
clamp_bpp = 18;
+ /* On DP to legacy converter, try harder to find sink bpc */
+ if (type == DRM_MODE_CONNECTOR_DisplayPort) {
+ legacy_bpc = intel_dp_legacy_bpc(&connector->base);
+
+ if (legacy_bpc) {
+ DRM_DEBUG_KMS("DP to VGA/DVI/HDMI converter with bpc %d\n",
+ legacy_bpc);
+ clamp_bpp = 3 * legacy_bpc;
+ }
+ }
+
if (bpp > clamp_bpp) {
DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of %d\n",
bpp, clamp_bpp);
b/drivers/gpu/drm/i915/intel_dp.c
@@ -6117,3 +6117,59 @@ void intel_dp_mst_resume(struct drm_device *dev)
}
}
}
+
+/* XXX Needs work for more than 1 downstream port */
+int intel_dp_legacy_bpc(struct drm_connector *connector)
+{
+ struct intel_dp *intel_dp = intel_attached_dp(connector);
+ uint8_t *dpcd = intel_dp->dpcd;
+ uint8_t type;
+ int bpc = 0;
+
+ /* if there's no downstream port, then this can't be DP->legacy */
+ if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
+ return bpc;
+
+ /* Basic type of downstream ports */
+ type = intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
+ DP_DWN_STRM_PORT_TYPE_MASK;
+
+ /*
+ * Lacking other info, 8 bpc is a reasonable start for analog out.
+ * E.g., Apple MiniDP->VGA adaptors don't provide more info than
+ * that. Despite having DP_DPCD_REV == 0x11 their downstream_ports
+ * descriptor is empty - all zeros.
+ */
+ if (type == DP_DWN_STRM_PORT_TYPE_ANALOG)
+ bpc = 8;
+
+ if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
+ return bpc;
+
+ /* Rev 1.1+. More specific downstream port type available */
+ type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
+
+ /* VGA, DVI and HDMI support at least 8 bpc */
+ if (type == DP_DS_PORT_TYPE_VGA || type == DP_DS_PORT_TYPE_DVI ||
+ type == DP_DS_PORT_TYPE_HDMI)
+ bpc = 8;
+
+ /* As of DP interop v1.1a only VGA defines additional detail */
+ if (type != DP_DS_PORT_TYPE_VGA ||
+ !(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE))
+ return bpc;
+
+ /* VGA with DP_DETAILED_CAP_INFO_AVAILABLE provides bpc info */
+ switch (intel_dp->downstream_ports[2] & DP_DS_VGA_MAX_BPC_MASK) {
+ case DP_DS_VGA_8BPC:
+ return 8;
+ case DP_DS_VGA_10BPC:
+ return 10;
+ case DP_DS_VGA_12BPC:
+ return 12;
+ case DP_DS_VGA_16BPC:
+ return 16;
+ }
+
+ return bpc;
+}
b/drivers/gpu/drm/i915/intel_drv.h
@@ -1253,6 +1253,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
void intel_dp_add_properties(struct intel_dp *intel_dp, struct
drm_connector *connector);
void intel_dp_mst_suspend(struct drm_device *dev);
void intel_dp_mst_resume(struct drm_device *dev);
+int intel_dp_legacy_bpc(struct drm_connector *connector);
int intel_dp_max_link_rate(struct intel_dp *intel_dp);
int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);