1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2019 Intel Corporation 4 */ 5 6 #include <linux/delay.h> 7 #include <linux/pci.h> 8 #include <linux/vgaarb.h> 9 10 #include <drm/drm_device.h> 11 #include <drm/drm_print.h> 12 #include <video/vga.h> 13 14 #include "soc/intel_gmch.h" 15 16 #include "i915_reg.h" 17 #include "intel_de.h" 18 #include "intel_display.h" 19 #include "intel_vga.h" 20 #include "intel_vga_regs.h" 21 22 static i915_reg_t intel_vga_cntrl_reg(struct intel_display *display) 23 { 24 if (display->platform.valleyview || display->platform.cherryview) 25 return VLV_VGACNTRL; 26 else if (DISPLAY_VER(display) >= 5) 27 return CPU_VGACNTRL; 28 else 29 return VGACNTRL; 30 } 31 32 static bool has_vga_pipe_sel(struct intel_display *display) 33 { 34 if (display->platform.i845g || 35 display->platform.i865g) 36 return false; 37 38 if (display->platform.valleyview || 39 display->platform.cherryview) 40 return true; 41 42 return DISPLAY_VER(display) < 7; 43 } 44 45 /* Disable the VGA plane that we never use */ 46 void intel_vga_disable(struct intel_display *display) 47 { 48 struct pci_dev *pdev = to_pci_dev(display->drm->dev); 49 i915_reg_t vga_reg = intel_vga_cntrl_reg(display); 50 enum pipe pipe; 51 u32 tmp; 52 u8 sr1; 53 54 tmp = intel_de_read(display, vga_reg); 55 if (tmp & VGA_DISP_DISABLE) 56 return; 57 58 if (display->platform.cherryview) 59 pipe = REG_FIELD_GET(VGA_PIPE_SEL_MASK_CHV, tmp); 60 else if (has_vga_pipe_sel(display)) 61 pipe = REG_FIELD_GET(VGA_PIPE_SEL_MASK, tmp); 62 else 63 pipe = PIPE_A; 64 65 drm_dbg_kms(display->drm, "Disabling VGA plane on pipe %c\n", 66 pipe_name(pipe)); 67 68 /* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */ 69 vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); 70 outb(0x01, VGA_SEQ_I); 71 sr1 = inb(VGA_SEQ_D); 72 outb(sr1 | VGA_SR01_SCREEN_OFF, VGA_SEQ_D); 73 vga_put(pdev, VGA_RSRC_LEGACY_IO); 74 udelay(300); 75 76 intel_de_write(display, vga_reg, VGA_DISP_DISABLE); 77 intel_de_posting_read(display, vga_reg); 78 } 79 80 void intel_vga_reset_io_mem(struct intel_display *display) 81 { 82 struct pci_dev *pdev = to_pci_dev(display->drm->dev); 83 84 /* 85 * After we re-enable the power well, if we touch VGA register 0x3d5 86 * we'll get unclaimed register interrupts. This stops after we write 87 * anything to the VGA MSR register. The vgacon module uses this 88 * register all the time, so if we unbind our driver and, as a 89 * consequence, bind vgacon, we'll get stuck in an infinite loop at 90 * console_unlock(). So make here we touch the VGA MSR register, making 91 * sure vgacon can keep working normally without triggering interrupts 92 * and error messages. 93 */ 94 vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); 95 outb(inb(VGA_MIS_R), VGA_MIS_W); 96 vga_put(pdev, VGA_RSRC_LEGACY_IO); 97 } 98 99 int intel_vga_register(struct intel_display *display) 100 { 101 102 struct pci_dev *pdev = to_pci_dev(display->drm->dev); 103 int ret; 104 105 /* 106 * If we have > 1 VGA cards, then we need to arbitrate access to the 107 * common VGA resources. 108 * 109 * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA), 110 * then we do not take part in VGA arbitration and the 111 * vga_client_register() fails with -ENODEV. 112 */ 113 ret = vga_client_register(pdev, intel_gmch_vga_set_decode); 114 if (ret && ret != -ENODEV) 115 return ret; 116 117 return 0; 118 } 119 120 void intel_vga_unregister(struct intel_display *display) 121 { 122 struct pci_dev *pdev = to_pci_dev(display->drm->dev); 123 124 vga_client_unregister(pdev); 125 } 126