1 1.1 riastrad /* $NetBSD: i915_switcheroo.c,v 1.2 2021/12/18 23:45:28 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad // SPDX-License-Identifier: MIT 4 1.1 riastrad /* 5 1.1 riastrad * Copyright 2019 Intel Corporation 6 1.1 riastrad */ 7 1.1 riastrad 8 1.1 riastrad #include <sys/cdefs.h> 9 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: i915_switcheroo.c,v 1.2 2021/12/18 23:45:28 riastradh Exp $"); 10 1.1 riastrad 11 1.1 riastrad #include <linux/vga_switcheroo.h> 12 1.1 riastrad 13 1.1 riastrad #include "i915_drv.h" 14 1.1 riastrad #include "i915_switcheroo.h" 15 1.1 riastrad 16 1.1 riastrad static void i915_switcheroo_set_state(struct pci_dev *pdev, 17 1.1 riastrad enum vga_switcheroo_state state) 18 1.1 riastrad { 19 1.1 riastrad struct drm_i915_private *i915 = pdev_to_i915(pdev); 20 1.1 riastrad pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; 21 1.1 riastrad 22 1.1 riastrad if (!i915) { 23 1.1 riastrad dev_err(&pdev->dev, "DRM not initialized, aborting switch.\n"); 24 1.1 riastrad return; 25 1.1 riastrad } 26 1.1 riastrad 27 1.1 riastrad if (state == VGA_SWITCHEROO_ON) { 28 1.1 riastrad pr_info("switched on\n"); 29 1.1 riastrad i915->drm.switch_power_state = DRM_SWITCH_POWER_CHANGING; 30 1.1 riastrad /* i915 resume handler doesn't set to D0 */ 31 1.1 riastrad pci_set_power_state(pdev, PCI_D0); 32 1.1 riastrad i915_resume_switcheroo(i915); 33 1.1 riastrad i915->drm.switch_power_state = DRM_SWITCH_POWER_ON; 34 1.1 riastrad } else { 35 1.1 riastrad pr_info("switched off\n"); 36 1.1 riastrad i915->drm.switch_power_state = DRM_SWITCH_POWER_CHANGING; 37 1.1 riastrad i915_suspend_switcheroo(i915, pmm); 38 1.1 riastrad i915->drm.switch_power_state = DRM_SWITCH_POWER_OFF; 39 1.1 riastrad } 40 1.1 riastrad } 41 1.1 riastrad 42 1.1 riastrad static bool i915_switcheroo_can_switch(struct pci_dev *pdev) 43 1.1 riastrad { 44 1.1 riastrad struct drm_i915_private *i915 = pdev_to_i915(pdev); 45 1.1 riastrad 46 1.1 riastrad /* 47 1.1 riastrad * FIXME: open_count is protected by drm_global_mutex but that would lead to 48 1.1 riastrad * locking inversion with the driver load path. And the access here is 49 1.1 riastrad * completely racy anyway. So don't bother with locking for now. 50 1.1 riastrad */ 51 1.1 riastrad return i915 && i915->drm.open_count == 0; 52 1.1 riastrad } 53 1.1 riastrad 54 1.1 riastrad static const struct vga_switcheroo_client_ops i915_switcheroo_ops = { 55 1.1 riastrad .set_gpu_state = i915_switcheroo_set_state, 56 1.1 riastrad .reprobe = NULL, 57 1.1 riastrad .can_switch = i915_switcheroo_can_switch, 58 1.1 riastrad }; 59 1.1 riastrad 60 1.1 riastrad int i915_switcheroo_register(struct drm_i915_private *i915) 61 1.1 riastrad { 62 1.1 riastrad struct pci_dev *pdev = i915->drm.pdev; 63 1.1 riastrad 64 1.1 riastrad return vga_switcheroo_register_client(pdev, &i915_switcheroo_ops, false); 65 1.1 riastrad } 66 1.1 riastrad 67 1.1 riastrad void i915_switcheroo_unregister(struct drm_i915_private *i915) 68 1.1 riastrad { 69 1.1 riastrad struct pci_dev *pdev = i915->drm.pdev; 70 1.1 riastrad 71 1.1 riastrad vga_switcheroo_unregister_client(pdev); 72 1.1 riastrad } 73