104d348aeSZhi Wang /* 204d348aeSZhi Wang * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 304d348aeSZhi Wang * 404d348aeSZhi Wang * Permission is hereby granted, free of charge, to any person obtaining a 504d348aeSZhi Wang * copy of this software and associated documentation files (the "Software"), 604d348aeSZhi Wang * to deal in the Software without restriction, including without limitation 704d348aeSZhi Wang * the rights to use, copy, modify, merge, publish, distribute, sublicense, 804d348aeSZhi Wang * and/or sell copies of the Software, and to permit persons to whom the 904d348aeSZhi Wang * Software is furnished to do so, subject to the following conditions: 1004d348aeSZhi Wang * 1104d348aeSZhi Wang * The above copyright notice and this permission notice (including the next 1204d348aeSZhi Wang * paragraph) shall be included in all copies or substantial portions of the 1304d348aeSZhi Wang * Software. 1404d348aeSZhi Wang * 1504d348aeSZhi Wang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1604d348aeSZhi Wang * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1704d348aeSZhi Wang * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1804d348aeSZhi Wang * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1904d348aeSZhi Wang * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2004d348aeSZhi Wang * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2104d348aeSZhi Wang * SOFTWARE. 2204d348aeSZhi Wang * 2304d348aeSZhi Wang * Authors: 2404d348aeSZhi Wang * Ke Yu 2504d348aeSZhi Wang * Zhiyuan Lv <zhiyuan.lv@intel.com> 2604d348aeSZhi Wang * 2704d348aeSZhi Wang * Contributors: 2804d348aeSZhi Wang * Terrence Xu <terrence.xu@intel.com> 2904d348aeSZhi Wang * Changbin Du <changbin.du@intel.com> 3004d348aeSZhi Wang * Bing Niu <bing.niu@intel.com> 3104d348aeSZhi Wang * Zhi Wang <zhi.a.wang@intel.com> 3204d348aeSZhi Wang * 3304d348aeSZhi Wang */ 3404d348aeSZhi Wang 3504d348aeSZhi Wang #include "i915_drv.h" 36feddf6e8SZhenyu Wang #include "gvt.h" 3704d348aeSZhi Wang 3804d348aeSZhi Wang static int get_edp_pipe(struct intel_vgpu *vgpu) 3904d348aeSZhi Wang { 4004d348aeSZhi Wang u32 data = vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP); 4104d348aeSZhi Wang int pipe = -1; 4204d348aeSZhi Wang 4304d348aeSZhi Wang switch (data & TRANS_DDI_EDP_INPUT_MASK) { 4404d348aeSZhi Wang case TRANS_DDI_EDP_INPUT_A_ON: 4504d348aeSZhi Wang case TRANS_DDI_EDP_INPUT_A_ONOFF: 4604d348aeSZhi Wang pipe = PIPE_A; 4704d348aeSZhi Wang break; 4804d348aeSZhi Wang case TRANS_DDI_EDP_INPUT_B_ONOFF: 4904d348aeSZhi Wang pipe = PIPE_B; 5004d348aeSZhi Wang break; 5104d348aeSZhi Wang case TRANS_DDI_EDP_INPUT_C_ONOFF: 5204d348aeSZhi Wang pipe = PIPE_C; 5304d348aeSZhi Wang break; 5404d348aeSZhi Wang } 5504d348aeSZhi Wang return pipe; 5604d348aeSZhi Wang } 5704d348aeSZhi Wang 5804d348aeSZhi Wang static int edp_pipe_is_enabled(struct intel_vgpu *vgpu) 5904d348aeSZhi Wang { 6004d348aeSZhi Wang struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 6104d348aeSZhi Wang 6204d348aeSZhi Wang if (!(vgpu_vreg(vgpu, PIPECONF(_PIPE_EDP)) & PIPECONF_ENABLE)) 6304d348aeSZhi Wang return 0; 6404d348aeSZhi Wang 6504d348aeSZhi Wang if (!(vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP) & TRANS_DDI_FUNC_ENABLE)) 6604d348aeSZhi Wang return 0; 6704d348aeSZhi Wang return 1; 6804d348aeSZhi Wang } 6904d348aeSZhi Wang 7004d348aeSZhi Wang static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe) 7104d348aeSZhi Wang { 7204d348aeSZhi Wang struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 7304d348aeSZhi Wang 7404d348aeSZhi Wang if (WARN_ON(pipe < PIPE_A || pipe >= I915_MAX_PIPES)) 7504d348aeSZhi Wang return -EINVAL; 7604d348aeSZhi Wang 7704d348aeSZhi Wang if (vgpu_vreg(vgpu, PIPECONF(pipe)) & PIPECONF_ENABLE) 7804d348aeSZhi Wang return 1; 7904d348aeSZhi Wang 8004d348aeSZhi Wang if (edp_pipe_is_enabled(vgpu) && 8104d348aeSZhi Wang get_edp_pipe(vgpu) == pipe) 8204d348aeSZhi Wang return 1; 8304d348aeSZhi Wang return 0; 8404d348aeSZhi Wang } 8504d348aeSZhi Wang 86bca5609fSZhenyu Wang static unsigned char virtual_dp_monitor_edid[GVT_EDID_NUM][EDID_SIZE] = { 87bca5609fSZhenyu Wang { 88bca5609fSZhenyu Wang /* EDID with 1024x768 as its resolution */ 89bca5609fSZhenyu Wang /*Header*/ 90bca5609fSZhenyu Wang 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 91bca5609fSZhenyu Wang /* Vendor & Product Identification */ 92bca5609fSZhenyu Wang 0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17, 93bca5609fSZhenyu Wang /* Version & Revision */ 94bca5609fSZhenyu Wang 0x01, 0x04, 95bca5609fSZhenyu Wang /* Basic Display Parameters & Features */ 96bca5609fSZhenyu Wang 0xa5, 0x34, 0x20, 0x78, 0x23, 97bca5609fSZhenyu Wang /* Color Characteristics */ 98bca5609fSZhenyu Wang 0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54, 99bca5609fSZhenyu Wang /* Established Timings: maximum resolution is 1024x768 */ 100bca5609fSZhenyu Wang 0x21, 0x08, 0x00, 101bca5609fSZhenyu Wang /* Standard Timings. All invalid */ 102bca5609fSZhenyu Wang 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 103bca5609fSZhenyu Wang 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 104bca5609fSZhenyu Wang /* 18 Byte Data Blocks 1: invalid */ 105bca5609fSZhenyu Wang 0x00, 0x00, 0x80, 0xa0, 0x70, 0xb0, 106bca5609fSZhenyu Wang 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a, 107bca5609fSZhenyu Wang /* 18 Byte Data Blocks 2: invalid */ 108bca5609fSZhenyu Wang 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a, 109bca5609fSZhenyu Wang 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 110bca5609fSZhenyu Wang /* 18 Byte Data Blocks 3: invalid */ 111bca5609fSZhenyu Wang 0x00, 0x00, 0x00, 0xfc, 0x00, 0x48, 112bca5609fSZhenyu Wang 0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20, 113bca5609fSZhenyu Wang /* 18 Byte Data Blocks 4: invalid */ 114bca5609fSZhenyu Wang 0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30, 115bca5609fSZhenyu Wang 0x44, 0x58, 0x51, 0x0a, 0x20, 0x20, 116bca5609fSZhenyu Wang /* Extension Block Count */ 117bca5609fSZhenyu Wang 0x00, 118bca5609fSZhenyu Wang /* Checksum */ 119bca5609fSZhenyu Wang 0xef, 120bca5609fSZhenyu Wang }, 121bca5609fSZhenyu Wang { 1222c883136SChuanxiao Dong /* EDID with 1920x1200 as its resolution */ 12304d348aeSZhi Wang /*Header*/ 12404d348aeSZhi Wang 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 12504d348aeSZhi Wang /* Vendor & Product Identification */ 12604d348aeSZhi Wang 0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17, 12704d348aeSZhi Wang /* Version & Revision */ 12804d348aeSZhi Wang 0x01, 0x04, 12904d348aeSZhi Wang /* Basic Display Parameters & Features */ 13004d348aeSZhi Wang 0xa5, 0x34, 0x20, 0x78, 0x23, 13104d348aeSZhi Wang /* Color Characteristics */ 13204d348aeSZhi Wang 0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54, 13304d348aeSZhi Wang /* Established Timings: maximum resolution is 1024x768 */ 13404d348aeSZhi Wang 0x21, 0x08, 0x00, 1352c883136SChuanxiao Dong /* 1362c883136SChuanxiao Dong * Standard Timings. 1372c883136SChuanxiao Dong * below new resolutions can be supported: 1382c883136SChuanxiao Dong * 1920x1080, 1280x720, 1280x960, 1280x1024, 1392c883136SChuanxiao Dong * 1440x900, 1600x1200, 1680x1050 1402c883136SChuanxiao Dong */ 1412c883136SChuanxiao Dong 0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 1422c883136SChuanxiao Dong 0xa9, 0x40, 0xb3, 0x00, 0x01, 0x01, 1432c883136SChuanxiao Dong /* 18 Byte Data Blocks 1: max resolution is 1920x1200 */ 1442c883136SChuanxiao Dong 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0, 14504d348aeSZhi Wang 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a, 14604d348aeSZhi Wang /* 18 Byte Data Blocks 2: invalid */ 14704d348aeSZhi Wang 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a, 14804d348aeSZhi Wang 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 14904d348aeSZhi Wang /* 18 Byte Data Blocks 3: invalid */ 15004d348aeSZhi Wang 0x00, 0x00, 0x00, 0xfc, 0x00, 0x48, 15104d348aeSZhi Wang 0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20, 15204d348aeSZhi Wang /* 18 Byte Data Blocks 4: invalid */ 15304d348aeSZhi Wang 0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30, 15404d348aeSZhi Wang 0x44, 0x58, 0x51, 0x0a, 0x20, 0x20, 15504d348aeSZhi Wang /* Extension Block Count */ 15604d348aeSZhi Wang 0x00, 15704d348aeSZhi Wang /* Checksum */ 1582c883136SChuanxiao Dong 0x45, 159bca5609fSZhenyu Wang }, 16004d348aeSZhi Wang }; 16104d348aeSZhi Wang 16204d348aeSZhi Wang #define DPCD_HEADER_SIZE 0xb 16304d348aeSZhi Wang 164999ccb40SDu, Changbin static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = { 16504d348aeSZhi Wang 0x11, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 16604d348aeSZhi Wang }; 16704d348aeSZhi Wang 16804d348aeSZhi Wang static void emulate_monitor_status_change(struct intel_vgpu *vgpu) 16904d348aeSZhi Wang { 17004d348aeSZhi Wang struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 17104d348aeSZhi Wang vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTB_HOTPLUG_CPT | 17204d348aeSZhi Wang SDE_PORTC_HOTPLUG_CPT | 17304d348aeSZhi Wang SDE_PORTD_HOTPLUG_CPT); 17404d348aeSZhi Wang 17504d348aeSZhi Wang if (IS_SKYLAKE(dev_priv)) 17604d348aeSZhi Wang vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT | 17704d348aeSZhi Wang SDE_PORTE_HOTPLUG_SPT); 17804d348aeSZhi Wang 17904d348aeSZhi Wang if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) 18004d348aeSZhi Wang vgpu_vreg(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT; 18104d348aeSZhi Wang 18204d348aeSZhi Wang if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) 18304d348aeSZhi Wang vgpu_vreg(vgpu, SDEISR) |= SDE_PORTC_HOTPLUG_CPT; 18404d348aeSZhi Wang 18504d348aeSZhi Wang if (intel_vgpu_has_monitor_on_port(vgpu, PORT_D)) 18604d348aeSZhi Wang vgpu_vreg(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT; 18704d348aeSZhi Wang 18804d348aeSZhi Wang if (IS_SKYLAKE(dev_priv) && 18904d348aeSZhi Wang intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) { 19004d348aeSZhi Wang vgpu_vreg(vgpu, SDEISR) |= SDE_PORTE_HOTPLUG_SPT; 19104d348aeSZhi Wang } 19204d348aeSZhi Wang 19304d348aeSZhi Wang if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) { 19404d348aeSZhi Wang if (IS_BROADWELL(dev_priv)) 19504d348aeSZhi Wang vgpu_vreg(vgpu, GEN8_DE_PORT_ISR) |= 19604d348aeSZhi Wang GEN8_PORT_DP_A_HOTPLUG; 19704d348aeSZhi Wang else 19804d348aeSZhi Wang vgpu_vreg(vgpu, SDEISR) |= SDE_PORTA_HOTPLUG_SPT; 19904d348aeSZhi Wang } 20004d348aeSZhi Wang } 20104d348aeSZhi Wang 20204d348aeSZhi Wang static void clean_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num) 20304d348aeSZhi Wang { 20404d348aeSZhi Wang struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num); 20504d348aeSZhi Wang 20604d348aeSZhi Wang kfree(port->edid); 20704d348aeSZhi Wang port->edid = NULL; 20804d348aeSZhi Wang 20904d348aeSZhi Wang kfree(port->dpcd); 21004d348aeSZhi Wang port->dpcd = NULL; 21104d348aeSZhi Wang } 21204d348aeSZhi Wang 21304d348aeSZhi Wang static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num, 214*d1a513beSZhenyu Wang int type, unsigned int resolution) 21504d348aeSZhi Wang { 21604d348aeSZhi Wang struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num); 21704d348aeSZhi Wang 218*d1a513beSZhenyu Wang if (WARN_ON(resolution >= GVT_EDID_NUM)) 219*d1a513beSZhenyu Wang return -EINVAL; 220*d1a513beSZhenyu Wang 22104d348aeSZhi Wang port->edid = kzalloc(sizeof(*(port->edid)), GFP_KERNEL); 22204d348aeSZhi Wang if (!port->edid) 22304d348aeSZhi Wang return -ENOMEM; 22404d348aeSZhi Wang 22504d348aeSZhi Wang port->dpcd = kzalloc(sizeof(*(port->dpcd)), GFP_KERNEL); 22604d348aeSZhi Wang if (!port->dpcd) { 22704d348aeSZhi Wang kfree(port->edid); 22804d348aeSZhi Wang return -ENOMEM; 22904d348aeSZhi Wang } 23004d348aeSZhi Wang 231*d1a513beSZhenyu Wang memcpy(port->edid->edid_block, virtual_dp_monitor_edid[resolution], 23204d348aeSZhi Wang EDID_SIZE); 23304d348aeSZhi Wang port->edid->data_valid = true; 23404d348aeSZhi Wang 23504d348aeSZhi Wang memcpy(port->dpcd->data, dpcd_fix_data, DPCD_HEADER_SIZE); 23604d348aeSZhi Wang port->dpcd->data_valid = true; 23704d348aeSZhi Wang port->dpcd->data[DPCD_SINK_COUNT] = 0x1; 23804d348aeSZhi Wang port->type = type; 23904d348aeSZhi Wang 24004d348aeSZhi Wang emulate_monitor_status_change(vgpu); 24104d348aeSZhi Wang return 0; 24204d348aeSZhi Wang } 24304d348aeSZhi Wang 24404d348aeSZhi Wang /** 24504d348aeSZhi Wang * intel_gvt_check_vblank_emulation - check if vblank emulation timer should 24604d348aeSZhi Wang * be turned on/off when a virtual pipe is enabled/disabled. 24704d348aeSZhi Wang * @gvt: a GVT device 24804d348aeSZhi Wang * 24904d348aeSZhi Wang * This function is used to turn on/off vblank timer according to currently 25004d348aeSZhi Wang * enabled/disabled virtual pipes. 25104d348aeSZhi Wang * 25204d348aeSZhi Wang */ 25304d348aeSZhi Wang void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt) 25404d348aeSZhi Wang { 25504d348aeSZhi Wang struct intel_gvt_irq *irq = &gvt->irq; 25604d348aeSZhi Wang struct intel_vgpu *vgpu; 25704d348aeSZhi Wang bool have_enabled_pipe = false; 25804d348aeSZhi Wang int pipe, id; 25904d348aeSZhi Wang 26004d348aeSZhi Wang if (WARN_ON(!mutex_is_locked(&gvt->lock))) 26104d348aeSZhi Wang return; 26204d348aeSZhi Wang 26304d348aeSZhi Wang hrtimer_cancel(&irq->vblank_timer.timer); 26404d348aeSZhi Wang 26504d348aeSZhi Wang for_each_active_vgpu(gvt, vgpu, id) { 26604d348aeSZhi Wang for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) { 26704d348aeSZhi Wang have_enabled_pipe = 26804d348aeSZhi Wang pipe_is_enabled(vgpu, pipe); 26904d348aeSZhi Wang if (have_enabled_pipe) 27004d348aeSZhi Wang break; 27104d348aeSZhi Wang } 27204d348aeSZhi Wang } 27304d348aeSZhi Wang 27404d348aeSZhi Wang if (have_enabled_pipe) 27504d348aeSZhi Wang hrtimer_start(&irq->vblank_timer.timer, 27604d348aeSZhi Wang ktime_add_ns(ktime_get(), irq->vblank_timer.period), 27704d348aeSZhi Wang HRTIMER_MODE_ABS); 27804d348aeSZhi Wang } 27904d348aeSZhi Wang 28004d348aeSZhi Wang static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe) 28104d348aeSZhi Wang { 28204d348aeSZhi Wang struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 28304d348aeSZhi Wang struct intel_vgpu_irq *irq = &vgpu->irq; 28404d348aeSZhi Wang int vblank_event[] = { 28504d348aeSZhi Wang [PIPE_A] = PIPE_A_VBLANK, 28604d348aeSZhi Wang [PIPE_B] = PIPE_B_VBLANK, 28704d348aeSZhi Wang [PIPE_C] = PIPE_C_VBLANK, 28804d348aeSZhi Wang }; 28904d348aeSZhi Wang int event; 29004d348aeSZhi Wang 29104d348aeSZhi Wang if (pipe < PIPE_A || pipe > PIPE_C) 29204d348aeSZhi Wang return; 29304d348aeSZhi Wang 29404d348aeSZhi Wang for_each_set_bit(event, irq->flip_done_event[pipe], 29504d348aeSZhi Wang INTEL_GVT_EVENT_MAX) { 29604d348aeSZhi Wang clear_bit(event, irq->flip_done_event[pipe]); 29704d348aeSZhi Wang if (!pipe_is_enabled(vgpu, pipe)) 29804d348aeSZhi Wang continue; 29904d348aeSZhi Wang 30004d348aeSZhi Wang vgpu_vreg(vgpu, PIPE_FLIPCOUNT_G4X(pipe))++; 30104d348aeSZhi Wang intel_vgpu_trigger_virtual_event(vgpu, event); 30204d348aeSZhi Wang } 30304d348aeSZhi Wang 30404d348aeSZhi Wang if (pipe_is_enabled(vgpu, pipe)) { 30504d348aeSZhi Wang vgpu_vreg(vgpu, PIPE_FRMCOUNT_G4X(pipe))++; 30604d348aeSZhi Wang intel_vgpu_trigger_virtual_event(vgpu, vblank_event[pipe]); 30704d348aeSZhi Wang } 30804d348aeSZhi Wang } 30904d348aeSZhi Wang 31004d348aeSZhi Wang static void emulate_vblank(struct intel_vgpu *vgpu) 31104d348aeSZhi Wang { 31204d348aeSZhi Wang int pipe; 31304d348aeSZhi Wang 31404d348aeSZhi Wang for_each_pipe(vgpu->gvt->dev_priv, pipe) 31504d348aeSZhi Wang emulate_vblank_on_pipe(vgpu, pipe); 31604d348aeSZhi Wang } 31704d348aeSZhi Wang 31804d348aeSZhi Wang /** 31904d348aeSZhi Wang * intel_gvt_emulate_vblank - trigger vblank events for vGPUs on GVT device 32004d348aeSZhi Wang * @gvt: a GVT device 32104d348aeSZhi Wang * 32204d348aeSZhi Wang * This function is used to trigger vblank interrupts for vGPUs on GVT device 32304d348aeSZhi Wang * 32404d348aeSZhi Wang */ 32504d348aeSZhi Wang void intel_gvt_emulate_vblank(struct intel_gvt *gvt) 32604d348aeSZhi Wang { 32704d348aeSZhi Wang struct intel_vgpu *vgpu; 32804d348aeSZhi Wang int id; 32904d348aeSZhi Wang 33004d348aeSZhi Wang if (WARN_ON(!mutex_is_locked(&gvt->lock))) 33104d348aeSZhi Wang return; 33204d348aeSZhi Wang 33304d348aeSZhi Wang for_each_active_vgpu(gvt, vgpu, id) 33404d348aeSZhi Wang emulate_vblank(vgpu); 33504d348aeSZhi Wang } 33604d348aeSZhi Wang 33704d348aeSZhi Wang /** 33804d348aeSZhi Wang * intel_vgpu_clean_display - clean vGPU virtual display emulation 33904d348aeSZhi Wang * @vgpu: a vGPU 34004d348aeSZhi Wang * 34104d348aeSZhi Wang * This function is used to clean vGPU virtual display emulation stuffs 34204d348aeSZhi Wang * 34304d348aeSZhi Wang */ 34404d348aeSZhi Wang void intel_vgpu_clean_display(struct intel_vgpu *vgpu) 34504d348aeSZhi Wang { 34604d348aeSZhi Wang struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 34704d348aeSZhi Wang 34804d348aeSZhi Wang if (IS_SKYLAKE(dev_priv)) 34904d348aeSZhi Wang clean_virtual_dp_monitor(vgpu, PORT_D); 35004d348aeSZhi Wang else 35104d348aeSZhi Wang clean_virtual_dp_monitor(vgpu, PORT_B); 35204d348aeSZhi Wang } 35304d348aeSZhi Wang 35404d348aeSZhi Wang /** 35504d348aeSZhi Wang * intel_vgpu_init_display- initialize vGPU virtual display emulation 35604d348aeSZhi Wang * @vgpu: a vGPU 35704d348aeSZhi Wang * 35804d348aeSZhi Wang * This function is used to initialize vGPU virtual display emulation stuffs 35904d348aeSZhi Wang * 36004d348aeSZhi Wang * Returns: 36104d348aeSZhi Wang * Zero on success, negative error code if failed. 36204d348aeSZhi Wang * 36304d348aeSZhi Wang */ 364*d1a513beSZhenyu Wang int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution) 36504d348aeSZhi Wang { 36604d348aeSZhi Wang struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 36704d348aeSZhi Wang 36804d348aeSZhi Wang intel_vgpu_init_i2c_edid(vgpu); 36904d348aeSZhi Wang 37004d348aeSZhi Wang if (IS_SKYLAKE(dev_priv)) 371*d1a513beSZhenyu Wang return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D, 372*d1a513beSZhenyu Wang resolution); 37304d348aeSZhi Wang else 374*d1a513beSZhenyu Wang return setup_virtual_dp_monitor(vgpu, PORT_B, GVT_DP_B, 375*d1a513beSZhenyu Wang resolution); 37604d348aeSZhi Wang } 3776294b61bSChangbin Du 3786294b61bSChangbin Du /** 3796294b61bSChangbin Du * intel_vgpu_reset_display- reset vGPU virtual display emulation 3806294b61bSChangbin Du * @vgpu: a vGPU 3816294b61bSChangbin Du * 3826294b61bSChangbin Du * This function is used to reset vGPU virtual display emulation stuffs 3836294b61bSChangbin Du * 3846294b61bSChangbin Du */ 3856294b61bSChangbin Du void intel_vgpu_reset_display(struct intel_vgpu *vgpu) 3866294b61bSChangbin Du { 3876294b61bSChangbin Du emulate_monitor_status_change(vgpu); 3886294b61bSChangbin Du } 389