static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation) { struct drm_i915_private *dev_priv = drm_dev->dev_private; bool fw_csr; int ret; disable_rpm_wakeref_asserts(dev_priv); fw_csr = suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload; /* * In case of firmware assisted context save/restore don't manually * deinit the power domains. This also means the CSR/DMC firmware will * stay active, it will power down any HW resources as required and * also enable deeper system power states that would be blocked if the * firmware was inactive. */ if (!fw_csr) intel_power_domains_suspend(dev_priv); ret = intel_suspend_complete(dev_priv); if (ret) { DRM_ERROR("Suspend complete failed: %d\n", ret); if (!fw_csr) intel_power_domains_init_hw(dev_priv, true); goto out; } pci_disable_device(drm_dev->pdev); /* * During hibernation on some platforms the BIOS may try to access * the device even though it's already in D3 and hang the machine. So * leave the device in D0 on those platforms and hope the BIOS will * power down the device properly. The issue was seen on multiple old * GENs with different BIOS vendors, so having an explicit blacklist * is inpractical; apply the workaround on everything pre GEN6. The * platforms where the issue was seen: * Lenovo Thinkpad X301, X61s, X60, T60, X41 * Fujitsu FSC S7110 * Acer Aspire 1830T */ if (!(hibernation && INTEL_INFO(dev_priv)->gen < 6)) pci_set_power_state(drm_dev->pdev, PCI_D3hot); dev_priv->suspended_to_idle = suspend_to_idle(dev_priv); out: enable_rpm_wakeref_asserts(dev_priv); return ret; }
static int i915_drm_thaw_early(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; if (IS_HASWELL(dev) || IS_BROADWELL(dev)) hsw_disable_pc8(dev_priv); intel_uncore_early_sanitize(dev, true); intel_uncore_sanitize(dev); intel_power_domains_init_hw(dev_priv); return 0; }
static int i915_drm_resume_early(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int ret = 0; /* * We have a resume ordering issue with the snd-hda driver also * requiring our device to be power up. Due to the lack of a * parent/child relationship we currently solve this with an early * resume hook. * * FIXME: This should be solved with a special hdmi sink device or * similar so that power domains can be employed. */ if (pci_enable_device(dev->pdev)) { ret = -EIO; goto out; } pci_set_master(dev->pdev); disable_rpm_wakeref_asserts(dev_priv); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) ret = vlv_resume_prepare(dev_priv, false); if (ret) DRM_ERROR("Resume prepare failed: %d, continuing anyway\n", ret); intel_uncore_early_sanitize(dev, true); if (IS_BROXTON(dev)) ret = bxt_resume_prepare(dev_priv); else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) hsw_disable_pc8(dev_priv); intel_uncore_sanitize(dev); if (!(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload)) intel_power_domains_init_hw(dev_priv, true); out: dev_priv->suspended_to_idle = false; enable_rpm_wakeref_asserts(dev_priv); return ret; }
static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) { struct drm_i915_private *dev_priv = dev->dev_private; int error = 0; intel_uncore_early_sanitize(dev); intel_uncore_sanitize(dev); if (drm_core_check_feature(dev, DRIVER_MODESET) && restore_gtt_mappings) { mutex_lock(&dev->struct_mutex); i915_gem_restore_gtt_mappings(dev); mutex_unlock(&dev->struct_mutex); } intel_power_domains_init_hw(dev); i915_restore_state(dev); intel_opregion_setup(dev); /* KMS EnterVT equivalent */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { intel_init_pch_refclk(dev); mutex_lock(&dev->struct_mutex); error = i915_gem_init_hw(dev); mutex_unlock(&dev->struct_mutex); /* We need working interrupts for modeset enabling ... */ drm_irq_install(dev); intel_modeset_init_hw(dev); drm_modeset_lock_all(dev); drm_mode_config_reset(dev); intel_modeset_setup_hw_state(dev, true); drm_modeset_unlock_all(dev); /* * ... but also need to make sure that hotplug processing * doesn't cause havoc. Like in the driver load code we don't * bother with the tiny race here where we might loose hotplug * notifications. * */ intel_hpd_init(dev); dev_priv->enable_hotplug_processing = true; /* Config may have changed between suspend and resume */ intel_resume_hotplug(dev); } intel_opregion_init(dev); /* * The console lock can be pretty contented on resume due * to all the printk activity. Try to keep it out of the hot * path of resume if possible. */ if (console_trylock()) { intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING); console_unlock(); } else { schedule_work(&dev_priv->console_resume_work); } /* Undo what we did at i915_drm_freeze so the refcount goes back to the * expected level. */ hsw_enable_package_c8(dev_priv); mutex_lock(&dev_priv->modeset_restore_lock); dev_priv->modeset_restore = MODESET_DONE; mutex_unlock(&dev_priv->modeset_restore_lock); intel_runtime_pm_put(dev_priv); return error; }
static int i915_load_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int ret; ret = intel_parse_bios(dev); if (ret) DRM_INFO("failed to find VBIOS tables\n"); /* If we have > 1 VGA cards, then we need to arbitrate access * to the common VGA resources. * * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA), * then we do not take part in VGA arbitration and the * vga_client_register() fails with -ENODEV. */ ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode); if (ret && ret != -ENODEV) goto out; intel_register_dsm_handler(); ret = vga_switcheroo_register_client(dev->pdev, &i915_switcheroo_ops, false); if (ret) goto cleanup_vga_client; /* Initialise stolen first so that we may reserve preallocated * objects for the BIOS to KMS transition. */ ret = i915_gem_init_stolen(dev); if (ret) goto cleanup_vga_switcheroo; intel_power_domains_init_hw(dev_priv); ret = intel_irq_install(dev_priv); if (ret) goto cleanup_gem_stolen; /* Important: The output setup functions called by modeset_init need * working irqs for e.g. gmbus and dp aux transfers. */ intel_modeset_init(dev); ret = i915_gem_init(dev); if (ret) goto cleanup_irq; intel_modeset_gem_init(dev); /* Always safe in the mode setting case. */ /* FIXME: do pre/post-mode set stuff in core KMS code */ dev->vblank_disable_allowed = true; if (INTEL_INFO(dev)->num_pipes == 0) return 0; ret = intel_fbdev_init(dev); if (ret) goto cleanup_gem; /* Only enable hotplug handling once the fbdev is fully set up. */ intel_hpd_init(dev_priv); /* * Some ports require correctly set-up hpd registers for detection to * work properly (leading to ghost connected connector status), e.g. VGA * on gm45. Hence we can only set up the initial fbdev config after hpd * irqs are fully enabled. Now we should scan for the initial config * only once hotplug handling is enabled, but due to screwed-up locking * around kms/fbdev init we can't protect the fdbev initial config * scanning against hotplug events. Hence do this first and ignore the * tiny window where we will loose hotplug notifactions. */ async_schedule(intel_fbdev_initial_config, dev_priv); drm_kms_helper_poll_init(dev); return 0; cleanup_gem: mutex_lock(&dev->struct_mutex); i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); cleanup_irq: drm_irq_uninstall(dev); cleanup_gem_stolen: i915_gem_cleanup_stolen(dev); cleanup_vga_switcheroo: vga_switcheroo_unregister_client(dev->pdev); cleanup_vga_client: vga_client_register(dev->pdev, NULL, NULL, NULL); out: return ret; }