Commit a36e7dc0 authored by Clint Taylor's avatar Clint Taylor Committed by Lucas De Marchi

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ä <ville.syrjala@linux.intel.com>
Cc: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarClint Taylor <clinton.a.taylor@intel.com>
Signed-off-by: default avatarLucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Acked-by: default avatarJani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211216062645.3477854-1-lucas.demarchi@intel.com
parent d0c0cf22
...@@ -2335,6 +2335,63 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size) ...@@ -2335,6 +2335,63 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size)
return vbt; return vbt;
} }
static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915)
{
u32 count, data, found, store = 0;
u32 static_region, oprom_offset;
u32 oprom_size = 0x200000;
u16 vbt_size;
u32 *vbt;
static_region = intel_uncore_read(&i915->uncore, SPI_STATIC_REGIONS);
static_region &= OPTIONROM_SPI_REGIONID_MASK;
intel_uncore_write(&i915->uncore, PRIMARY_SPI_REGIONID, static_region);
oprom_offset = intel_uncore_read(&i915->uncore, OROM_OFFSET);
oprom_offset &= OROM_OFFSET_MASK;
for (count = 0; count < oprom_size; count += 4) {
intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, oprom_offset + count);
data = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER);
if (data == *((const u32 *)"$VBT")) {
found = oprom_offset + count;
break;
}
}
if (count >= oprom_size)
goto err_not_found;
/* Get VBT size and allocate space for the VBT */
intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, found +
offsetof(struct vbt_header, vbt_size));
vbt_size = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER);
vbt_size &= 0xffff;
vbt = kzalloc(vbt_size, GFP_KERNEL);
if (!vbt)
goto err_not_found;
for (count = 0; count < vbt_size; count += 4) {
intel_uncore_write(&i915->uncore, PRIMARY_SPI_ADDRESS, found + count);
data = intel_uncore_read(&i915->uncore, PRIMARY_SPI_TRIGGER);
*(vbt + store++) = data;
}
if (!intel_bios_is_valid_vbt(vbt, vbt_size))
goto err_free_vbt;
drm_dbg_kms(&i915->drm, "Found valid VBT in SPI flash\n");
return (struct vbt_header *)vbt;
err_free_vbt:
kfree(vbt);
err_not_found:
return NULL;
}
static struct vbt_header *oprom_get_vbt(struct drm_i915_private *i915) static struct vbt_header *oprom_get_vbt(struct drm_i915_private *i915)
{ {
struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 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) ...@@ -2384,6 +2441,8 @@ static struct vbt_header *oprom_get_vbt(struct drm_i915_private *i915)
pci_unmap_rom(pdev, oprom); pci_unmap_rom(pdev, oprom);
drm_dbg_kms(&i915->drm, "Found valid VBT in PCI ROM\n");
return vbt; return vbt;
err_free_vbt: err_free_vbt:
...@@ -2418,17 +2477,23 @@ void intel_bios_init(struct drm_i915_private *i915) ...@@ -2418,17 +2477,23 @@ void intel_bios_init(struct drm_i915_private *i915)
init_vbt_defaults(i915); init_vbt_defaults(i915);
/* If the OpRegion does not have VBT, look in PCI ROM. */ /*
* If the OpRegion does not have VBT, look in SPI flash through MMIO or
* PCI mapping
*/
if (!vbt && IS_DGFX(i915)) {
oprom_vbt = spi_oprom_get_vbt(i915);
vbt = oprom_vbt;
}
if (!vbt) { if (!vbt) {
oprom_vbt = oprom_get_vbt(i915); oprom_vbt = oprom_get_vbt(i915);
if (!oprom_vbt)
goto out;
vbt = oprom_vbt; vbt = oprom_vbt;
drm_dbg_kms(&i915->drm, "Found valid VBT in PCI ROM\n");
} }
if (!vbt)
goto out;
bdb = get_bdb_header(vbt); bdb = get_bdb_header(vbt);
i915->vbt.version = bdb->version; i915->vbt.version = bdb->version;
......
...@@ -12853,6 +12853,14 @@ enum skl_power_gate { ...@@ -12853,6 +12853,14 @@ enum skl_power_gate {
#define TCSS_DDI_STATUS_HPD_LIVE_STATUS_TBT REG_BIT(1) #define TCSS_DDI_STATUS_HPD_LIVE_STATUS_TBT REG_BIT(1)
#define TCSS_DDI_STATUS_HPD_LIVE_STATUS_ALT REG_BIT(0) #define TCSS_DDI_STATUS_HPD_LIVE_STATUS_ALT REG_BIT(0)
#define PRIMARY_SPI_TRIGGER _MMIO(0x102040)
#define PRIMARY_SPI_ADDRESS _MMIO(0x102080)
#define PRIMARY_SPI_REGIONID _MMIO(0x102084)
#define SPI_STATIC_REGIONS _MMIO(0x102090)
#define OPTIONROM_SPI_REGIONID_MASK REG_GENMASK(7, 0)
#define OROM_OFFSET _MMIO(0x1020c0)
#define OROM_OFFSET_MASK REG_GENMASK(20, 16)
/* This register controls the Display State Buffer (DSB) engines. */ /* This register controls the Display State Buffer (DSB) engines. */
#define _DSBSL_INSTANCE_BASE 0x70B00 #define _DSBSL_INSTANCE_BASE 0x70B00
#define DSBSL_INSTANCE(pipe, id) (_DSBSL_INSTANCE_BASE + \ #define DSBSL_INSTANCE(pipe, id) (_DSBSL_INSTANCE_BASE + \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment