@@ -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+
23382395static 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
23892448err_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
0 commit comments