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