/* SPDX-License-Identifier: GPL-2.0-only */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include uintptr_t fsp_soc_get_igd_bar(void) { return graphics_get_memory_base(); } static void graphics_setup_panel(struct device *dev) { struct soc_intel_skylake_config *conf = config_of(dev); struct resource *mmio_res; uint8_t *base; u32 reg32; if (!conf) return; mmio_res = find_resource(dev, PCI_BASE_ADDRESS_0); if (!mmio_res || !mmio_res->base) return; base = (void *)(uintptr_t)mmio_res->base; reg32 = conf->gpu_pp_up_delay_ms * 10 << 16; reg32 |= conf->gpu_pp_backlight_on_delay_ms * 10; write32(base + PCH_PP_ON_DELAYS, reg32); reg32 = conf->gpu_pp_down_delay_ms * 10 << 16; reg32 |= conf->gpu_pp_backlight_off_delay_ms * 10; write32(base + PCH_PP_OFF_DELAYS, reg32); reg32 = read32(base + PCH_PP_DIVISOR); reg32 &= ~0x1f; reg32 |= (DIV_ROUND_UP(conf->gpu_pp_cycle_delay_ms, 100) + 1) & 0x1f; write32(base + PCH_PP_DIVISOR, reg32); /* So far all devices seem to use the PCH PWM function. The CPU PWM registers are all zero after reset. */ if (conf->gpu_pch_backlight_pwm_hz) { /* Reference clock is 24MHz. We can choose either a 16 or a 128 step increment. Use 16 if we would have less than 100 steps otherwise. */ const unsigned int hz_limit = 24 * 1000 * 1000 / 128 / 100; unsigned int pwm_increment, pwm_period; u32 south_chicken1; south_chicken1 = read32(base + SOUTH_CHICKEN1); if (conf->gpu_pch_backlight_pwm_hz > hz_limit) { pwm_increment = 16; south_chicken1 &= ~1; } else { pwm_increment = 128; south_chicken1 |= 1; } write32(base + SOUTH_CHICKEN1, south_chicken1); pwm_period = 24 * 1000 * 1000 / pwm_increment / conf->gpu_pch_backlight_pwm_hz; /* Start with a 50% duty cycle. */ write32(base + BLC_PWM_PCH_CTL2, pwm_period << 16 | pwm_period / 2); write32(base + BLC_PWM_PCH_CTL1, !!conf->gpu_pch_backlight_polarity << 29 | BLM_PCH_PWM_ENABLE); } } void graphics_soc_init(struct device *dev) { u32 ddi_buf_ctl; graphics_setup_panel(dev); /* * Enable DDI-A (eDP) 4-lane operation if the link is not up yet. * This will allow the kernel to use 4-lane eDP links properly * if the VBIOS or GOP driver does not execute. */ ddi_buf_ctl = graphics_gtt_read(DDI_BUF_CTL_A); if (!acpi_is_wakeup_s3() && !(ddi_buf_ctl & DDI_BUF_CTL_ENABLE)) { ddi_buf_ctl |= DDI_A_4_LANES; graphics_gtt_write(DDI_BUF_CTL_A, ddi_buf_ctl); } /* IGD needs to Bus Master */ u32 reg32 = pci_read_config32(dev, PCI_COMMAND); reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; pci_write_config32(dev, PCI_COMMAND, reg32); /* * GFX PEIM module inside FSP binary is taking care of graphics * initialization based on RUN_FSP_GOP Kconfig option and input * VBT file. * * In case of non-FSP solution, SoC need to select another * Kconfig to perform GFX initialization. */ if (CONFIG(RUN_FSP_GOP)) { /* nothing to do */ } else if (CONFIG(MAINBOARD_USE_LIBGFXINIT)) { if (!acpi_is_wakeup_s3() && display_init_required()) { int lightup_ok; gma_gfxinit(&lightup_ok); gfx_set_init_done(lightup_ok); } } else { /* Initialize PCI device, load/execute BIOS Option ROM */ pci_dev_init(dev); } intel_gma_restore_opregion(); } uintptr_t gma_get_gnvs_aslb(const void *gnvs) { const global_nvs_t *gnvs_ptr = gnvs; return (uintptr_t)(gnvs_ptr ? gnvs_ptr->aslb : 0); } void gma_set_gnvs_aslb(void *gnvs, uintptr_t aslb) { global_nvs_t *gnvs_ptr = gnvs; if (gnvs_ptr) gnvs_ptr->aslb = aslb; } /* Initialize IGD OpRegion, called from ACPI code */ static void update_igd_opregion(igd_opregion_t *opregion) { /* FIXME: Add platform specific mailbox initialization */ } uintptr_t graphics_soc_write_acpi_opregion(const struct device *device, uintptr_t current, struct acpi_rsdp *rsdp) { igd_opregion_t *opregion; global_nvs_t *gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); /* If GOP is not used, exit here */ if (!CONFIG(INTEL_GMA_ADD_VBT)) return current; /* If IGD is disabled, exit here */ if (pci_read_config16(device, PCI_VENDOR_ID) == 0xFFFF) return current; printk(BIOS_DEBUG, "ACPI: * IGD OpRegion\n"); opregion = (igd_opregion_t *)current; if (intel_gma_init_igd_opregion(opregion) != CB_SUCCESS) return current; if (gnvs) gnvs->aslb = (u32)(uintptr_t)opregion; update_igd_opregion(opregion); current += sizeof(igd_opregion_t); current = acpi_align_current(current); printk(BIOS_DEBUG, "current = %lx\n", current); return current; } const struct i915_gpu_controller_info * intel_igd_get_controller_info(const struct device *device) { struct soc_intel_skylake_config *chip = device->chip_info; return &chip->gfx; }