From: Dave Airlie <airlied@xxxxxxxxxx> This patches the EDID to add the special mode. TODO make this more generic. Signed-off-by: Dave Airlie <airlied@xxxxxxxxxx> --- drivers/gpu/drm/drm_dp_mst_topology.c | 13 ++++++++++--- drivers/gpu/drm/drm_edid.c | 36 +++++++++++++++++++++++++++++++++++ include/drm/drm_edid.h | 5 ++++- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 1f15d85..08b7140 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -31,6 +31,7 @@ #include <drm/drmP.h> #include <drm/drm_fixed.h> +#include <drm/drm_edid.h> /** * DOC: dp mst helper @@ -2225,9 +2226,15 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_ goto out; } } - if (port->cached_edid) - edid = drm_edid_duplicate(port->cached_edid); - else + if (port->cached_edid) { + if (connector->has_tile && connector->tile_is_single_monitor) { + edid = drm_patch_edid_detailed_mode(connector->dev, + port->cached_edid, + 3840, 2160, 60); + } else { + edid = drm_edid_duplicate(port->cached_edid); + } + } else edid = drm_get_edid(connector, &port->aux.ddc); out: drm_dp_put_port(port); diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 94e8a57..3ccc2c6 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3892,3 +3892,39 @@ void drm_get_displayid(struct drm_connector *connector, return; } EXPORT_SYMBOL(drm_get_displayid); + +static void drm_patch_edid_reset_csum(struct edid *edid) +{ + unsigned i, sum = 0; + unsigned char *p = (unsigned char *)edid; + + for (i = 0; i < EDID_LENGTH - 1; i++) + sum += p[i]; + edid->checksum = (0x100 - (sum & 0xff)) & 0xff; +} + +struct edid *drm_patch_edid_detailed_mode(struct drm_device *dev, + struct edid *orig_edid, + int hdisplay, int vdisplay, int vrefresh) +{ + struct edid *edid = drm_edid_duplicate(orig_edid); + struct drm_display_mode *mode = drm_cvt_mode(dev, hdisplay, vdisplay, vrefresh, true, false, false); + + int hblank = mode->htotal - mode->hdisplay; + int vblank = mode->vtotal - mode->vdisplay; + + DRM_DEBUG_KMS("mode->clock is %d, %d\n", mode->clock, cpu_to_le16(mode->clock / 10)); + edid->detailed_timings[1] = edid->detailed_timings[0]; + edid->detailed_timings[0].pixel_clock = cpu_to_le16(mode->clock / 10); + edid->detailed_timings[0].data.pixel_data.hactive_lo = mode->hdisplay & 0xff; + edid->detailed_timings[0].data.pixel_data.hblank_lo = hblank & 0xff; + edid->detailed_timings[0].data.pixel_data.hactive_hblank_hi = (mode->hdisplay >> 4 & 0xf0) | ((hblank >> 8) & 0xf); + edid->detailed_timings[0].data.pixel_data.vactive_lo = mode->vdisplay & 0xff; + edid->detailed_timings[0].data.pixel_data.vblank_lo = vblank & 0xff; + edid->detailed_timings[0].data.pixel_data.vactive_vblank_hi = (mode->vdisplay >> 4 & 0xf0) | ((vblank >> 8) & 0xf); + + drm_patch_edid_reset_csum(edid); + + return edid; +} +EXPORT_SYMBOL(drm_patch_edid_detailed_mode); diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 3e87f5a..17eb503 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -280,5 +280,8 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, int drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, const struct drm_display_mode *mode); - +struct drm_device; +struct edid *drm_patch_edid_detailed_mode(struct drm_device *dev, + struct edid *orig_edid, + int hdisplay, int vdisplay, int vrefresh); #endif /* __DRM_EDID_H__ */ -- 1.9.3 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx