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