1 1.2 riastrad /* $NetBSD: nouveau_vga.c,v 1.3 2021/12/18 23:45:32 riastradh Exp $ */ 2 1.2 riastrad 3 1.3 riastrad // SPDX-License-Identifier: MIT 4 1.2 riastrad #include <sys/cdefs.h> 5 1.2 riastrad __KERNEL_RCSID(0, "$NetBSD: nouveau_vga.c,v 1.3 2021/12/18 23:45:32 riastradh Exp $"); 6 1.2 riastrad 7 1.1 riastrad #include <linux/vgaarb.h> 8 1.1 riastrad #include <linux/vga_switcheroo.h> 9 1.1 riastrad 10 1.1 riastrad #include <drm/drm_crtc_helper.h> 11 1.3 riastrad #include <drm/drm_fb_helper.h> 12 1.1 riastrad 13 1.3 riastrad #include "nouveau_drv.h" 14 1.1 riastrad #include "nouveau_acpi.h" 15 1.1 riastrad #include "nouveau_fbcon.h" 16 1.1 riastrad #include "nouveau_vga.h" 17 1.1 riastrad 18 1.1 riastrad static unsigned int 19 1.1 riastrad nouveau_vga_set_decode(void *priv, bool state) 20 1.1 riastrad { 21 1.2 riastrad struct nouveau_drm *drm = nouveau_drm(priv); 22 1.3 riastrad struct nvif_object *device = &drm->client.device.object; 23 1.1 riastrad 24 1.3 riastrad if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CURIE && 25 1.3 riastrad drm->client.device.info.chipset >= 0x4c) 26 1.2 riastrad nvif_wr32(device, 0x088060, state); 27 1.2 riastrad else 28 1.3 riastrad if (drm->client.device.info.chipset >= 0x40) 29 1.2 riastrad nvif_wr32(device, 0x088054, state); 30 1.1 riastrad else 31 1.2 riastrad nvif_wr32(device, 0x001854, state); 32 1.1 riastrad 33 1.1 riastrad if (state) 34 1.1 riastrad return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | 35 1.1 riastrad VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; 36 1.1 riastrad else 37 1.1 riastrad return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; 38 1.1 riastrad } 39 1.1 riastrad 40 1.1 riastrad static void 41 1.1 riastrad nouveau_switcheroo_set_state(struct pci_dev *pdev, 42 1.1 riastrad enum vga_switcheroo_state state) 43 1.1 riastrad { 44 1.1 riastrad struct drm_device *dev = pci_get_drvdata(pdev); 45 1.1 riastrad 46 1.1 riastrad if ((nouveau_is_optimus() || nouveau_is_v1_dsm()) && state == VGA_SWITCHEROO_OFF) 47 1.1 riastrad return; 48 1.1 riastrad 49 1.1 riastrad if (state == VGA_SWITCHEROO_ON) { 50 1.3 riastrad pr_err("VGA switcheroo: switched nouveau on\n"); 51 1.1 riastrad dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; 52 1.1 riastrad nouveau_pmops_resume(&pdev->dev); 53 1.1 riastrad dev->switch_power_state = DRM_SWITCH_POWER_ON; 54 1.1 riastrad } else { 55 1.3 riastrad pr_err("VGA switcheroo: switched nouveau off\n"); 56 1.1 riastrad dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; 57 1.1 riastrad nouveau_switcheroo_optimus_dsm(); 58 1.1 riastrad nouveau_pmops_suspend(&pdev->dev); 59 1.1 riastrad dev->switch_power_state = DRM_SWITCH_POWER_OFF; 60 1.1 riastrad } 61 1.1 riastrad } 62 1.1 riastrad 63 1.1 riastrad static void 64 1.1 riastrad nouveau_switcheroo_reprobe(struct pci_dev *pdev) 65 1.1 riastrad { 66 1.1 riastrad struct drm_device *dev = pci_get_drvdata(pdev); 67 1.3 riastrad drm_fb_helper_output_poll_changed(dev); 68 1.1 riastrad } 69 1.1 riastrad 70 1.1 riastrad static bool 71 1.1 riastrad nouveau_switcheroo_can_switch(struct pci_dev *pdev) 72 1.1 riastrad { 73 1.1 riastrad struct drm_device *dev = pci_get_drvdata(pdev); 74 1.1 riastrad 75 1.2 riastrad /* 76 1.2 riastrad * FIXME: open_count is protected by drm_global_mutex but that would lead to 77 1.2 riastrad * locking inversion with the driver load path. And the access here is 78 1.2 riastrad * completely racy anyway. So don't bother with locking for now. 79 1.2 riastrad */ 80 1.2 riastrad return dev->open_count == 0; 81 1.1 riastrad } 82 1.1 riastrad 83 1.1 riastrad static const struct vga_switcheroo_client_ops 84 1.1 riastrad nouveau_switcheroo_ops = { 85 1.1 riastrad .set_gpu_state = nouveau_switcheroo_set_state, 86 1.1 riastrad .reprobe = nouveau_switcheroo_reprobe, 87 1.1 riastrad .can_switch = nouveau_switcheroo_can_switch, 88 1.1 riastrad }; 89 1.1 riastrad 90 1.1 riastrad void 91 1.1 riastrad nouveau_vga_init(struct nouveau_drm *drm) 92 1.1 riastrad { 93 1.1 riastrad struct drm_device *dev = drm->dev; 94 1.3 riastrad bool runtime = nouveau_pmops_runtime(); 95 1.1 riastrad 96 1.1 riastrad /* only relevant for PCI devices */ 97 1.1 riastrad if (!dev->pdev) 98 1.1 riastrad return; 99 1.1 riastrad 100 1.1 riastrad vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); 101 1.1 riastrad 102 1.3 riastrad /* don't register Thunderbolt eGPU with vga_switcheroo */ 103 1.3 riastrad if (pci_is_thunderbolt_attached(dev->pdev)) 104 1.3 riastrad return; 105 1.3 riastrad 106 1.1 riastrad vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, runtime); 107 1.1 riastrad 108 1.1 riastrad if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) 109 1.1 riastrad vga_switcheroo_init_domain_pm_ops(drm->dev->dev, &drm->vga_pm_domain); 110 1.1 riastrad } 111 1.1 riastrad 112 1.1 riastrad void 113 1.1 riastrad nouveau_vga_fini(struct nouveau_drm *drm) 114 1.1 riastrad { 115 1.1 riastrad struct drm_device *dev = drm->dev; 116 1.3 riastrad bool runtime = nouveau_pmops_runtime(); 117 1.3 riastrad 118 1.3 riastrad /* only relevant for PCI devices */ 119 1.3 riastrad if (!dev->pdev) 120 1.3 riastrad return; 121 1.2 riastrad 122 1.3 riastrad vga_client_register(dev->pdev, NULL, NULL, NULL); 123 1.3 riastrad 124 1.3 riastrad if (pci_is_thunderbolt_attached(dev->pdev)) 125 1.3 riastrad return; 126 1.2 riastrad 127 1.1 riastrad vga_switcheroo_unregister_client(dev->pdev); 128 1.2 riastrad if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) 129 1.2 riastrad vga_switcheroo_fini_domain_pm_ops(drm->dev->dev); 130 1.1 riastrad } 131 1.1 riastrad 132 1.1 riastrad 133 1.1 riastrad void 134 1.1 riastrad nouveau_vga_lastclose(struct drm_device *dev) 135 1.1 riastrad { 136 1.1 riastrad vga_switcheroo_process_delayed_switch(); 137 1.1 riastrad } 138