On Mon, 22 May 2023, Matt Roper <[email protected]> wrote:
> 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().
>
> v2:
>  - Fix use of uninitialized i915 pointer in error path if
>    pci_enable_device() fails before the i915 device is created.  (lkp)
>  - Use drm_device parameter to intel_display_device_probe.  This goes
>    against i915 conventions, but since the primary goal here is to make
>    it easy to call this function from other drivers (like Xe) and since
>    we don't need anything from the i915 structure, this seems like an
>    exception where drm_device is a more natural fit.
>
> Signed-off-by: Matt Roper <[email protected]>
> ---
>  .../drm/i915/display/intel_display_device.c   | 64 +++++++++++++++++--
>  .../drm/i915/display/intel_display_device.h   |  5 +-
>  drivers/gpu/drm/i915/i915_driver.c            | 17 +++--
>  drivers/gpu/drm/i915/intel_device_info.c      | 12 ++--
>  4 files changed, 81 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c 
> b/drivers/gpu/drm/i915/display/intel_display_device.c
> index 3c5941c8788d..6605487c3890 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"
> @@ -692,18 +695,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_device *drm, u16 *ver, u16 *rel, u16 *step)

Please always prefer struct drm_i915_private * over struct drm_device *.

> +{
> +     struct pci_dev *pdev = to_pci_dev(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(drm, "Cannot map MMIO BAR to read display GMD_ID\n");
> +             return &no_display;
> +     }
> +
> +     val = ioread32(addr);
> +     pci_iounmap(pdev, addr);
> +
> +     if (val == 0)
> +             /* Platform doesn't have display */
> +             return &no_display;
> +
> +     *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(drm, "Unrecognized display IP version %d.%02d; disabling 
> display.\n",
> +             *ver, *rel);
> +     return &no_display;
> +}
> +
>  const struct intel_display_device_info *
> -intel_display_device_probe(u16 pci_devid)
> +intel_display_device_probe(struct drm_device *drm, bool has_gmdid,
> +                        u16 *gmdid_ver, u16 *gmdid_rel, u16 *gmdid_step)

Ditto.

>  {
> +     struct pci_dev *pdev = to_pci_dev(drm->dev);
>       int i;
>  
> +     if (has_gmdid)
> +             return probe_gmdid_display(drm, 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 &no_display;
> diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h 
> b/drivers/gpu/drm/i915/display/intel_display_device.h
> index 1f7d08b3ad6b..2a14943313ad 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_device;
> +

Please keep forward declarations near the top of the file, right after
includes.

>  const struct intel_display_device_info *
> -intel_display_device_probe(u16 pci_devid);
> +intel_display_device_probe(struct drm_device *drm, 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..37532e55327d 100644
> --- a/drivers/gpu/drm/i915/i915_driver.c
> +++ b/drivers/gpu/drm/i915/i915_driver.c
> @@ -754,13 +754,17 @@ 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;
> +     if (ret) {
> +             pr_err("Failed to enable graphics device: %pe\n", ERR_PTR(ret));
> +             return ret;
> +     }
> +
> +     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)
> @@ -843,7 +847,6 @@ int i915_driver_probe(struct pci_dev *pdev, const struct 
> pci_device_id *ent)
>       i915_driver_late_release(i915);
>  out_pci_disable:
>       pci_disable_device(pdev);
> -out_fini:
>       i915_probe_error(i915, "Device initialization failed (%d)\n", ret);
>       return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_device_info.c 
> b/drivers/gpu/drm/i915/intel_device_info.c
> index e1507ae59f2d..85105639d55d 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);
>  }
> @@ -574,6 +571,7 @@ void intel_device_info_driver_create(struct 
> drm_i915_private *i915,
>  {
>       struct intel_device_info *info;
>       struct intel_runtime_info *runtime;
> +     u16 ver, rel, step;
>  
>       /* Setup the write-once "constant" device info */
>       info = mkwrite_device_info(i915);
> @@ -584,8 +582,14 @@ 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->drm, info->has_gmd_id,
> +                                                &ver, &rel, &step);
>       *DISPLAY_RUNTIME_INFO(i915) = DISPLAY_INFO(i915)->__runtime_defaults;
> +     if (info->has_gmd_id) {
> +             DISPLAY_RUNTIME_INFO(i915)->ip.ver = ver;
> +             DISPLAY_RUNTIME_INFO(i915)->ip.rel = rel;
> +             DISPLAY_RUNTIME_INFO(i915)->ip.step = step;
> +     }

The division of initialization responsibilities between here and
intel_display_device_probe() is perhaps a bit odd?

Nothing that can't be fixed later though, I guess.

BR,
Jani.

>  
>       runtime->device_id = device_id;
>  }

-- 
Jani Nikula, Intel Open Source Graphics Center

Reply via email to