176 lines
6.2 KiB
Diff
176 lines
6.2 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Cai Yulong <yulongc@hwtc.com.cn>
|
||
|
Date: Fri, 17 May 2019 15:16:38 +0800
|
||
|
Subject: [PATCH] drm/i915/gvt: create edid from drm_display_mode instance for
|
||
|
fixed-mode panel
|
||
|
|
||
|
Current gvt display pipe iteration code use intel_connector.detect_edid
|
||
|
to see if there is monitor attached to the connector, this will fail with
|
||
|
those panel which only contains a fixed mode, e.g. MIPI-DSI panel
|
||
|
.
|
||
|
This patch create a edid based on the panel's fixed mode and make
|
||
|
fixed-mode panel available during virutal monitor setup.
|
||
|
|
||
|
Tracked-On: projectacrn/acrn-hypervisor#3196
|
||
|
Signed-off-by: Cai Yulong <yulongc@hwtc.com.cn>
|
||
|
---
|
||
|
drivers/gpu/drm/i915/gvt/display.c | 18 +++++--
|
||
|
drivers/gpu/drm/i915/gvt/edid.c | 86 ++++++++++++++++++++++++++++++
|
||
|
drivers/gpu/drm/i915/gvt/edid.h | 2 +
|
||
|
3 files changed, 102 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
|
||
|
index 1c905d9e063b..290d5b380a3e 100644
|
||
|
--- a/drivers/gpu/drm/i915/gvt/display.c
|
||
|
+++ b/drivers/gpu/drm/i915/gvt/display.c
|
||
|
@@ -576,6 +576,7 @@ int setup_virtual_monitors(struct intel_vgpu *vgpu)
|
||
|
struct intel_connector *connector = NULL;
|
||
|
struct drm_connector_list_iter conn_iter;
|
||
|
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
|
||
|
+ struct edid *edid;
|
||
|
int pipe = 0;
|
||
|
int ret = 0;
|
||
|
int type = gvt_emulate_hdmi ? GVT_HDMI_A : GVT_DP_A;
|
||
|
@@ -587,17 +588,26 @@ int setup_virtual_monitors(struct intel_vgpu *vgpu)
|
||
|
|
||
|
drm_connector_list_iter_begin(&vgpu->gvt->dev_priv->drm, &conn_iter);
|
||
|
for_each_intel_connector_iter(connector, &conn_iter) {
|
||
|
- if (connector->encoder->get_hw_state(connector->encoder, &pipe)
|
||
|
- && connector->detect_edid) {
|
||
|
+ if (connector->encoder->get_hw_state(connector->encoder,
|
||
|
+ &pipe)) {
|
||
|
/* if no planes are allocated for this pipe, skip it */
|
||
|
if (i915_modparams.avail_planes_per_pipe &&
|
||
|
!bxt_check_planes(vgpu, pipe))
|
||
|
continue;
|
||
|
+
|
||
|
+ if (connector->panel.fixed_mode) {
|
||
|
+ edid = intel_gvt_create_edid_from_mode(
|
||
|
+ connector->panel.fixed_mode);
|
||
|
+ } else if (connector->detect_edid) {
|
||
|
+ edid = connector->detect_edid;
|
||
|
+ } else {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
/* Get (Dom0) port associated with current pipe. */
|
||
|
port = connector->encoder->port;
|
||
|
ret = setup_virtual_monitor(vgpu, port,
|
||
|
- type, 0, connector->detect_edid,
|
||
|
- !gvt_emulate_hdmi);
|
||
|
+ type, 0, edid, !gvt_emulate_hdmi);
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
type++;
|
||
|
diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c
|
||
|
index c4bf4800f72f..97d16834368c 100644
|
||
|
--- a/drivers/gpu/drm/i915/gvt/edid.c
|
||
|
+++ b/drivers/gpu/drm/i915/gvt/edid.c
|
||
|
@@ -426,6 +426,92 @@ static inline int get_aux_ch_reg(unsigned int offset)
|
||
|
return reg;
|
||
|
}
|
||
|
|
||
|
+static u8 edid_checksum(struct edid *edid)
|
||
|
+{
|
||
|
+ u8 *raw = (u8 *)edid, csum = 0;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ for (i = 0; i < EDID_LENGTH; i++)
|
||
|
+ csum += raw[i];
|
||
|
+
|
||
|
+ return csum;
|
||
|
+}
|
||
|
+
|
||
|
+struct edid *intel_gvt_create_edid_from_mode(struct drm_display_mode *mode)
|
||
|
+{
|
||
|
+ struct edid *edid = NULL;
|
||
|
+ struct detailed_pixel_timing *pt;
|
||
|
+
|
||
|
+ edid = kzalloc(sizeof(struct edid), GFP_KERNEL);
|
||
|
+ if (edid) {
|
||
|
+ /* EDID header */
|
||
|
+ memset(&edid->header[1], 0xff, 6);
|
||
|
+ /* Vendor & product info */
|
||
|
+ edid->mfg_id[0] = 0x22, edid->mfg_id[1] = 0xf0;
|
||
|
+ edid->prod_code[0] = 0x54, edid->prod_code[1] = 0x29;
|
||
|
+ edid->serial = 0x00000000;
|
||
|
+ edid->mfg_week = 0x05, edid->mfg_year = 0x19;
|
||
|
+ /* EDID version */
|
||
|
+ edid->version = 0x01, edid->revision = 0x04;
|
||
|
+ /* Display info */
|
||
|
+ edid->input = 0xa5;
|
||
|
+ edid->width_cm = 0x34;
|
||
|
+ edid->height_cm = 0x20;
|
||
|
+ edid->gamma = 0x78;
|
||
|
+ edid->features = 0x23;
|
||
|
+ /* Color characteristics */
|
||
|
+ edid->red_green_lo = 0xfc;
|
||
|
+ edid->black_white_lo = 0x81;
|
||
|
+ edid->red_x = 0xa4, edid->red_y = 0x55;
|
||
|
+ edid->green_x = 0x4d, edid->green_y = 0x9d;
|
||
|
+ edid->blue_x = 0x25, edid->blue_y = 0x12;
|
||
|
+ edid->white_x = 0x50, edid->white_y = 0x54;
|
||
|
+ /* Detailed timings */
|
||
|
+ edid->detailed_timings[0].pixel_clock =
|
||
|
+ cpu_to_le16(mode->clock / 10);
|
||
|
+ pt = &edid->detailed_timings[0].data.pixel_data;
|
||
|
+ pt->hactive_lo = mode->hdisplay & 0xff;
|
||
|
+ pt->hblank_lo = (mode->htotal - mode->hdisplay) & 0xff;
|
||
|
+ pt->hactive_hblank_hi = (mode->hdisplay & 0xf00) >> 4
|
||
|
+ | ((mode->htotal - mode->hdisplay) & 0xf00) >> 8;
|
||
|
+ pt->vactive_lo = mode->vdisplay & 0xff;
|
||
|
+ pt->vblank_lo = (mode->vtotal - mode->vdisplay) & 0xff;
|
||
|
+ pt->vactive_vblank_hi = (mode->vdisplay & 0xf00) >> 4
|
||
|
+ | ((mode->vtotal - mode->vdisplay) & 0xf00) >> 8;
|
||
|
+ pt->hsync_offset_lo =
|
||
|
+ (mode->hsync_start - mode->hdisplay) & 0xff;
|
||
|
+ pt->hsync_pulse_width_lo =
|
||
|
+ (mode->hsync_end - mode->hsync_start) & 0xff;
|
||
|
+ pt->vsync_offset_pulse_width_lo =
|
||
|
+ ((mode->vsync_start - mode->vdisplay) & 0x0f) << 4;
|
||
|
+ pt->vsync_offset_pulse_width_lo |=
|
||
|
+ (mode->vsync_end - mode->vsync_start) & 0x0f;
|
||
|
+ pt->hsync_vsync_offset_pulse_width_hi =
|
||
|
+ ((mode->hsync_start - mode->hdisplay) & 0x300) >> 2;
|
||
|
+ pt->hsync_vsync_offset_pulse_width_hi |=
|
||
|
+ ((mode->hsync_end - mode->hsync_start) & 0x300) >> 4;
|
||
|
+ pt->hsync_vsync_offset_pulse_width_hi |=
|
||
|
+ ((mode->vsync_start - mode->vdisplay) & 0x30) >> 2;
|
||
|
+ pt->hsync_vsync_offset_pulse_width_hi |=
|
||
|
+ ((mode->vsync_end - mode->vsync_start) & 0x30) >> 4;
|
||
|
+ pt->width_mm_lo = mode->width_mm & 0xff;
|
||
|
+ pt->height_mm_lo = mode->height_mm & 0xff;
|
||
|
+ pt->width_height_mm_hi = (mode->width_mm & 0xf00) >> 4;
|
||
|
+ pt->width_height_mm_hi |= (mode->height_mm & 0xf00) >> 8;
|
||
|
+
|
||
|
+ pt->misc = mode->flags & DRM_MODE_FLAG_PHSYNC ?
|
||
|
+ DRM_EDID_PT_HSYNC_POSITIVE : 0;
|
||
|
+ pt->misc |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
|
||
|
+ DRM_EDID_PT_VSYNC_POSITIVE : 0;
|
||
|
+ pt->misc |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
|
||
|
+ DRM_EDID_PT_INTERLACED : 0;
|
||
|
+
|
||
|
+ edid->checksum = 0 - edid_checksum(edid);
|
||
|
+ }
|
||
|
+
|
||
|
+ return edid;
|
||
|
+}
|
||
|
+
|
||
|
#define AUX_CTL_MSG_LENGTH(reg) \
|
||
|
((reg & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> \
|
||
|
DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT)
|
||
|
diff --git a/drivers/gpu/drm/i915/gvt/edid.h b/drivers/gpu/drm/i915/gvt/edid.h
|
||
|
index 11a75d69062d..fb9a37f61b73 100644
|
||
|
--- a/drivers/gpu/drm/i915/gvt/edid.h
|
||
|
+++ b/drivers/gpu/drm/i915/gvt/edid.h
|
||
|
@@ -147,4 +147,6 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
|
||
|
unsigned int offset,
|
||
|
void *p_data);
|
||
|
|
||
|
+struct edid *intel_gvt_create_edid_from_mode(struct drm_display_mode *mode);
|
||
|
+
|
||
|
#endif /*_GVT_EDID_H_*/
|
||
|
--
|
||
|
https://clearlinux.org
|
||
|
|