From patchwork Wed Mar 10 22:45:18 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 84726 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o2AMkHC6006498 for ; Wed, 10 Mar 2010 22:46:54 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A19F69F669; Wed, 10 Mar 2010 14:46:38 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTP id 52A4D9F64D for ; Wed, 10 Mar 2010 14:46:23 -0800 (PST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 10 Mar 2010 14:44:11 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.49,616,1262592000"; d="scan'208";a="499618607" Received: from unknown (HELO localhost.localdomain) ([10.255.13.214]) by orsmga002.jf.intel.com with ESMTP; 10 Mar 2010 14:45:27 -0800 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Wed, 10 Mar 2010 22:45:18 +0000 Message-Id: <1268261124-13653-32-git-send-email-chris@chris-wilson.co.uk> X-Mailer: git-send-email 1.7.0 In-Reply-To: <1268261124-13653-1-git-send-email-chris@chris-wilson.co.uk> References: <1268261124-13653-1-git-send-email-chris@chris-wilson.co.uk> Subject: [Intel-gfx] [PATCH 31/37] drm/i915: __iomem fixes for reading the VBIOS X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 10 Mar 2010 22:46:55 +0000 (UTC) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 70c9d4b..7dbb49a 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -33,25 +33,23 @@ #define SLAVE_ADDR1 0x70 #define SLAVE_ADDR2 0x72 -static int panel_type; - -static void * -find_section(struct bdb_header *bdb, int section_id) +static void __iomem * +find_section(struct bdb_header __iomem *bdb, int section_id) { - u8 *base = (u8 *)bdb; - int index = 0; + u8 __iomem *base = (u8 __iomem *)bdb; + int index; u16 total, current_size; u8 current_id; /* skip to first section */ - index += bdb->header_size; - total = bdb->bdb_size; + index = ioread16(&bdb->header_size); + total = ioread16(&bdb->bdb_size); /* walk the sections looking for section_id */ while (index < total) { - current_id = *(base + index); + current_id = ioread8(base + index); index++; - current_size = *((u16 *)(base + index)); + current_size = ioread16(base + index); index += 2; if (current_id == section_id) return base + index; @@ -62,37 +60,36 @@ find_section(struct bdb_header *bdb, int section_id) } static u16 -get_blocksize(void *p) +get_blocksize(void __iomem *p) { - u16 *block_ptr, block_size; - - block_ptr = (u16 *)((char *)p - 2); - block_size = *block_ptr; - return block_size; + return ioread16(p - 2); } static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, - struct lvds_dvo_timing *dvo_timing) + struct lvds_dvo_timing __iomem *dvo_timing) { - panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | - dvo_timing->hactive_lo; + struct lvds_dvo_timing timing; + + memcpy_fromio(&timing, dvo_timing, sizeof(timing)); + panel_fixed_mode->hdisplay = (timing.hactive_hi << 8) | + timing.hactive_lo; panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + - ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); + ((timing.hsync_off_hi << 8) | timing.hsync_off_lo); panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + - dvo_timing->hsync_pulse_width; + timing.hsync_pulse_width; panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + - ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); + ((timing.hblank_hi << 8) | timing.hblank_lo); - panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | - dvo_timing->vactive_lo; + panel_fixed_mode->vdisplay = (timing.vactive_hi << 8) | + timing.vactive_lo; panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + - dvo_timing->vsync_off; + timing.vsync_off; panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + - dvo_timing->vsync_pulse_width; + timing.vsync_pulse_width; panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + - ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); - panel_fixed_mode->clock = dvo_timing->clock * 10; + ((timing.vblank_hi << 8) | timing.vblank_lo); + panel_fixed_mode->clock = timing.clock * 10; panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; /* Some VBTs have bogus h/vtotal values */ @@ -107,30 +104,34 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, /* Try to find integrated panel data */ static void parse_lfp_panel_data(struct drm_i915_private *dev_priv, - struct bdb_header *bdb) + struct bdb_header __iomem *bdb, + int *panel_type) { - struct bdb_lvds_options *lvds_options; - struct bdb_lvds_lfp_data *lvds_lfp_data; - struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; - struct bdb_lvds_lfp_data_entry *entry; - struct lvds_dvo_timing *dvo_timing; + struct bdb_lvds_options __iomem *lvds_options_io; + struct bdb_lvds_lfp_data __iomem *lvds_lfp_data; + struct bdb_lvds_lfp_data_ptrs __iomem *lvds_lfp_data_ptrs; + struct bdb_lvds_lfp_data_entry __iomem *entry; + struct lvds_dvo_timing __iomem *dvo_timing; struct drm_display_mode *panel_fixed_mode; int lfp_data_size, dvo_timing_offset; int i, temp_downclock; struct drm_display_mode *temp_mode; + struct bdb_lvds_options lvds_options; /* Defaults if we can't find VBT info */ dev_priv->lvds_dither = 0; dev_priv->lvds_vbt = 0; - lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); - if (!lvds_options) + lvds_options_io = find_section(bdb, BDB_LVDS_OPTIONS); + if (!lvds_options_io) return; - dev_priv->lvds_dither = lvds_options->pixel_dither; - if (lvds_options->panel_type == 0xff) + memcpy_fromio(&lvds_options, lvds_options_io, sizeof(lvds_options)); + + dev_priv->lvds_dither = lvds_options.pixel_dither; + if (lvds_options.panel_type == 0xff) return; - panel_type = lvds_options->panel_type; + *panel_type = lvds_options.panel_type; lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); if (!lvds_lfp_data) @@ -142,23 +143,24 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, dev_priv->lvds_vbt = 1; - lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset - - lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset; - entry = (struct bdb_lvds_lfp_data_entry *) - ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * - lvds_options->panel_type)); - dvo_timing_offset = lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset - - lvds_lfp_data_ptrs->ptr[0].fp_timing_offset; + lfp_data_size = ioread16(&lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset) - + ioread16(&lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset); + entry = (struct bdb_lvds_lfp_data_entry __iomem *) + ((u8 __iomem *)lvds_lfp_data->data + (lfp_data_size * lvds_options.panel_type)); + dvo_timing_offset = ioread16(&lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset) - + ioread16(&lvds_lfp_data_ptrs->ptr[0].fp_timing_offset); /* * the size of fp_timing varies on the different platform. * So calculate the DVO timing relative offset in LVDS data * entry to get the DVO timing entry */ - dvo_timing = (struct lvds_dvo_timing *) - ((unsigned char *)entry + dvo_timing_offset); + dvo_timing = (struct lvds_dvo_timing __iomem *) + ((u8 __iomem *)entry + dvo_timing_offset); panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); + if (!panel_fixed_mode) + return; fill_detail_timing_data(panel_fixed_mode, dvo_timing); @@ -168,28 +170,31 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, drm_mode_debug_printmodeline(panel_fixed_mode); temp_mode = kzalloc(sizeof(*temp_mode), GFP_KERNEL); + if(!temp_mode) + return; + temp_downclock = panel_fixed_mode->clock; /* * enumerate the LVDS panel timing info entry in VBT to check whether * the LVDS downclock is found. */ for (i = 0; i < 16; i++) { - entry = (struct bdb_lvds_lfp_data_entry *) - ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * i)); - dvo_timing = (struct lvds_dvo_timing *) - ((unsigned char *)entry + dvo_timing_offset); + entry = (struct bdb_lvds_lfp_data_entry __iomem *) + ((u8 __iomem *)lvds_lfp_data->data + (lfp_data_size * i)); + dvo_timing = (struct lvds_dvo_timing __iomem *) + ((u8 __iomem *)entry + dvo_timing_offset); fill_detail_timing_data(temp_mode, dvo_timing); if (temp_mode->hdisplay == panel_fixed_mode->hdisplay && - temp_mode->hsync_start == panel_fixed_mode->hsync_start && - temp_mode->hsync_end == panel_fixed_mode->hsync_end && - temp_mode->htotal == panel_fixed_mode->htotal && - temp_mode->vdisplay == panel_fixed_mode->vdisplay && - temp_mode->vsync_start == panel_fixed_mode->vsync_start && - temp_mode->vsync_end == panel_fixed_mode->vsync_end && - temp_mode->vtotal == panel_fixed_mode->vtotal && - temp_mode->clock < temp_downclock) { + temp_mode->hsync_start == panel_fixed_mode->hsync_start && + temp_mode->hsync_end == panel_fixed_mode->hsync_end && + temp_mode->htotal == panel_fixed_mode->htotal && + temp_mode->vdisplay == panel_fixed_mode->vdisplay && + temp_mode->vsync_start == panel_fixed_mode->vsync_start && + temp_mode->vsync_end == panel_fixed_mode->vsync_end && + temp_mode->vtotal == panel_fixed_mode->vtotal && + temp_mode->clock < temp_downclock) { /* * downclock is already found. But we expect * to find the lower downclock. @@ -208,16 +213,15 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, "Normal Clock %dKHz, downclock %dKHz\n", temp_downclock, panel_fixed_mode->clock); } - return; } /* Try to find sdvo panel data */ static void parse_sdvo_panel_data(struct drm_i915_private *dev_priv, - struct bdb_header *bdb) + struct bdb_header __iomem *bdb) { - struct bdb_sdvo_lvds_options *sdvo_lvds_options; - struct lvds_dvo_timing *dvo_timing; + struct bdb_sdvo_lvds_options __iomem *sdvo_lvds_options; + struct lvds_dvo_timing __iomem *dvo_timing; struct drm_display_mode *panel_fixed_mode; dev_priv->sdvo_lvds_vbt_mode = NULL; @@ -231,12 +235,11 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, return; panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); - if (!panel_fixed_mode) return; fill_detail_timing_data(panel_fixed_mode, - dvo_timing + sdvo_lvds_options->panel_type); + dvo_timing + ioread8(&sdvo_lvds_options->panel_type)); dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; @@ -245,40 +248,43 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, static void parse_general_features(struct drm_i915_private *dev_priv, - struct bdb_header *bdb) + struct bdb_header __iomem *bdb) { - struct drm_device *dev = dev_priv->dev; - struct bdb_general_features *general; + struct bdb_general_features __iomem *general_io; + struct bdb_general_features general; /* Set sensible defaults in case we can't find the general block */ dev_priv->int_tv_support = 1; dev_priv->int_crt_support = 1; - general = find_section(bdb, BDB_GENERAL_FEATURES); - if (general) { - dev_priv->int_tv_support = general->int_tv_support; - dev_priv->int_crt_support = general->int_crt_support; - dev_priv->lvds_use_ssc = general->enable_ssc; - - if (dev_priv->lvds_use_ssc) { - if (IS_I85X(dev_priv->dev)) - dev_priv->lvds_ssc_freq = - general->ssc_freq ? 66 : 48; - else if (IS_IRONLAKE(dev_priv->dev) || IS_GEN6(dev)) - dev_priv->lvds_ssc_freq = - general->ssc_freq ? 100 : 120; - else - dev_priv->lvds_ssc_freq = - general->ssc_freq ? 100 : 96; - } + general_io = find_section(bdb, BDB_GENERAL_FEATURES); + if (!general_io) + return; + + memcpy_fromio(&general, general_io, sizeof(general)); + + dev_priv->int_tv_support = general.int_tv_support; + dev_priv->int_crt_support = general.int_crt_support; + dev_priv->lvds_use_ssc = general.enable_ssc; + + if (dev_priv->lvds_use_ssc) { + if (IS_I85X(dev_priv->dev)) + dev_priv->lvds_ssc_freq = + general.ssc_freq ? 66 : 48; + else if (IS_IRONLAKE(dev_priv->dev) || IS_GEN6(dev)) + dev_priv->lvds_ssc_freq = + general.ssc_freq ? 100 : 120; + else + dev_priv->lvds_ssc_freq = + general.ssc_freq ? 100 : 96; } } static void parse_general_definitions(struct drm_i915_private *dev_priv, - struct bdb_header *bdb) + struct bdb_header __iomem *bdb) { - struct bdb_general_definitions *general; + struct bdb_general_definitions __iomem *general; const int crt_bus_map_table[] = { GPIOB, GPIOA, @@ -292,7 +298,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv, if (general) { u16 block_size = get_blocksize(general); if (block_size >= sizeof(*general)) { - int bus_pin = general->crt_ddc_gmbus_pin; + int bus_pin = ioread8(&general->crt_ddc_gmbus_pin); DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); if ((bus_pin >= 1) && (bus_pin <= 6)) { dev_priv->crt_ddc_bus = @@ -305,77 +311,90 @@ parse_general_definitions(struct drm_i915_private *dev_priv, } } +static bool +has_child_device_config(struct bdb_general_definitions __iomem *defs) +{ + /* Judge whether the size of child device meets the requirements. + * If the child device size obtained from general definition block + * is different with sizeof(struct child_device_config), skip the + * parsing of sdvo device info. + */ + return ioread8(&defs->child_dev_size) == sizeof(struct child_device_config); +} + +static int +get_child_device_num(struct bdb_general_definitions __iomem *defs) +{ + if (!has_child_device_config(defs)) { + DRM_DEBUG_KMS("different child size is found. Invalid.\n"); + return 0; + } + + return (get_blocksize(defs) - sizeof(*defs)) / + sizeof(struct child_device_config); +} + static void parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, - struct bdb_header *bdb) + struct bdb_header __iomem *bdb) { struct sdvo_device_mapping *p_mapping; - struct bdb_general_definitions *p_defs; - struct child_device_config *p_child; + struct bdb_general_definitions __iomem *p_defs; int i, child_device_num, count; - u16 block_size; p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); if (!p_defs) { DRM_DEBUG_KMS("No general definition block is found\n"); return; } - /* judge whether the size of child device meets the requirements. - * If the child device size obtained from general definition block - * is different with sizeof(struct child_device_config), skip the - * parsing of sdvo device info - */ - if (p_defs->child_dev_size != sizeof(*p_child)) { - /* different child dev size . Ignore it */ - DRM_DEBUG_KMS("different child size is found. Invalid.\n"); + + child_device_num = get_child_device_num(p_defs); + if (child_device_num == 0) return; - } - /* get the block size of general definitions */ - block_size = get_blocksize(p_defs); - /* get the number of child device */ - child_device_num = (block_size - sizeof(*p_defs)) / - sizeof(*p_child); + count = 0; for (i = 0; i < child_device_num; i++) { - p_child = &(p_defs->devices[i]); - if (!p_child->device_type) { + struct child_device_config child; + + memcpy_fromio(&child, &p_defs->devices[i], sizeof(child)); + if (!child.device_type) { /* skip the device block if device type is invalid */ continue; } - if (p_child->slave_addr != SLAVE_ADDR1 && - p_child->slave_addr != SLAVE_ADDR2) { + if (child.slave_addr != SLAVE_ADDR1 && + child.slave_addr != SLAVE_ADDR2) { /* * If the slave address is neither 0x70 nor 0x72, * it is not a SDVO device. Skip it. */ continue; } - if (p_child->dvo_port != DEVICE_PORT_DVOB && - p_child->dvo_port != DEVICE_PORT_DVOC) { + if (child.dvo_port != DEVICE_PORT_DVOB && + child.dvo_port != DEVICE_PORT_DVOC) { /* skip the incorrect SDVO port */ DRM_DEBUG_KMS("Incorrect SDVO port. Skip it \n"); continue; } DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" " %s port\n", - p_child->slave_addr, - (p_child->dvo_port == DEVICE_PORT_DVOB) ? - "SDVOB" : "SDVOC"); - p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]); + child.slave_addr, + (child.dvo_port == DEVICE_PORT_DVOB) ? + "SDVOB" : "SDVOC"); + p_mapping = &(dev_priv->sdvo_mappings[child.dvo_port - 1]); if (!p_mapping->initialized) { - p_mapping->dvo_port = p_child->dvo_port; - p_mapping->slave_addr = p_child->slave_addr; - p_mapping->dvo_wiring = p_child->dvo_wiring; + p_mapping->dvo_port = child.dvo_port; + p_mapping->slave_addr = child.slave_addr; + p_mapping->dvo_wiring = child.dvo_wiring; p_mapping->initialized = 1; } else { DRM_DEBUG_KMS("Maybe one SDVO port is shared by " - "two SDVO device.\n"); + "two SDVO device.\n"); } - if (p_child->slave2_addr) { + if (child.slave2_addr) { /* Maybe this is a SDVO device with multiple inputs */ /* And the mapping info is not added */ DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this" - " is a SDVO device with multiple inputs.\n"); + " is a SDVO device with multiple inputs.\n"); } count++; } @@ -389,30 +408,32 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, static void parse_driver_features(struct drm_i915_private *dev_priv, - struct bdb_header *bdb) + struct bdb_header __iomem *bdb) { struct drm_device *dev = dev_priv->dev; - struct bdb_driver_features *driver; + struct bdb_driver_features __iomem *driver_io; + struct bdb_driver_features driver; - driver = find_section(bdb, BDB_DRIVER_FEATURES); - if (!driver) + driver_io = find_section(bdb, BDB_DRIVER_FEATURES); + if (!driver_io) return; - if (driver && SUPPORTS_EDP(dev) && - driver->lvds_config == BDB_DRIVER_FEATURE_EDP) { - dev_priv->edp_support = 1; - } else { - dev_priv->edp_support = 0; - } + memcpy_fromio(&driver, driver_io, sizeof(driver)); - if (driver && driver->dual_frequency) + dev_priv->edp_support = + SUPPORTS_EDP(dev) && + driver.lvds_config == BDB_DRIVER_FEATURE_EDP; + + if (driver.dual_frequency) dev_priv->render_reclock_avail = true; } static void -parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) +parse_edp(struct drm_i915_private *dev_priv, + struct bdb_header __iomem *bdb, + int panel_type) { - struct bdb_edp *edp; + struct bdb_edp __iomem *edp; edp = find_section(bdb, BDB_EDP); if (!edp) { @@ -424,7 +445,7 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) return; } - switch ((edp->color_depth >> (panel_type * 2)) & 3) { + switch ((ioread32(&edp->color_depth) >> (panel_type * 2)) & 3) { case EDP_18BPP: dev_priv->edp_bpp = 18; break; @@ -439,48 +460,36 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) static void parse_device_mapping(struct drm_i915_private *dev_priv, - struct bdb_header *bdb) + struct bdb_header __iomem *bdb) { - struct bdb_general_definitions *p_defs; - struct child_device_config *p_child, *child_dev_ptr; + struct bdb_general_definitions __iomem *p_defs; int i, child_device_num, count; - u16 block_size; p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); if (!p_defs) { DRM_DEBUG_KMS("No general definition block is found\n"); return; } - /* judge whether the size of child device meets the requirements. - * If the child device size obtained from general definition block - * is different with sizeof(struct child_device_config), skip the - * parsing of sdvo device info - */ - if (p_defs->child_dev_size != sizeof(*p_child)) { - /* different child dev size . Ignore it */ - DRM_DEBUG_KMS("different child size is found. Invalid.\n"); + + child_device_num = get_child_device_num(p_defs); + if (child_device_num == 0) return; - } - /* get the block size of general definitions */ - block_size = get_blocksize(p_defs); - /* get the number of child device */ - child_device_num = (block_size - sizeof(*p_defs)) / - sizeof(*p_child); - count = 0; + /* get the number of child device that is present */ + count = 0; for (i = 0; i < child_device_num; i++) { - p_child = &(p_defs->devices[i]); - if (!p_child->device_type) { - /* skip the device block if device type is invalid */ + /* skip the device block if device type is invalid */ + if (ioread16(&p_defs->devices[i].device_type) == 0) continue; - } + count++; } if (!count) { DRM_DEBUG_KMS("no child dev is parsed from VBT \n"); return; } - dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL); + + dev_priv->child_dev = kzalloc(sizeof(struct child_device_config) * count, GFP_KERNEL); if (!dev_priv->child_dev) { DRM_DEBUG_KMS("No memory space for child device\n"); return; @@ -489,18 +498,27 @@ parse_device_mapping(struct drm_i915_private *dev_priv, dev_priv->child_dev_num = count; count = 0; for (i = 0; i < child_device_num; i++) { - p_child = &(p_defs->devices[i]); - if (!p_child->device_type) { - /* skip the device block if device type is invalid */ + /* skip the device block if device type is invalid */ + if (ioread16(&p_defs->devices[i].device_type) == 0) continue; - } - child_dev_ptr = dev_priv->child_dev + count; + + memcpy_fromio(dev_priv->child_dev + count, + p_defs->devices + i, + sizeof(struct child_device_config)); count++; - memcpy((void *)child_dev_ptr, (void *)p_child, - sizeof(*p_child)); } - return; } + +static bool +is_vbt_sig(u8 __iomem *mem) +{ + return + ioread8(mem + 0) == '$' && + ioread8(mem + 1) == 'V' && + ioread8(mem + 2) == 'B' && + ioread8(mem + 3) == 'T'; +} + /** * intel_init_bios - initialize VBIOS settings & find VBT * @dev: DRM device @@ -520,10 +538,11 @@ intel_init_bios(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct pci_dev *pdev = dev->pdev; - struct vbt_header *vbt = NULL; - struct bdb_header *bdb; + struct vbt_header __iomem *vbt; + struct bdb_header __iomem *bdb; u8 __iomem *bios; size_t size; + int panel_type = 0; int i; bios = pci_map_rom(pdev, &size); @@ -531,30 +550,30 @@ intel_init_bios(struct drm_device *dev) return -1; /* Scour memory looking for the VBT signature */ + vbt = NULL; for (i = 0; i + 4 < size; i++) { - if (!memcmp(bios + i, "$VBT", 4)) { - vbt = (struct vbt_header *)(bios + i); + if (is_vbt_sig(bios + i)) { + vbt = (struct vbt_header __iomem *)(bios + i); break; } } - if (!vbt) { DRM_ERROR("VBT signature missing\n"); pci_unmap_rom(pdev, bios); return -1; } - bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); + bdb = (struct bdb_header __iomem *)(bios + i + ioread32(&vbt->bdb_offset)); /* Grab useful general definitions */ parse_general_features(dev_priv, bdb); parse_general_definitions(dev_priv, bdb); - parse_lfp_panel_data(dev_priv, bdb); + parse_lfp_panel_data(dev_priv, bdb, &panel_type); parse_sdvo_panel_data(dev_priv, bdb); parse_sdvo_device_mapping(dev_priv, bdb); parse_device_mapping(dev_priv, bdb); parse_driver_features(dev_priv, bdb); - parse_edp(dev_priv, bdb); + parse_edp(dev_priv, bdb, panel_type); pci_unmap_rom(pdev, bios);