Skip to content

Commit a36e7dc

Browse files
catayloxlucasdemarchi
authored andcommitted
drm/i915/dg1: Read OPROM via SPI controller
Read OPROM SPI through MMIO and find VBT entry since we can't use OpRegion and PCI mapping may not work on some systems due to most BIOSes not leaving the Option ROM mapped. v2: Remove message with allocation failure Cc: Ville Syrjälä <[email protected]> Cc: Tomas Winkler <[email protected]> Signed-off-by: Clint Taylor <[email protected]> Signed-off-by: Lucas De Marchi <[email protected]> Signed-off-by: Jani Nikula <[email protected]> Acked-by: Jani Nikula <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent d0c0cf2 commit a36e7dc

File tree

2 files changed

+79
-6
lines changed

2 files changed

+79
-6
lines changed

drivers/gpu/drm/i915/display/intel_bios.c

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,6 +2335,63 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size)
23352335
return vbt;
23362336
}
23372337

2338+
static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915)
2339+
{
2340+
u32 count, data, found, store = 0;
2341+
u32 static_region, oprom_offset;
2342+
u32 oprom_size = 0x200000;
2343+
u16 vbt_size;
2344+
u32 *vbt;
2345+
2346+
static_region = intel_uncore_read(&i915->uncore, SPI_STATIC_REGIONS);
2347+
static_region &= OPTIONROM_SPI_REGIONID_MASK;
2348+
intel_uncore_write(&i915->uncore, PRIMARY_SPI_REGIONID, static_region);
2349+
2350+
oprom_offset = intel_uncore_read(&i915->uncore, OROM_OFFSET);
2351+
oprom_offset &= OROM_OFFSET_MASK;
2352+
2353+
for (count = 0; count < oprom_size; count += 4) {
2354+
intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, oprom_offset + count);
2355+
data = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER);
2356+
2357+
if (data == *((const u32 *)"$VBT")) {
2358+
found = oprom_offset + count;
2359+
break;
2360+
}
2361+
}
2362+
2363+
if (count >= oprom_size)
2364+
goto err_not_found;
2365+
2366+
/* Get VBT size and allocate space for the VBT */
2367+
intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, found +
2368+
offsetof(struct vbt_header, vbt_size));
2369+
vbt_size = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER);
2370+
vbt_size &= 0xffff;
2371+
2372+
vbt = kzalloc(vbt_size, GFP_KERNEL);
2373+
if (!vbt)
2374+
goto err_not_found;
2375+
2376+
for (count = 0; count < vbt_size; count += 4) {
2377+
intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, found + count);
2378+
data = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER);
2379+
*(vbt + store++) = data;
2380+
}
2381+
2382+
if (!intel_bios_is_valid_vbt(vbt, vbt_size))
2383+
goto err_free_vbt;
2384+
2385+
drm_dbg_kms(&i915->drm, "Found valid VBT in SPI flash\n");
2386+
2387+
return (struct vbt_header *)vbt;
2388+
2389+
err_free_vbt:
2390+
kfree(vbt);
2391+
err_not_found:
2392+
return NULL;
2393+
}
2394+
23382395
static struct vbt_header *oprom_get_vbt(struct drm_i915_private *i915)
23392396
{
23402397
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
@@ -2384,6 +2441,8 @@ static struct vbt_header *oprom_get_vbt(struct drm_i915_private *i915)
23842441

23852442
pci_unmap_rom(pdev, oprom);
23862443

2444+
drm_dbg_kms(&i915->drm, "Found valid VBT in PCI ROM\n");
2445+
23872446
return vbt;
23882447

23892448
err_free_vbt:
@@ -2418,17 +2477,23 @@ void intel_bios_init(struct drm_i915_private *i915)
24182477

24192478
init_vbt_defaults(i915);
24202479

2421-
/* If the OpRegion does not have VBT, look in PCI ROM. */
2480+
/*
2481+
* If the OpRegion does not have VBT, look in SPI flash through MMIO or
2482+
* PCI mapping
2483+
*/
2484+
if (!vbt && IS_DGFX(i915)) {
2485+
oprom_vbt = spi_oprom_get_vbt(i915);
2486+
vbt = oprom_vbt;
2487+
}
2488+
24222489
if (!vbt) {
24232490
oprom_vbt = oprom_get_vbt(i915);
2424-
if (!oprom_vbt)
2425-
goto out;
2426-
24272491
vbt = oprom_vbt;
2428-
2429-
drm_dbg_kms(&i915->drm, "Found valid VBT in PCI ROM\n");
24302492
}
24312493

2494+
if (!vbt)
2495+
goto out;
2496+
24322497
bdb = get_bdb_header(vbt);
24332498
i915->vbt.version = bdb->version;
24342499

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12853,6 +12853,14 @@ enum skl_power_gate {
1285312853
#define TCSS_DDI_STATUS_HPD_LIVE_STATUS_TBT REG_BIT(1)
1285412854
#define TCSS_DDI_STATUS_HPD_LIVE_STATUS_ALT REG_BIT(0)
1285512855

12856+
#define PRIMARY_SPI_TRIGGER _MMIO(0x102040)
12857+
#define PRIMARY_SPI_ADDRESS _MMIO(0x102080)
12858+
#define PRIMARY_SPI_REGIONID _MMIO(0x102084)
12859+
#define SPI_STATIC_REGIONS _MMIO(0x102090)
12860+
#define OPTIONROM_SPI_REGIONID_MASK REG_GENMASK(7, 0)
12861+
#define OROM_OFFSET _MMIO(0x1020c0)
12862+
#define OROM_OFFSET_MASK REG_GENMASK(20, 16)
12863+
1285612864
/* This register controls the Display State Buffer (DSB) engines. */
1285712865
#define _DSBSL_INSTANCE_BASE 0x70B00
1285812866
#define DSBSL_INSTANCE(pipe, id) (_DSBSL_INSTANCE_BASE + \

0 commit comments

Comments
 (0)