drm/i915/gvt: Fix virtual display setup for BXT/APL
authorColin Xu <colin.xu@intel.com>
Mon, 9 Nov 2020 07:39:22 +0000 (15:39 +0800)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Tue, 10 Nov 2020 06:46:00 +0000 (14:46 +0800)
Program display related vregs to proper value at initialization, setup
virtual monitor and hotplug.

vGPU virtual display vregs inherit the value from pregs. The virtual DP
monitor is always setup on PORT_B for BXT/APL. However the host may
connect monitor on other PORT or without any monitor connected. Without
properly setup PIPE/DDI/PLL related vregs, guest driver may not setup
the virutal display as expected, and the guest desktop may not be
created.
Since only one virtual display is supported, enable PIPE_A only. And
enable transcoder/DDI/PLL based on which port is setup for BXT/APL.

V2:
Revise commit message.

V3:
set_edid should on PORT_B for BXT.
Inject hpd event for BXT.

V4:
Temporarily disable vfio edid on BXT/APL until issue fixed.

V5:
Rebase to use new HPD define GEN8_DE_PORT_HOTPLUG for BXT.
Put vfio edid disabling on BXT/APL to a separate patch.

Acked-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Colin Xu <colin.xu@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20201109073922.757759-1-colin.xu@intel.com
drivers/gpu/drm/i915/gvt/display.c
drivers/gpu/drm/i915/gvt/mmio.c

index 5b5c71a0b4af5c8bc96e33703e6a88d7a67b28af..5c1fcac260d3b396a298942fb124ab145c6a3b63 100644 (file)
@@ -173,22 +173,162 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
        int pipe;
 
        if (IS_BROXTON(dev_priv)) {
+               enum transcoder trans;
+               enum port port;
+
+               /* Clear PIPE, DDI, PHY, HPD before setting new */
                vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
                        ~(GEN8_DE_PORT_HOTPLUG(HPD_PORT_A) |
                          GEN8_DE_PORT_HOTPLUG(HPD_PORT_B) |
                          GEN8_DE_PORT_HOTPLUG(HPD_PORT_C));
 
+               for_each_pipe(dev_priv, pipe) {
+                       vgpu_vreg_t(vgpu, PIPECONF(pipe)) &=
+                               ~(PIPECONF_ENABLE | I965_PIPECONF_ACTIVE);
+                       vgpu_vreg_t(vgpu, DSPCNTR(pipe)) &= ~DISPLAY_PLANE_ENABLE;
+                       vgpu_vreg_t(vgpu, SPRCTL(pipe)) &= ~SPRITE_ENABLE;
+                       vgpu_vreg_t(vgpu, CURCNTR(pipe)) &= ~MCURSOR_MODE;
+                       vgpu_vreg_t(vgpu, CURCNTR(pipe)) |= MCURSOR_MODE_DISABLE;
+               }
+
+               for (trans = TRANSCODER_A; trans <= TRANSCODER_EDP; trans++) {
+                       vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(trans)) &=
+                               ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
+                                 TRANS_DDI_PORT_MASK | TRANS_DDI_FUNC_ENABLE);
+               }
+               vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &=
+                       ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
+                         TRANS_DDI_PORT_MASK);
+
+               for (port = PORT_A; port <= PORT_C; port++) {
+                       vgpu_vreg_t(vgpu, BXT_PHY_CTL(port)) &=
+                               ~BXT_PHY_LANE_ENABLED;
+                       vgpu_vreg_t(vgpu, BXT_PHY_CTL(port)) |=
+                               (BXT_PHY_CMNLANE_POWERDOWN_ACK |
+                                BXT_PHY_LANE_POWERDOWN_ACK);
+
+                       vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(port)) &=
+                               ~(PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
+                                 PORT_PLL_REF_SEL | PORT_PLL_LOCK |
+                                 PORT_PLL_ENABLE);
+
+                       vgpu_vreg_t(vgpu, DDI_BUF_CTL(port)) &=
+                               ~(DDI_INIT_DISPLAY_DETECTED |
+                                 DDI_BUF_CTL_ENABLE);
+                       vgpu_vreg_t(vgpu, DDI_BUF_CTL(port)) |= DDI_BUF_IS_IDLE;
+               }
+
+               vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) &= ~(BIT(0) | BIT(1));
+               vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) &=
+                       ~PHY_POWER_GOOD;
+               vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY1)) &=
+                       ~PHY_POWER_GOOD;
+               vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) &= ~BIT(30);
+               vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY1)) &= ~BIT(30);
+
+               vgpu_vreg_t(vgpu, SFUSE_STRAP) &= ~SFUSE_STRAP_DDIB_DETECTED;
+               vgpu_vreg_t(vgpu, SFUSE_STRAP) &= ~SFUSE_STRAP_DDIC_DETECTED;
+
+               /*
+                * Only 1 PIPE enabled in current vGPU display and PIPE_A is
+                *  tied to TRANSCODER_A in HW, so it's safe to assume PIPE_A,
+                *   TRANSCODER_A can be enabled. PORT_x depends on the input of
+                *   setup_virtual_dp_monitor.
+                */
+               vgpu_vreg_t(vgpu, PIPECONF(PIPE_A)) |= PIPECONF_ENABLE;
+               vgpu_vreg_t(vgpu, PIPECONF(PIPE_A)) |= I965_PIPECONF_ACTIVE;
+
+               /*
+                * Golden M/N are calculated based on:
+                *   24 bpp, 4 lanes, 154000 pixel clk (from virtual EDID),
+                *   DP link clk 1620 MHz and non-constant_n.
+                * TODO: calculate DP link symbol clk and stream clk m/n.
+                */
+               vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) = 63 << TU_SIZE_SHIFT;
+               vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) |= 0x5b425e;
+               vgpu_vreg_t(vgpu, PIPE_DATA_N1(TRANSCODER_A)) = 0x800000;
+               vgpu_vreg_t(vgpu, PIPE_LINK_M1(TRANSCODER_A)) = 0x3cd6e;
+               vgpu_vreg_t(vgpu, PIPE_LINK_N1(TRANSCODER_A)) = 0x80000;
+
+               /* Enable per-DDI/PORT vreg */
                if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
+                       vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(1);
+                       vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY1)) |=
+                               PHY_POWER_GOOD;
+                       vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY1)) |=
+                               BIT(30);
+                       vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_A)) |=
+                               BXT_PHY_LANE_ENABLED;
+                       vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_A)) &=
+                               ~(BXT_PHY_CMNLANE_POWERDOWN_ACK |
+                                 BXT_PHY_LANE_POWERDOWN_ACK);
+                       vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_A)) |=
+                               (PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
+                                PORT_PLL_REF_SEL | PORT_PLL_LOCK |
+                                PORT_PLL_ENABLE);
+                       vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_A)) |=
+                               (DDI_BUF_CTL_ENABLE | DDI_INIT_DISPLAY_DETECTED);
+                       vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_A)) &=
+                               ~DDI_BUF_IS_IDLE;
+                       vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)) |=
+                               (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
+                                TRANS_DDI_FUNC_ENABLE);
                        vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
                                GEN8_DE_PORT_HOTPLUG(HPD_PORT_A);
                }
 
                if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
+                       vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIB_DETECTED;
+                       vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(0);
+                       vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) |=
+                               PHY_POWER_GOOD;
+                       vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) |=
+                               BIT(30);
+                       vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_B)) |=
+                               BXT_PHY_LANE_ENABLED;
+                       vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_B)) &=
+                               ~(BXT_PHY_CMNLANE_POWERDOWN_ACK |
+                                 BXT_PHY_LANE_POWERDOWN_ACK);
+                       vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_B)) |=
+                               (PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
+                                PORT_PLL_REF_SEL | PORT_PLL_LOCK |
+                                PORT_PLL_ENABLE);
+                       vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_B)) |=
+                               DDI_BUF_CTL_ENABLE;
+                       vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_B)) &=
+                               ~DDI_BUF_IS_IDLE;
+                       vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
+                               (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
+                                (PORT_B << TRANS_DDI_PORT_SHIFT) |
+                                TRANS_DDI_FUNC_ENABLE);
                        vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
                                GEN8_DE_PORT_HOTPLUG(HPD_PORT_B);
                }
 
                if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
+                       vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIC_DETECTED;
+                       vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(0);
+                       vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) |=
+                               PHY_POWER_GOOD;
+                       vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) |=
+                               BIT(30);
+                       vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) |=
+                               BXT_PHY_LANE_ENABLED;
+                       vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) &=
+                               ~(BXT_PHY_CMNLANE_POWERDOWN_ACK |
+                                 BXT_PHY_LANE_POWERDOWN_ACK);
+                       vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_C)) |=
+                               (PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
+                                PORT_PLL_REF_SEL | PORT_PLL_LOCK |
+                                PORT_PLL_ENABLE);
+                       vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_C)) |=
+                               DDI_BUF_CTL_ENABLE;
+                       vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_C)) &=
+                               ~DDI_BUF_IS_IDLE;
+                       vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
+                               (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
+                                (PORT_B << TRANS_DDI_PORT_SHIFT) |
+                                TRANS_DDI_FUNC_ENABLE);
                        vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
                                GEN8_DE_PORT_HOTPLUG(HPD_PORT_C);
                }
@@ -520,6 +660,45 @@ void intel_vgpu_emulate_hotplug(struct intel_vgpu *vgpu, bool connected)
                vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
                                PORTD_HOTPLUG_STATUS_MASK;
                intel_vgpu_trigger_virtual_event(vgpu, DP_D_HOTPLUG);
+       } else if (IS_BROXTON(i915)) {
+               if (connected) {
+                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
+                               vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
+                                       GEN8_DE_PORT_HOTPLUG(HPD_PORT_A);
+                       }
+                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
+                               vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
+                                       SFUSE_STRAP_DDIB_DETECTED;
+                               vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
+                                       GEN8_DE_PORT_HOTPLUG(HPD_PORT_B);
+                       }
+                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
+                               vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
+                                       SFUSE_STRAP_DDIC_DETECTED;
+                               vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
+                                       GEN8_DE_PORT_HOTPLUG(HPD_PORT_C);
+                       }
+               } else {
+                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
+                               vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
+                                       ~GEN8_DE_PORT_HOTPLUG(HPD_PORT_A);
+                       }
+                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
+                               vgpu_vreg_t(vgpu, SFUSE_STRAP) &=
+                                       ~SFUSE_STRAP_DDIB_DETECTED;
+                               vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
+                                       ~GEN8_DE_PORT_HOTPLUG(HPD_PORT_B);
+                       }
+                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
+                               vgpu_vreg_t(vgpu, SFUSE_STRAP) &=
+                                       ~SFUSE_STRAP_DDIC_DETECTED;
+                               vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
+                                       ~GEN8_DE_PORT_HOTPLUG(HPD_PORT_C);
+                       }
+               }
+               vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+                       PORTB_HOTPLUG_STATUS_MASK;
+               intel_vgpu_trigger_virtual_event(vgpu, DP_B_HOTPLUG);
        }
 }
 
index b6811f6a230df4e18291bdc59f6b2d564ceb75c3..24210b1eaec5821c1d7dda3b1e6c9bb38e7c11f8 100644 (file)
@@ -280,6 +280,11 @@ void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu, bool dmlr)
                        vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) |=
                                    BXT_PHY_CMNLANE_POWERDOWN_ACK |
                                    BXT_PHY_LANE_POWERDOWN_ACK;
+                       vgpu_vreg_t(vgpu, SKL_FUSE_STATUS) |=
+                               SKL_FUSE_DOWNLOAD_STATUS |
+                               SKL_FUSE_PG_DIST_STATUS(SKL_PG0) |
+                               SKL_FUSE_PG_DIST_STATUS(SKL_PG1) |
+                               SKL_FUSE_PG_DIST_STATUS(SKL_PG2);
                }
        } else {
 #define GVT_GEN8_MMIO_RESET_OFFSET             (0x44200)