drm/i915/bios: reduce indent in parse_general_features
[linux-2.6-block.git] / drivers / gpu / drm / i915 / intel_bios.c
index ce82f9c7df2460b049b279957a8db78965b4f49c..eba3e0f87181edbf3b4749f24709a35f2c83a8a9 100644 (file)
@@ -24,7 +24,7 @@
  *    Eric Anholt <eric@anholt.net>
  *
  */
-#include <linux/dmi.h>
+
 #include <drm/drm_dp_helper.h>
 #include <drm/drmP.h>
 #include <drm/i915_drm.h>
@@ -332,10 +332,10 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
        drm_mode_debug_printmodeline(panel_fixed_mode);
 }
 
-static int intel_bios_ssc_frequency(struct drm_device *dev,
+static int intel_bios_ssc_frequency(struct drm_i915_private *dev_priv,
                                    bool alternate)
 {
-       switch (INTEL_INFO(dev)->gen) {
+       switch (INTEL_INFO(dev_priv)->gen) {
        case 2:
                return alternate ? 66667 : 48000;
        case 3:
@@ -350,26 +350,29 @@ static void
 parse_general_features(struct drm_i915_private *dev_priv,
                       const struct bdb_header *bdb)
 {
-       struct drm_device *dev = dev_priv->dev;
        const struct bdb_general_features *general;
 
        general = find_section(bdb, BDB_GENERAL_FEATURES);
-       if (general) {
-               dev_priv->vbt.int_tv_support = general->int_tv_support;
+       if (!general)
+               return;
+
+       dev_priv->vbt.int_tv_support = general->int_tv_support;
+       /* int_crt_support can't be trusted on earlier platforms */
+       if (bdb->version >= 155 &&
+           (HAS_DDI(dev_priv) || IS_VALLEYVIEW(dev_priv)))
                dev_priv->vbt.int_crt_support = general->int_crt_support;
-               dev_priv->vbt.lvds_use_ssc = general->enable_ssc;
-               dev_priv->vbt.lvds_ssc_freq =
-                       intel_bios_ssc_frequency(dev, general->ssc_freq);
-               dev_priv->vbt.display_clock_mode = general->display_clock_mode;
-               dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
-               DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
-                             dev_priv->vbt.int_tv_support,
-                             dev_priv->vbt.int_crt_support,
-                             dev_priv->vbt.lvds_use_ssc,
-                             dev_priv->vbt.lvds_ssc_freq,
-                             dev_priv->vbt.display_clock_mode,
-                             dev_priv->vbt.fdi_rx_polarity_inverted);
-       }
+       dev_priv->vbt.lvds_use_ssc = general->enable_ssc;
+       dev_priv->vbt.lvds_ssc_freq =
+               intel_bios_ssc_frequency(dev_priv, general->ssc_freq);
+       dev_priv->vbt.display_clock_mode = general->display_clock_mode;
+       dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
+       DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
+                     dev_priv->vbt.int_tv_support,
+                     dev_priv->vbt.int_crt_support,
+                     dev_priv->vbt.lvds_use_ssc,
+                     dev_priv->vbt.lvds_ssc_freq,
+                     dev_priv->vbt.display_clock_mode,
+                     dev_priv->vbt.fdi_rx_polarity_inverted);
 }
 
 static void
@@ -1054,10 +1057,9 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
 static void parse_ddi_ports(struct drm_i915_private *dev_priv,
                            const struct bdb_header *bdb)
 {
-       struct drm_device *dev = dev_priv->dev;
        enum port port;
 
-       if (!HAS_DDI(dev))
+       if (!HAS_DDI(dev_priv))
                return;
 
        if (!dev_priv->vbt.child_dev_num)
@@ -1170,7 +1172,6 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
 static void
 init_vbt_defaults(struct drm_i915_private *dev_priv)
 {
-       struct drm_device *dev = dev_priv->dev;
        enum port port;
 
        dev_priv->vbt.crt_ddc_pin = GMBUS_PIN_VGADDC;
@@ -1195,8 +1196,8 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
         * Core/SandyBridge/IvyBridge use alternative (120MHz) reference
         * clock for LVDS.
         */
-       dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev,
-                       !HAS_PCH_SPLIT(dev));
+       dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev_priv,
+                       !HAS_PCH_SPLIT(dev_priv));
        DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq);
 
        for (port = PORT_A; port < I915_MAX_PORTS; port++) {
@@ -1211,88 +1212,79 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
        }
 }
 
-static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
+static const struct bdb_header *get_bdb_header(const struct vbt_header *vbt)
 {
-       DRM_DEBUG_KMS("Falling back to manually reading VBT from "
-                     "VBIOS ROM for %s\n",
-                     id->ident);
-       return 1;
+       const void *_vbt = vbt;
+
+       return _vbt + vbt->bdb_offset;
 }
 
-static const struct dmi_system_id intel_no_opregion_vbt[] = {
-       {
-               .callback = intel_no_opregion_vbt_callback,
-               .ident = "ThinkCentre A57",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
-               },
-       },
-       { }
-};
-
-static const struct bdb_header *validate_vbt(const void *base,
-                                            size_t size,
-                                            const void *_vbt,
-                                            const char *source)
+/**
+ * intel_bios_is_valid_vbt - does the given buffer contain a valid VBT
+ * @buf:       pointer to a buffer to validate
+ * @size:      size of the buffer
+ *
+ * Returns true on valid VBT.
+ */
+bool intel_bios_is_valid_vbt(const void *buf, size_t size)
 {
-       size_t offset = _vbt - base;
-       const struct vbt_header *vbt = _vbt;
+       const struct vbt_header *vbt = buf;
        const struct bdb_header *bdb;
 
-       if (offset + sizeof(struct vbt_header) > size) {
+       if (!vbt)
+               return false;
+
+       if (sizeof(struct vbt_header) > size) {
                DRM_DEBUG_DRIVER("VBT header incomplete\n");
-               return NULL;
+               return false;
        }
 
        if (memcmp(vbt->signature, "$VBT", 4)) {
                DRM_DEBUG_DRIVER("VBT invalid signature\n");
-               return NULL;
+               return false;
        }
 
-       offset += vbt->bdb_offset;
-       if (offset + sizeof(struct bdb_header) > size) {
+       if (vbt->bdb_offset + sizeof(struct bdb_header) > size) {
                DRM_DEBUG_DRIVER("BDB header incomplete\n");
-               return NULL;
+               return false;
        }
 
-       bdb = base + offset;
-       if (offset + bdb->bdb_size > size) {
+       bdb = get_bdb_header(vbt);
+       if (vbt->bdb_offset + bdb->bdb_size > size) {
                DRM_DEBUG_DRIVER("BDB incomplete\n");
-               return NULL;
+               return false;
        }
 
-       DRM_DEBUG_KMS("Using VBT from %s: %20s\n",
-                     source, vbt->signature);
-       return bdb;
+       return vbt;
 }
 
-static const struct bdb_header *find_vbt(void __iomem *bios, size_t size)
+static const struct vbt_header *find_vbt(void __iomem *bios, size_t size)
 {
-       const struct bdb_header *bdb = NULL;
        size_t i;
 
        /* Scour memory looking for the VBT signature. */
        for (i = 0; i + 4 < size; i++) {
-               if (ioread32(bios + i) == *((const u32 *) "$VBT")) {
-                       /*
-                        * This is the one place where we explicitly discard the
-                        * address space (__iomem) of the BIOS/VBT. From now on
-                        * everything is based on 'base', and treated as regular
-                        * memory.
-                        */
-                       void *_bios = (void __force *) bios;
+               void *vbt;
 
-                       bdb = validate_vbt(_bios, size, _bios + i, "PCI ROM");
-                       break;
-               }
+               if (ioread32(bios + i) != *((const u32 *) "$VBT"))
+                       continue;
+
+               /*
+                * This is the one place where we explicitly discard the address
+                * space (__iomem) of the BIOS/VBT.
+                */
+               vbt = (void __force *) bios + i;
+               if (intel_bios_is_valid_vbt(vbt, size - i))
+                       return vbt;
+
+               break;
        }
 
-       return bdb;
+       return NULL;
 }
 
 /**
- * intel_parse_bios - find VBT and initialize settings from the BIOS
+ * intel_bios_init - find VBT and initialize settings from the BIOS
  * @dev: DRM device
  *
  * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
@@ -1301,37 +1293,39 @@ static const struct bdb_header *find_vbt(void __iomem *bios, size_t size)
  * Returns 0 on success, nonzero on failure.
  */
 int
-intel_parse_bios(struct drm_device *dev)
+intel_bios_init(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct pci_dev *pdev = dev->pdev;
-       const struct bdb_header *bdb = NULL;
+       struct pci_dev *pdev = dev_priv->dev->pdev;
+       const struct vbt_header *vbt = dev_priv->opregion.vbt;
+       const struct bdb_header *bdb;
        u8 __iomem *bios = NULL;
 
-       if (HAS_PCH_NOP(dev))
+       if (HAS_PCH_NOP(dev_priv))
                return -ENODEV;
 
        init_vbt_defaults(dev_priv);
 
-       /* XXX Should this validation be moved to intel_opregion.c? */
-       if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt)
-               bdb = validate_vbt(dev_priv->opregion.header, OPREGION_SIZE,
-                                  dev_priv->opregion.vbt, "OpRegion");
-
-       if (bdb == NULL) {
+       if (!vbt) {
                size_t size;
 
                bios = pci_map_rom(pdev, &size);
                if (!bios)
                        return -1;
 
-               bdb = find_vbt(bios, size);
-               if (!bdb) {
+               vbt = find_vbt(bios, size);
+               if (!vbt) {
                        pci_unmap_rom(pdev, bios);
                        return -1;
                }
+
+               DRM_DEBUG_KMS("Found valid VBT in PCI ROM\n");
        }
 
+       bdb = get_bdb_header(vbt);
+
+       DRM_DEBUG_KMS("VBT signature \"%.*s\", BDB version %d\n",
+                     (int)sizeof(vbt->signature), vbt->signature, bdb->version);
+
        /* Grab useful general definitions */
        parse_general_features(dev_priv, bdb);
        parse_general_definitions(dev_priv, bdb);