For platforms with GMD_ID support (i.e., everything MTL and beyond), identification of the display IP present should be based on the contents of the GMD_ID register rather than a PCI devid match. Note that since GMD_ID readout requires access to the PCI BAR, a slight change to the driver init sequence is needed --- pci_enable_device() is now called before i915_driver_create(). Signed-off-by: Matt Roper <matthew.d.roper@xxxxxxxxx> --- .../drm/i915/display/intel_display_device.c | 64 +++++++++++++++++-- .../drm/i915/display/intel_display_device.h | 5 +- drivers/gpu/drm/i915/i915_driver.c | 10 +-- drivers/gpu/drm/i915/intel_device_info.c | 13 ++-- 4 files changed, 78 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c index 78fa522aaf0b..813a2a494082 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.c +++ b/drivers/gpu/drm/i915/display/intel_display_device.c @@ -6,7 +6,10 @@ #include <drm/i915_pciids.h> #include <drm/drm_color_mgmt.h> #include <linux/mod_devicetable.h> +#include <linux/pci.h> +#include "i915_drv.h" +#include "i915_reg.h" #include "intel_display_device.h" #include "intel_display_power.h" #include "intel_display_reg_defs.h" @@ -674,18 +677,69 @@ static const struct pci_device_id intel_display_ids[] = { INTEL_RPLP_IDS(&xe_lpd_display), INTEL_DG2_IDS(&xe_hpd_display), - /* FIXME: Replace this with a GMD_ID lookup */ - INTEL_MTL_IDS(&xe_lpdp_display), + /* + * Do not add any GMD_ID-based platforms to this list. They will + * be probed automatically based on the IP version reported by + * the hardware. + */ }; +struct { + u16 ver; + u16 rel; + const struct intel_display_device_info *display; +} gmdid_display_map[] = { + { 14, 0, &xe_lpdp_display }, +}; + +static const struct intel_display_device_info * +probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step) +{ + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); + void __iomem *addr; + u32 val; + int i; + + addr = pci_iomap_range(pdev, 0, i915_mmio_reg_offset(GMD_ID_DISPLAY), sizeof(u32)); + if (!addr) { + drm_err(&i915->drm, "Cannot map MMIO BAR to read display GMD_ID\n"); + return NULL; + } + + val = ioread32(addr); + pci_iounmap(pdev, addr); + + if (val == 0) + /* Platform doesn't have display */ + return NULL; + + *ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val); + *rel = REG_FIELD_GET(GMD_ID_RELEASE_MASK, val); + *step = REG_FIELD_GET(GMD_ID_STEP, val); + + for (i = 0; i < ARRAY_SIZE(gmdid_display_map); i++) + if (*ver == gmdid_display_map[i].ver && + *rel == gmdid_display_map[i].rel) + return gmdid_display_map[i].display; + + drm_err(&i915->drm, "Unrecognized display IP version %d.%02d; disabling display.\n", + *ver, *rel); + return NULL; +} + const struct intel_display_device_info * -intel_display_device_probe(u16 pci_devid) +intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid, + u16 *gmdid_ver, u16 *gmdid_rel, u16 *gmdid_step) { + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); int i; + if (has_gmdid) + return probe_gmdid_display(i915, gmdid_ver, gmdid_rel, gmdid_step); + for (i = 0; i < ARRAY_SIZE(intel_display_ids); i++) { - if (intel_display_ids[i].device == pci_devid) - return (struct intel_display_device_info *)intel_display_ids[i].driver_data; + if (intel_display_ids[i].device == pdev->device) + return (const struct intel_display_device_info *)intel_display_ids[i].driver_data; } return NULL; diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index 0a60ebfaff80..9a344ee36d8c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -80,7 +80,10 @@ struct intel_display_device_info { } color; }; +struct drm_i915_private; + const struct intel_display_device_info * -intel_display_device_probe(u16 pci_devid); +intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid, + u16 *ver, u16 *rel, u16 *step); #endif diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 522733a89946..d02c602e9a0b 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -754,14 +754,16 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct drm_i915_private *i915; int ret; - i915 = i915_driver_create(pdev, ent); - if (IS_ERR(i915)) - return PTR_ERR(i915); - ret = pci_enable_device(pdev); if (ret) goto out_fini; + i915 = i915_driver_create(pdev, ent); + if (IS_ERR(i915)) { + ret = PTR_ERR(i915); + goto out_pci_disable; + } + ret = i915_driver_early_probe(i915); if (ret < 0) goto out_pci_disable; diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 9d0b54ba50c1..5f38ff8caac0 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -345,7 +345,6 @@ static void ip_ver_read(struct drm_i915_private *i915, u32 offset, struct intel_ static void intel_ipver_early_init(struct drm_i915_private *i915) { struct intel_runtime_info *runtime = RUNTIME_INFO(i915); - struct intel_display_runtime_info *display_runtime = DISPLAY_RUNTIME_INFO(i915); if (!HAS_GMD_ID(i915)) { drm_WARN_ON(&i915->drm, RUNTIME_INFO(i915)->graphics.ip.ver > 12); @@ -366,8 +365,6 @@ static void intel_ipver_early_init(struct drm_i915_private *i915) RUNTIME_INFO(i915)->graphics.ip.ver = 12; RUNTIME_INFO(i915)->graphics.ip.rel = 70; } - ip_ver_read(i915, i915_mmio_reg_offset(GMD_ID_DISPLAY), - (struct intel_ip_version *)&display_runtime->ip); ip_ver_read(i915, i915_mmio_reg_offset(GMD_ID_MEDIA), &runtime->media.ip); } @@ -575,6 +572,7 @@ void intel_device_info_driver_create(struct drm_i915_private *i915, struct intel_device_info *info; struct intel_runtime_info *runtime; struct intel_display_runtime_info *display_runtime; + u16 ver, rel, step; /* Setup the write-once "constant" device info */ info = mkwrite_device_info(i915); @@ -585,11 +583,18 @@ void intel_device_info_driver_create(struct drm_i915_private *i915, memcpy(runtime, &INTEL_INFO(i915)->__runtime, sizeof(*runtime)); /* Probe display support */ - info->display = intel_display_device_probe(device_id); + info->display = intel_display_device_probe(i915, info->has_gmd_id, + &ver, &rel, &step); if (info->display) { display_runtime = DISPLAY_RUNTIME_INFO(i915); memcpy(display_runtime, &DISPLAY_INFO(i915)->__runtime, sizeof(*display_runtime)); + + if (info->has_gmd_id) { + display_runtime->ip.ver = ver; + display_runtime->ip.rel = rel; + display_runtime->ip.step = step; + } } else { info->display = &no_display; } -- 2.40.0