static void guc_prepare_xfer(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); /* Must program this register before loading the ucode with DMA */ I915_WRITE(GUC_SHIM_CONTROL, GUC_DISABLE_SRAM_INIT_TO_ZEROES | GUC_ENABLE_READ_CACHE_LOGIC | GUC_ENABLE_MIA_CACHING | GUC_ENABLE_READ_CACHE_FOR_SRAM_DATA | GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA | GUC_ENABLE_MIA_CLOCK_GATING); if (IS_GEN9_LP(dev_priv)) I915_WRITE(GEN9LP_GT_PM_CONFIG, GT_DOORBELL_ENABLE); else I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE); if (IS_GEN(dev_priv, 9)) { /* DOP Clock Gating Enable for GuC clocks */ I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE | I915_READ(GEN7_MISCCPCTL))); /* allows for 5us (in 10ns units) before GT can go to RC6 */ I915_WRITE(GUC_ARAT_C6DIS, 0x1FF); } }
static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, resource_size_t *base, resource_size_t *size) { u32 reg_val = I915_READ(IS_GM45(dev_priv) ? CTG_STOLEN_RESERVED : ELK_STOLEN_RESERVED); resource_size_t stolen_top = dev_priv->dsm.end + 1; DRM_DEBUG_DRIVER("%s_STOLEN_RESERVED = %08x\n", IS_GM45(dev_priv) ? "CTG" : "ELK", reg_val); if ((reg_val & G4X_STOLEN_RESERVED_ENABLE) == 0) return; /* * Whether ILK really reuses the ELK register for this is unclear. * Let's see if we catch anyone with this supposedly enabled on ILK. */ WARN(IS_GEN(dev_priv, 5), "ILK stolen reserved found? 0x%08x\n", reg_val); if (!(reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK)) return; *base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16; WARN_ON((reg_val & G4X_STOLEN_RESERVED_ADDR1_MASK) < *base); *size = stolen_top - *base; }
/** * intel_csr_ucode_init() - initialize the firmware loading. * @dev_priv: i915 drm device. * * This function is called at the time of loading the display driver to read * firmware from a .bin file and copied into a internal memory. */ void intel_csr_ucode_init(struct drm_i915_private *dev_priv) { struct intel_csr *csr = &dev_priv->csr; INIT_WORK(&dev_priv->csr.work, csr_load_work_fn); if (!HAS_CSR(dev_priv)) return; /* * Obtain a runtime pm reference, until CSR is loaded, to avoid entering * runtime-suspend. * * On error, we return with the rpm wakeref held to prevent runtime * suspend as runtime suspend *requires* a working CSR for whatever * reason. */ intel_csr_runtime_pm_get(dev_priv); if (INTEL_GEN(dev_priv) >= 12) { /* Allow to load fw via parameter using the last known size */ csr->max_fw_size = GEN12_CSR_MAX_FW_SIZE; } else if (IS_GEN(dev_priv, 11)) { csr->fw_path = ICL_CSR_PATH; csr->required_version = ICL_CSR_VERSION_REQUIRED; csr->max_fw_size = ICL_CSR_MAX_FW_SIZE; } else if (IS_CANNONLAKE(dev_priv)) { csr->fw_path = CNL_CSR_PATH; csr->required_version = CNL_CSR_VERSION_REQUIRED; csr->max_fw_size = CNL_CSR_MAX_FW_SIZE; } else if (IS_GEMINILAKE(dev_priv)) { csr->fw_path = GLK_CSR_PATH; csr->required_version = GLK_CSR_VERSION_REQUIRED; csr->max_fw_size = GLK_CSR_MAX_FW_SIZE; } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { csr->fw_path = KBL_CSR_PATH; csr->required_version = KBL_CSR_VERSION_REQUIRED; csr->max_fw_size = KBL_CSR_MAX_FW_SIZE; } else if (IS_SKYLAKE(dev_priv)) { csr->fw_path = SKL_CSR_PATH; csr->required_version = SKL_CSR_VERSION_REQUIRED; csr->max_fw_size = SKL_CSR_MAX_FW_SIZE; } else if (IS_BROXTON(dev_priv)) { csr->fw_path = BXT_CSR_PATH; csr->required_version = BXT_CSR_VERSION_REQUIRED; csr->max_fw_size = BXT_CSR_MAX_FW_SIZE; } if (i915_modparams.dmc_firmware_path) { if (strlen(i915_modparams.dmc_firmware_path) == 0) { csr->fw_path = NULL; DRM_INFO("Disabling CSR firmware and runtime PM\n"); return; } csr->fw_path = i915_modparams.dmc_firmware_path; /* Bypass version check for firmware override. */ csr->required_version = 0; } if (csr->fw_path == NULL) { DRM_DEBUG_KMS("No known CSR firmware for platform, disabling runtime PM\n"); WARN_ON(!IS_ALPHA_SUPPORT(INTEL_INFO(dev_priv))); return; } DRM_DEBUG_KMS("Loading %s\n", csr->fw_path); schedule_work(&dev_priv->csr.work); }
static int i915_adjust_stolen(struct drm_i915_private *dev_priv, struct resource *dsm) { struct i915_ggtt *ggtt = &dev_priv->ggtt; struct resource *r; if (dsm->start == 0 || dsm->end <= dsm->start) return -EINVAL; /* * TODO: We have yet too encounter the case where the GTT wasn't at the * end of stolen. With that assumption we could simplify this. */ /* Make sure we don't clobber the GTT if it's within stolen memory */ if (INTEL_GEN(dev_priv) <= 4 && !IS_G33(dev_priv) && !IS_PINEVIEW(dev_priv) && !IS_G4X(dev_priv)) { struct resource stolen[2] = {*dsm, *dsm}; struct resource ggtt_res; resource_size_t ggtt_start; ggtt_start = I915_READ(PGTBL_CTL); if (IS_GEN(dev_priv, 4)) ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) | (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28; else ggtt_start &= PGTBL_ADDRESS_LO_MASK; ggtt_res = (struct resource) DEFINE_RES_MEM(ggtt_start, ggtt_total_entries(ggtt) * 4); if (ggtt_res.start >= stolen[0].start && ggtt_res.start < stolen[0].end) stolen[0].end = ggtt_res.start; if (ggtt_res.end > stolen[1].start && ggtt_res.end <= stolen[1].end) stolen[1].start = ggtt_res.end; /* Pick the larger of the two chunks */ if (resource_size(&stolen[0]) > resource_size(&stolen[1])) *dsm = stolen[0]; else *dsm = stolen[1]; if (stolen[0].start != stolen[1].start || stolen[0].end != stolen[1].end) { DRM_DEBUG_DRIVER("GTT within stolen memory at %pR\n", &ggtt_res); DRM_DEBUG_DRIVER("Stolen memory adjusted to %pR\n", dsm); } } /* * Verify that nothing else uses this physical address. Stolen * memory should be reserved by the BIOS and hidden from the * kernel. So if the region is already marked as busy, something * is seriously wrong. */ r = devm_request_mem_region(dev_priv->drm.dev, dsm->start, resource_size(dsm), "Graphics Stolen Memory"); if (r == NULL) { /* * One more attempt but this time requesting region from * start + 1, as we have seen that this resolves the region * conflict with the PCI Bus. * This is a BIOS w/a: Some BIOS wrap stolen in the root * PCI bus, but have an off-by-one error. Hence retry the * reservation starting from 1 instead of 0. * There's also BIOS with off-by-one on the other end. */ r = devm_request_mem_region(dev_priv->drm.dev, dsm->start + 1, resource_size(dsm) - 2, "Graphics Stolen Memory"); /* * GEN3 firmware likes to smash pci bridges into the stolen * range. Apparently this works. */ if (r == NULL && !IS_GEN(dev_priv, 3)) { DRM_ERROR("conflict detected with stolen region: %pR\n", dsm); return -EBUSY; } } return 0; }
static bool intel_fbc_can_activate(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_fbc *fbc = &dev_priv->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; /* We don't need to use a state cache here since this information is * global for all CRTC. */ if (fbc->underrun_detected) { fbc->no_fbc_reason = "underrun detected"; return false; } if (!cache->vma) { fbc->no_fbc_reason = "primary plane not visible"; return false; } if (cache->crtc.mode_flags & DRM_MODE_FLAG_INTERLACE) { fbc->no_fbc_reason = "incompatible mode"; return false; } if (!intel_fbc_hw_tracking_covers_screen(crtc)) { fbc->no_fbc_reason = "mode too large for compression"; return false; } /* The use of a CPU fence is mandatory in order to detect writes * by the CPU to the scanout and trigger updates to the FBC. * * Note that is possible for a tiled surface to be unmappable (and * so have no fence associated with it) due to aperture constaints * at the time of pinning. * * FIXME with 90/270 degree rotation we should use the fence on * the normal GTT view (the rotated view doesn't even have a * fence). Would need changes to the FBC fence Y offset as well. * For now this will effecively disable FBC with 90/270 degree * rotation. */ if (!(cache->flags & PLANE_HAS_FENCE)) { fbc->no_fbc_reason = "framebuffer not tiled or fenced"; return false; } if (INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv) && cache->plane.rotation != DRM_MODE_ROTATE_0) { fbc->no_fbc_reason = "rotation unsupported"; return false; } if (!stride_is_valid(dev_priv, cache->fb.stride)) { fbc->no_fbc_reason = "framebuffer stride not supported"; return false; } if (!pixel_format_is_valid(dev_priv, cache->fb.format->format)) { fbc->no_fbc_reason = "pixel format is invalid"; return false; } /* WaFbcExceedCdClockThreshold:hsw,bdw */ if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) && cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk.hw.cdclk * 95 / 100) { fbc->no_fbc_reason = "pixel rate is too big"; return false; } /* It is possible for the required CFB size change without a * crtc->disable + crtc->enable since it is possible to change the * stride without triggering a full modeset. Since we try to * over-allocate the CFB, there's a chance we may keep FBC enabled even * if this happens, but if we exceed the current CFB size we'll have to * disable FBC. Notice that it would be possible to disable FBC, wait * for a frame, free the stolen node, then try to reenable FBC in case * we didn't get any invalidate/deactivate calls, but this would require * a lot of tracking just for a specific case. If we conclude it's an * important case, we can implement it later. */ if (intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache) > fbc->compressed_fb.size * fbc->threshold) { fbc->no_fbc_reason = "CFB requirements changed"; return false; } /* * Work around a problem on GEN9+ HW, where enabling FBC on a plane * having a Y offset that isn't divisible by 4 causes FIFO underrun * and screen flicker. */ if (IS_GEN(dev_priv, 9, 10) && (fbc->state_cache.plane.adjusted_y & 3)) { fbc->no_fbc_reason = "plane Y offset is misaligned"; return false; } return true; }
int intel_uc_init_hw(struct drm_i915_private *i915) { struct intel_guc *guc = &i915->guc; struct intel_huc *huc = &i915->huc; int ret, attempts; if (!USES_GUC(i915)) return 0; GEM_BUG_ON(!HAS_GUC(i915)); guc_reset_interrupts(guc); /* WaEnableuKernelHeaderValidFix:skl */ /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */ if (IS_GEN(i915, 9)) attempts = 3; else attempts = 1; while (attempts--) { /* * Always reset the GuC just before (re)loading, so * that the state and timing are fairly predictable */ ret = __intel_uc_reset_hw(i915); if (ret) goto err_out; if (USES_HUC(i915)) { ret = intel_huc_fw_upload(huc); if (ret) goto err_out; } intel_guc_ads_reset(guc); intel_guc_init_params(guc); ret = intel_guc_fw_upload(guc); if (ret == 0) break; DRM_DEBUG_DRIVER("GuC fw load failed: %d; will reset and " "retry %d more time(s)\n", ret, attempts); } /* Did we succeded or run out of retries? */ if (ret) goto err_log_capture; ret = guc_enable_communication(guc); if (ret) goto err_log_capture; if (USES_HUC(i915)) { ret = intel_huc_auth(huc); if (ret) goto err_communication; } ret = intel_guc_sample_forcewake(guc); if (ret) goto err_communication; if (USES_GUC_SUBMISSION(i915)) { ret = intel_guc_submission_enable(guc); if (ret) goto err_communication; } dev_info(i915->drm.dev, "GuC firmware version %u.%u\n", guc->fw.major_ver_found, guc->fw.minor_ver_found); dev_info(i915->drm.dev, "GuC submission %s\n", enableddisabled(USES_GUC_SUBMISSION(i915))); dev_info(i915->drm.dev, "HuC %s\n", enableddisabled(USES_HUC(i915))); return 0; /* * We've failed to load the firmware :( */ err_communication: guc_disable_communication(guc); err_log_capture: guc_capture_load_err_log(guc); err_out: __uc_sanitize(i915); /* * Note that there is no fallback as either user explicitly asked for * the GuC or driver default option was to run with the GuC enabled. */ if (GEM_WARN_ON(ret == -EIO)) ret = -EINVAL; dev_err(i915->drm.dev, "GuC initialization failed %d\n", ret); return ret; }