Home | History | Annotate | Line # | Download | only in gvt
      1 /*	$NetBSD: display.c,v 1.2 2021/12/18 23:45:31 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * Authors:
     26  *    Ke Yu
     27  *    Zhiyuan Lv <zhiyuan.lv (at) intel.com>
     28  *
     29  * Contributors:
     30  *    Terrence Xu <terrence.xu (at) intel.com>
     31  *    Changbin Du <changbin.du (at) intel.com>
     32  *    Bing Niu <bing.niu (at) intel.com>
     33  *    Zhi Wang <zhi.a.wang (at) intel.com>
     34  *
     35  */
     36 
     37 #include <sys/cdefs.h>
     38 __KERNEL_RCSID(0, "$NetBSD: display.c,v 1.2 2021/12/18 23:45:31 riastradh Exp $");
     39 
     40 #include "i915_drv.h"
     41 #include "gvt.h"
     42 
     43 static int get_edp_pipe(struct intel_vgpu *vgpu)
     44 {
     45 	u32 data = vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP);
     46 	int pipe = -1;
     47 
     48 	switch (data & TRANS_DDI_EDP_INPUT_MASK) {
     49 	case TRANS_DDI_EDP_INPUT_A_ON:
     50 	case TRANS_DDI_EDP_INPUT_A_ONOFF:
     51 		pipe = PIPE_A;
     52 		break;
     53 	case TRANS_DDI_EDP_INPUT_B_ONOFF:
     54 		pipe = PIPE_B;
     55 		break;
     56 	case TRANS_DDI_EDP_INPUT_C_ONOFF:
     57 		pipe = PIPE_C;
     58 		break;
     59 	}
     60 	return pipe;
     61 }
     62 
     63 static int edp_pipe_is_enabled(struct intel_vgpu *vgpu)
     64 {
     65 	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
     66 
     67 	if (!(vgpu_vreg_t(vgpu, PIPECONF(_PIPE_EDP)) & PIPECONF_ENABLE))
     68 		return 0;
     69 
     70 	if (!(vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP) & TRANS_DDI_FUNC_ENABLE))
     71 		return 0;
     72 	return 1;
     73 }
     74 
     75 int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
     76 {
     77 	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
     78 
     79 	if (WARN_ON(pipe < PIPE_A || pipe >= I915_MAX_PIPES))
     80 		return -EINVAL;
     81 
     82 	if (vgpu_vreg_t(vgpu, PIPECONF(pipe)) & PIPECONF_ENABLE)
     83 		return 1;
     84 
     85 	if (edp_pipe_is_enabled(vgpu) &&
     86 			get_edp_pipe(vgpu) == pipe)
     87 		return 1;
     88 	return 0;
     89 }
     90 
     91 static unsigned char virtual_dp_monitor_edid[GVT_EDID_NUM][EDID_SIZE] = {
     92 	{
     93 /* EDID with 1024x768 as its resolution */
     94 		/*Header*/
     95 		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
     96 		/* Vendor & Product Identification */
     97 		0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17,
     98 		/* Version & Revision */
     99 		0x01, 0x04,
    100 		/* Basic Display Parameters & Features */
    101 		0xa5, 0x34, 0x20, 0x78, 0x23,
    102 		/* Color Characteristics */
    103 		0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54,
    104 		/* Established Timings: maximum resolution is 1024x768 */
    105 		0x21, 0x08, 0x00,
    106 		/* Standard Timings. All invalid */
    107 		0x00, 0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00,
    108 		0x00, 0x40, 0x00, 0x00, 0x00, 0x01,
    109 		/* 18 Byte Data Blocks 1: invalid */
    110 		0x00, 0x00, 0x80, 0xa0, 0x70, 0xb0,
    111 		0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a,
    112 		/* 18 Byte Data Blocks 2: invalid */
    113 		0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a,
    114 		0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    115 		/* 18 Byte Data Blocks 3: invalid */
    116 		0x00, 0x00, 0x00, 0xfc, 0x00, 0x48,
    117 		0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20,
    118 		/* 18 Byte Data Blocks 4: invalid */
    119 		0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30,
    120 		0x44, 0x58, 0x51, 0x0a, 0x20, 0x20,
    121 		/* Extension Block Count */
    122 		0x00,
    123 		/* Checksum */
    124 		0xef,
    125 	},
    126 	{
    127 /* EDID with 1920x1200 as its resolution */
    128 		/*Header*/
    129 		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
    130 		/* Vendor & Product Identification */
    131 		0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17,
    132 		/* Version & Revision */
    133 		0x01, 0x04,
    134 		/* Basic Display Parameters & Features */
    135 		0xa5, 0x34, 0x20, 0x78, 0x23,
    136 		/* Color Characteristics */
    137 		0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54,
    138 		/* Established Timings: maximum resolution is 1024x768 */
    139 		0x21, 0x08, 0x00,
    140 		/*
    141 		 * Standard Timings.
    142 		 * below new resolutions can be supported:
    143 		 * 1920x1080, 1280x720, 1280x960, 1280x1024,
    144 		 * 1440x900, 1600x1200, 1680x1050
    145 		 */
    146 		0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x40, 0x81, 0x80, 0x95, 0x00,
    147 		0xa9, 0x40, 0xb3, 0x00, 0x01, 0x01,
    148 		/* 18 Byte Data Blocks 1: max resolution is 1920x1200 */
    149 		0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0,
    150 		0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a,
    151 		/* 18 Byte Data Blocks 2: invalid */
    152 		0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a,
    153 		0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    154 		/* 18 Byte Data Blocks 3: invalid */
    155 		0x00, 0x00, 0x00, 0xfc, 0x00, 0x48,
    156 		0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20,
    157 		/* 18 Byte Data Blocks 4: invalid */
    158 		0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30,
    159 		0x44, 0x58, 0x51, 0x0a, 0x20, 0x20,
    160 		/* Extension Block Count */
    161 		0x00,
    162 		/* Checksum */
    163 		0x45,
    164 	},
    165 };
    166 
    167 #define DPCD_HEADER_SIZE        0xb
    168 
    169 /* let the virtual display supports DP1.2 */
    170 static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = {
    171 	0x12, 0x014, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    172 };
    173 
    174 static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
    175 {
    176 	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
    177 	int pipe;
    178 
    179 	if (IS_BROXTON(dev_priv)) {
    180 		vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &= ~(BXT_DE_PORT_HP_DDIA |
    181 			BXT_DE_PORT_HP_DDIB |
    182 			BXT_DE_PORT_HP_DDIC);
    183 
    184 		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
    185 			vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
    186 				BXT_DE_PORT_HP_DDIA;
    187 		}
    188 
    189 		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
    190 			vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
    191 				BXT_DE_PORT_HP_DDIB;
    192 		}
    193 
    194 		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
    195 			vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
    196 				BXT_DE_PORT_HP_DDIC;
    197 		}
    198 
    199 		return;
    200 	}
    201 
    202 	vgpu_vreg_t(vgpu, SDEISR) &= ~(SDE_PORTB_HOTPLUG_CPT |
    203 			SDE_PORTC_HOTPLUG_CPT |
    204 			SDE_PORTD_HOTPLUG_CPT);
    205 
    206 	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ||
    207 	    IS_COFFEELAKE(dev_priv)) {
    208 		vgpu_vreg_t(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT |
    209 				SDE_PORTE_HOTPLUG_SPT);
    210 		vgpu_vreg_t(vgpu, SKL_FUSE_STATUS) |=
    211 				SKL_FUSE_DOWNLOAD_STATUS |
    212 				SKL_FUSE_PG_DIST_STATUS(SKL_PG0) |
    213 				SKL_FUSE_PG_DIST_STATUS(SKL_PG1) |
    214 				SKL_FUSE_PG_DIST_STATUS(SKL_PG2);
    215 		vgpu_vreg_t(vgpu, LCPLL1_CTL) |=
    216 				LCPLL_PLL_ENABLE |
    217 				LCPLL_PLL_LOCK;
    218 		vgpu_vreg_t(vgpu, LCPLL2_CTL) |= LCPLL_PLL_ENABLE;
    219 
    220 	}
    221 
    222 	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
    223 		vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIB_DETECTED;
    224 		vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &=
    225 			~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
    226 			TRANS_DDI_PORT_MASK);
    227 		vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
    228 			(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DVI |
    229 			(PORT_B << TRANS_DDI_PORT_SHIFT) |
    230 			TRANS_DDI_FUNC_ENABLE);
    231 		if (IS_BROADWELL(dev_priv)) {
    232 			vgpu_vreg_t(vgpu, PORT_CLK_SEL(PORT_B)) &=
    233 				~PORT_CLK_SEL_MASK;
    234 			vgpu_vreg_t(vgpu, PORT_CLK_SEL(PORT_B)) |=
    235 				PORT_CLK_SEL_LCPLL_810;
    236 		}
    237 		vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_B)) |= DDI_BUF_CTL_ENABLE;
    238 		vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_B)) &= ~DDI_BUF_IS_IDLE;
    239 		vgpu_vreg_t(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT;
    240 	}
    241 
    242 	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
    243 		vgpu_vreg_t(vgpu, SDEISR) |= SDE_PORTC_HOTPLUG_CPT;
    244 		vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &=
    245 			~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
    246 			TRANS_DDI_PORT_MASK);
    247 		vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
    248 			(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DVI |
    249 			(PORT_C << TRANS_DDI_PORT_SHIFT) |
    250 			TRANS_DDI_FUNC_ENABLE);
    251 		if (IS_BROADWELL(dev_priv)) {
    252 			vgpu_vreg_t(vgpu, PORT_CLK_SEL(PORT_C)) &=
    253 				~PORT_CLK_SEL_MASK;
    254 			vgpu_vreg_t(vgpu, PORT_CLK_SEL(PORT_C)) |=
    255 				PORT_CLK_SEL_LCPLL_810;
    256 		}
    257 		vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_C)) |= DDI_BUF_CTL_ENABLE;
    258 		vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_C)) &= ~DDI_BUF_IS_IDLE;
    259 		vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIC_DETECTED;
    260 	}
    261 
    262 	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_D)) {
    263 		vgpu_vreg_t(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT;
    264 		vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &=
    265 			~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
    266 			TRANS_DDI_PORT_MASK);
    267 		vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
    268 			(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DVI |
    269 			(PORT_D << TRANS_DDI_PORT_SHIFT) |
    270 			TRANS_DDI_FUNC_ENABLE);
    271 		if (IS_BROADWELL(dev_priv)) {
    272 			vgpu_vreg_t(vgpu, PORT_CLK_SEL(PORT_D)) &=
    273 				~PORT_CLK_SEL_MASK;
    274 			vgpu_vreg_t(vgpu, PORT_CLK_SEL(PORT_D)) |=
    275 				PORT_CLK_SEL_LCPLL_810;
    276 		}
    277 		vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_D)) |= DDI_BUF_CTL_ENABLE;
    278 		vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_D)) &= ~DDI_BUF_IS_IDLE;
    279 		vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDID_DETECTED;
    280 	}
    281 
    282 	if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ||
    283 	     IS_COFFEELAKE(dev_priv)) &&
    284 			intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) {
    285 		vgpu_vreg_t(vgpu, SDEISR) |= SDE_PORTE_HOTPLUG_SPT;
    286 	}
    287 
    288 	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
    289 		if (IS_BROADWELL(dev_priv))
    290 			vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
    291 				GEN8_PORT_DP_A_HOTPLUG;
    292 		else
    293 			vgpu_vreg_t(vgpu, SDEISR) |= SDE_PORTA_HOTPLUG_SPT;
    294 
    295 		vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_A)) |= DDI_INIT_DISPLAY_DETECTED;
    296 	}
    297 
    298 	/* Clear host CRT status, so guest couldn't detect this host CRT. */
    299 	if (IS_BROADWELL(dev_priv))
    300 		vgpu_vreg_t(vgpu, PCH_ADPA) &= ~ADPA_CRT_HOTPLUG_MONITOR_MASK;
    301 
    302 	/* Disable Primary/Sprite/Cursor plane */
    303 	for_each_pipe(dev_priv, pipe) {
    304 		vgpu_vreg_t(vgpu, DSPCNTR(pipe)) &= ~DISPLAY_PLANE_ENABLE;
    305 		vgpu_vreg_t(vgpu, SPRCTL(pipe)) &= ~SPRITE_ENABLE;
    306 		vgpu_vreg_t(vgpu, CURCNTR(pipe)) &= ~MCURSOR_MODE;
    307 		vgpu_vreg_t(vgpu, CURCNTR(pipe)) |= MCURSOR_MODE_DISABLE;
    308 	}
    309 
    310 	vgpu_vreg_t(vgpu, PIPECONF(PIPE_A)) |= PIPECONF_ENABLE;
    311 }
    312 
    313 static void clean_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num)
    314 {
    315 	struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num);
    316 
    317 	kfree(port->edid);
    318 	port->edid = NULL;
    319 
    320 	kfree(port->dpcd);
    321 	port->dpcd = NULL;
    322 }
    323 
    324 static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num,
    325 				    int type, unsigned int resolution)
    326 {
    327 	struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num);
    328 
    329 	if (WARN_ON(resolution >= GVT_EDID_NUM))
    330 		return -EINVAL;
    331 
    332 	port->edid = kzalloc(sizeof(*(port->edid)), GFP_KERNEL);
    333 	if (!port->edid)
    334 		return -ENOMEM;
    335 
    336 	port->dpcd = kzalloc(sizeof(*(port->dpcd)), GFP_KERNEL);
    337 	if (!port->dpcd) {
    338 		kfree(port->edid);
    339 		return -ENOMEM;
    340 	}
    341 
    342 	memcpy(port->edid->edid_block, virtual_dp_monitor_edid[resolution],
    343 			EDID_SIZE);
    344 	port->edid->data_valid = true;
    345 
    346 	memcpy(port->dpcd->data, dpcd_fix_data, DPCD_HEADER_SIZE);
    347 	port->dpcd->data_valid = true;
    348 	port->dpcd->data[DPCD_SINK_COUNT] = 0x1;
    349 	port->type = type;
    350 	port->id = resolution;
    351 
    352 	emulate_monitor_status_change(vgpu);
    353 
    354 	return 0;
    355 }
    356 
    357 /**
    358  * intel_gvt_check_vblank_emulation - check if vblank emulation timer should
    359  * be turned on/off when a virtual pipe is enabled/disabled.
    360  * @gvt: a GVT device
    361  *
    362  * This function is used to turn on/off vblank timer according to currently
    363  * enabled/disabled virtual pipes.
    364  *
    365  */
    366 void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt)
    367 {
    368 	struct intel_gvt_irq *irq = &gvt->irq;
    369 	struct intel_vgpu *vgpu;
    370 	int pipe, id;
    371 	int found = false;
    372 
    373 	mutex_lock(&gvt->lock);
    374 	for_each_active_vgpu(gvt, vgpu, id) {
    375 		for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
    376 			if (pipe_is_enabled(vgpu, pipe)) {
    377 				found = true;
    378 				break;
    379 			}
    380 		}
    381 		if (found)
    382 			break;
    383 	}
    384 
    385 	/* all the pipes are disabled */
    386 	if (!found)
    387 		hrtimer_cancel(&irq->vblank_timer.timer);
    388 	else
    389 		hrtimer_start(&irq->vblank_timer.timer,
    390 			ktime_add_ns(ktime_get(), irq->vblank_timer.period),
    391 			HRTIMER_MODE_ABS);
    392 	mutex_unlock(&gvt->lock);
    393 }
    394 
    395 static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe)
    396 {
    397 	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
    398 	struct intel_vgpu_irq *irq = &vgpu->irq;
    399 	int vblank_event[] = {
    400 		[PIPE_A] = PIPE_A_VBLANK,
    401 		[PIPE_B] = PIPE_B_VBLANK,
    402 		[PIPE_C] = PIPE_C_VBLANK,
    403 	};
    404 	int event;
    405 
    406 	if (pipe < PIPE_A || pipe > PIPE_C)
    407 		return;
    408 
    409 	for_each_set_bit(event, irq->flip_done_event[pipe],
    410 			INTEL_GVT_EVENT_MAX) {
    411 		clear_bit(event, irq->flip_done_event[pipe]);
    412 		if (!pipe_is_enabled(vgpu, pipe))
    413 			continue;
    414 
    415 		intel_vgpu_trigger_virtual_event(vgpu, event);
    416 	}
    417 
    418 	if (pipe_is_enabled(vgpu, pipe)) {
    419 		vgpu_vreg_t(vgpu, PIPE_FRMCOUNT_G4X(pipe))++;
    420 		intel_vgpu_trigger_virtual_event(vgpu, vblank_event[pipe]);
    421 	}
    422 }
    423 
    424 static void emulate_vblank(struct intel_vgpu *vgpu)
    425 {
    426 	int pipe;
    427 
    428 	mutex_lock(&vgpu->vgpu_lock);
    429 	for_each_pipe(vgpu->gvt->dev_priv, pipe)
    430 		emulate_vblank_on_pipe(vgpu, pipe);
    431 	mutex_unlock(&vgpu->vgpu_lock);
    432 }
    433 
    434 /**
    435  * intel_gvt_emulate_vblank - trigger vblank events for vGPUs on GVT device
    436  * @gvt: a GVT device
    437  *
    438  * This function is used to trigger vblank interrupts for vGPUs on GVT device
    439  *
    440  */
    441 void intel_gvt_emulate_vblank(struct intel_gvt *gvt)
    442 {
    443 	struct intel_vgpu *vgpu;
    444 	int id;
    445 
    446 	mutex_lock(&gvt->lock);
    447 	for_each_active_vgpu(gvt, vgpu, id)
    448 		emulate_vblank(vgpu);
    449 	mutex_unlock(&gvt->lock);
    450 }
    451 
    452 /**
    453  * intel_vgpu_emulate_hotplug - trigger hotplug event for vGPU
    454  * @vgpu: a vGPU
    455  * @connected: link state
    456  *
    457  * This function is used to trigger hotplug interrupt for vGPU
    458  *
    459  */
    460 void intel_vgpu_emulate_hotplug(struct intel_vgpu *vgpu, bool connected)
    461 {
    462 	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
    463 
    464 	/* TODO: add more platforms support */
    465 	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
    466 		if (connected) {
    467 			vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
    468 				SFUSE_STRAP_DDID_DETECTED;
    469 			vgpu_vreg_t(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT;
    470 		} else {
    471 			vgpu_vreg_t(vgpu, SFUSE_STRAP) &=
    472 				~SFUSE_STRAP_DDID_DETECTED;
    473 			vgpu_vreg_t(vgpu, SDEISR) &= ~SDE_PORTD_HOTPLUG_CPT;
    474 		}
    475 		vgpu_vreg_t(vgpu, SDEIIR) |= SDE_PORTD_HOTPLUG_CPT;
    476 		vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
    477 				PORTD_HOTPLUG_STATUS_MASK;
    478 		intel_vgpu_trigger_virtual_event(vgpu, DP_D_HOTPLUG);
    479 	}
    480 }
    481 
    482 /**
    483  * intel_vgpu_clean_display - clean vGPU virtual display emulation
    484  * @vgpu: a vGPU
    485  *
    486  * This function is used to clean vGPU virtual display emulation stuffs
    487  *
    488  */
    489 void intel_vgpu_clean_display(struct intel_vgpu *vgpu)
    490 {
    491 	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
    492 
    493 	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ||
    494 	    IS_COFFEELAKE(dev_priv))
    495 		clean_virtual_dp_monitor(vgpu, PORT_D);
    496 	else
    497 		clean_virtual_dp_monitor(vgpu, PORT_B);
    498 }
    499 
    500 /**
    501  * intel_vgpu_init_display- initialize vGPU virtual display emulation
    502  * @vgpu: a vGPU
    503  * @resolution: resolution index for intel_vgpu_edid
    504  *
    505  * This function is used to initialize vGPU virtual display emulation stuffs
    506  *
    507  * Returns:
    508  * Zero on success, negative error code if failed.
    509  *
    510  */
    511 int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution)
    512 {
    513 	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
    514 
    515 	intel_vgpu_init_i2c_edid(vgpu);
    516 
    517 	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ||
    518 	    IS_COFFEELAKE(dev_priv))
    519 		return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D,
    520 						resolution);
    521 	else
    522 		return setup_virtual_dp_monitor(vgpu, PORT_B, GVT_DP_B,
    523 						resolution);
    524 }
    525 
    526 /**
    527  * intel_vgpu_reset_display- reset vGPU virtual display emulation
    528  * @vgpu: a vGPU
    529  *
    530  * This function is used to reset vGPU virtual display emulation stuffs
    531  *
    532  */
    533 void intel_vgpu_reset_display(struct intel_vgpu *vgpu)
    534 {
    535 	emulate_monitor_status_change(vgpu);
    536 }
    537