static void csr_load_work_fn(struct work_struct *work) { struct drm_i915_private *dev_priv; struct intel_csr *csr; const struct firmware *fw; int ret; dev_priv = container_of(work, typeof(*dev_priv), csr.work); csr = &dev_priv->csr; ret = request_firmware(&fw, dev_priv->csr.fw_path, &dev_priv->drm.pdev->dev); if (fw) dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw); if (dev_priv->csr.dmc_payload) { intel_csr_load_program(dev_priv); intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); DRM_INFO("Finished loading %s (v%u.%u)\n", dev_priv->csr.fw_path, CSR_VERSION_MAJOR(csr->version), CSR_VERSION_MINOR(csr->version)); } else { dev_notice(dev_priv->drm.dev, "Failed to load DMC firmware" " [" FIRMWARE_URL "]," " disabling runtime power management.\n"); } release_firmware(fw); }
static void intel_csr_runtime_pm_put(struct drm_i915_private *dev_priv) { intel_wakeref_t wakeref __maybe_unused = fetch_and_zero(&dev_priv->csr.wakeref); intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref); }
int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt) { struct drm_i915_private *dev_priv = crtc->dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum intel_display_power_domain power_domain; enum intel_pipe_crc_source source; u32 val = 0; /* shut up gcc */ int ret = 0; if (display_crc_ctl_parse_source(source_name, &source) < 0) { DRM_DEBUG_DRIVER("unknown source %s\n", source_name); return -EINVAL; } power_domain = POWER_DOMAIN_PIPE(crtc->index); if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) { DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n"); return -EIO; } ret = get_new_crc_ctl_reg(dev_priv, crtc->index, &source, &val); if (ret != 0) goto out; if (source) { /* * When IPS gets enabled, the pipe CRC changes. Since IPS gets * enabled and disabled dynamically based on package C states, * user space can't make reliable use of the CRCs, so let's just * completely disable it. */ hsw_disable_ips(intel_crtc); } I915_WRITE(PIPE_CRC_CTL(crtc->index), val); POSTING_READ(PIPE_CRC_CTL(crtc->index)); if (!source) { if (IS_G4X(dev_priv)) g4x_undo_pipe_scramble_reset(dev_priv, crtc->index); else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_undo_pipe_scramble_reset(dev_priv, crtc->index); else if (IS_HASWELL(dev_priv) && crtc->index == PIPE_A) hsw_trans_edp_pipe_A_crc_wa(dev_priv, false); hsw_enable_ips(intel_crtc); } pipe_crc->skipped = 0; *values_cnt = 5; out: intel_display_power_put(dev_priv, power_domain); return ret; }
/** * intel_csr_ucode_suspend() - prepare CSR firmware before system suspend * @dev_priv: i915 drm device * * Prepare the DMC firmware before entering system suspend. This includes * flushing pending work items and releasing any resources acquired during * init. */ void intel_csr_ucode_suspend(struct drm_i915_private *dev_priv) { if (!HAS_CSR(dev_priv)) return; flush_work(&dev_priv->csr.work); /* Drop the reference held in case DMC isn't loaded. */ if (!dev_priv->csr.dmc_payload) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); }
/** * intel_display_set_init_power - set the initial power domain state * @dev_priv: i915 device instance * @enable: whether to enable or disable the initial power domain state * * For simplicity our driver load/unload and system suspend/resume code assumes * that all power domains are always enabled. This functions controls the state * of this little hack. While the initial power domain state is enabled runtime * pm is effectively disabled. */ void intel_display_set_init_power(struct drm_i915_private *dev_priv, bool enable) { if (dev_priv->power_domains.init_power_on == enable) return; if (enable) intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); else intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); dev_priv->power_domains.init_power_on = enable; }
static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, struct intel_dpll_hw_state *hw_state) { uint32_t val; if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; val = I915_READ(SPLL_CTL); hw_state->spll = val; intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); return val & SPLL_PLL_ENABLE; }
int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt) { struct drm_i915_private *dev_priv = crtc->dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index]; enum intel_display_power_domain power_domain; enum intel_pipe_crc_source source; u32 val = 0; /* shut up gcc */ int ret = 0; if (display_crc_ctl_parse_source(source_name, &source) < 0) { DRM_DEBUG_DRIVER("unknown source %s\n", source_name); return -EINVAL; } power_domain = POWER_DOMAIN_PIPE(crtc->index); if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) { DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n"); return -EIO; } ret = get_new_crc_ctl_reg(dev_priv, crtc->index, &source, &val); if (ret != 0) goto out; I915_WRITE(PIPE_CRC_CTL(crtc->index), val); POSTING_READ(PIPE_CRC_CTL(crtc->index)); if (!source) { if (IS_G4X(dev_priv)) g4x_undo_pipe_scramble_reset(dev_priv, crtc->index); else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_undo_pipe_scramble_reset(dev_priv, crtc->index); else if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) && crtc->index == PIPE_A) hsw_pipe_A_crc_wa(dev_priv, false); } pipe_crc->skipped = 0; *values_cnt = 5; out: intel_display_power_put(dev_priv, power_domain); return ret; }
static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, struct intel_dpll_hw_state *hw_state) { uint32_t val; if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; val = I915_READ(PCH_DPLL(pll->id)); hw_state->dpll = val; hw_state->fp0 = I915_READ(PCH_FP0(pll->id)); hw_state->fp1 = I915_READ(PCH_FP1(pll->id)); intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); return val & DPLL_VCO_ENABLE; }
static enum drm_connector_status intel_dsi_detect(struct drm_connector *connector, bool force) { struct intel_dsi *intel_dsi = intel_attached_dsi(connector); struct intel_encoder *intel_encoder = &intel_dsi->base; enum intel_display_power_domain power_domain; enum drm_connector_status connector_status; struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private; DRM_DEBUG_KMS("\n"); power_domain = intel_display_port_power_domain(intel_encoder); intel_display_power_get(dev_priv, power_domain); connector_status = intel_dsi->dev.dev_ops->detect(&intel_dsi->dev); intel_display_power_put(dev_priv, power_domain); return connector_status; }
static void csr_load_work_fn(struct work_struct *work) { struct drm_i915_private *dev_priv; struct intel_csr *csr; const struct firmware *fw; int ret; dev_priv = container_of(work, typeof(*dev_priv), csr.work); csr = &dev_priv->csr; ret = request_firmware(&fw, dev_priv->csr.fw_path, &dev_priv->dev->pdev->dev); if (!fw) goto out; dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw); if (!dev_priv->csr.dmc_payload) goto out; /* load csr program during system boot, as needed for DC states */ intel_csr_load_program(dev_priv); out: if (dev_priv->csr.dmc_payload) { intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); DRM_INFO("Finished loading %s (v%u.%u)\n", dev_priv->csr.fw_path, CSR_VERSION_MAJOR(csr->version), CSR_VERSION_MINOR(csr->version)); } else { DRM_ERROR("Failed to load DMC firmware, disabling rpm\n"); } release_firmware(fw); }
static int pipe_crc_set_source(struct drm_i915_private *dev_priv, enum pipe pipe, enum intel_pipe_crc_source source) { struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); enum intel_display_power_domain power_domain; u32 val = 0; /* shut up gcc */ int ret; if (pipe_crc->source == source) return 0; /* forbid changing the source without going back to 'none' */ if (pipe_crc->source && source) return -EINVAL; power_domain = POWER_DOMAIN_PIPE(pipe); if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) { DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n"); return -EIO; } ret = get_new_crc_ctl_reg(dev_priv, pipe, &source, &val); if (ret != 0) goto out; /* none -> real source transition */ if (source) { struct intel_pipe_crc_entry *entries; DRM_DEBUG_DRIVER("collecting CRCs for pipe %c, %s\n", pipe_name(pipe), pipe_crc_source_name(source)); entries = kcalloc(INTEL_PIPE_CRC_ENTRIES_NR, sizeof(pipe_crc->entries[0]), GFP_KERNEL); if (!entries) { ret = -ENOMEM; goto out; } /* * When IPS gets enabled, the pipe CRC changes. Since IPS gets * enabled and disabled dynamically based on package C states, * user space can't make reliable use of the CRCs, so let's just * completely disable it. */ hsw_disable_ips(crtc); spin_lock_irq(&pipe_crc->lock); kfree(pipe_crc->entries); pipe_crc->entries = entries; pipe_crc->head = 0; pipe_crc->tail = 0; spin_unlock_irq(&pipe_crc->lock); } pipe_crc->source = source; I915_WRITE(PIPE_CRC_CTL(pipe), val); POSTING_READ(PIPE_CRC_CTL(pipe)); /* real source -> none transition */ if (!source) { struct intel_pipe_crc_entry *entries; struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n", pipe_name(pipe)); drm_modeset_lock(&crtc->base.mutex, NULL); if (crtc->base.state->active) intel_wait_for_vblank(dev_priv, pipe); drm_modeset_unlock(&crtc->base.mutex); spin_lock_irq(&pipe_crc->lock); entries = pipe_crc->entries; pipe_crc->entries = NULL; pipe_crc->head = 0; pipe_crc->tail = 0; spin_unlock_irq(&pipe_crc->lock); kfree(entries); if (IS_G4X(dev_priv)) g4x_undo_pipe_scramble_reset(dev_priv, pipe); else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_undo_pipe_scramble_reset(dev_priv, pipe); else if (IS_HASWELL(dev_priv) && pipe == PIPE_A) hsw_trans_edp_pipe_A_crc_wa(dev_priv, false); hsw_enable_ips(crtc); } ret = 0; out: intel_display_power_put(dev_priv, power_domain); return ret; }