Path: blob/master/drivers/gpu/drm/i915/intel_bios.c
15112 views
/*1* Copyright � 2006 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*22* Authors:23* Eric Anholt <[email protected]>24*25*/26#include <drm/drm_dp_helper.h>27#include "drmP.h"28#include "drm.h"29#include "i915_drm.h"30#include "i915_drv.h"31#include "intel_bios.h"3233#define SLAVE_ADDR1 0x7034#define SLAVE_ADDR2 0x723536static int panel_type;3738static void *39find_section(struct bdb_header *bdb, int section_id)40{41u8 *base = (u8 *)bdb;42int index = 0;43u16 total, current_size;44u8 current_id;4546/* skip to first section */47index += bdb->header_size;48total = bdb->bdb_size;4950/* walk the sections looking for section_id */51while (index < total) {52current_id = *(base + index);53index++;54current_size = *((u16 *)(base + index));55index += 2;56if (current_id == section_id)57return base + index;58index += current_size;59}6061return NULL;62}6364static u1665get_blocksize(void *p)66{67u16 *block_ptr, block_size;6869block_ptr = (u16 *)((char *)p - 2);70block_size = *block_ptr;71return block_size;72}7374static void75fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,76struct lvds_dvo_timing *dvo_timing)77{78panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |79dvo_timing->hactive_lo;80panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +81((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);82panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +83dvo_timing->hsync_pulse_width;84panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +85((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);8687panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |88dvo_timing->vactive_lo;89panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +90dvo_timing->vsync_off;91panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +92dvo_timing->vsync_pulse_width;93panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +94((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);95panel_fixed_mode->clock = dvo_timing->clock * 10;96panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;9798if (dvo_timing->hsync_positive)99panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;100else101panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;102103if (dvo_timing->vsync_positive)104panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;105else106panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;107108/* Some VBTs have bogus h/vtotal values */109if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)110panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;111if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)112panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;113114drm_mode_set_name(panel_fixed_mode);115}116117/* Try to find integrated panel data */118static void119parse_lfp_panel_data(struct drm_i915_private *dev_priv,120struct bdb_header *bdb)121{122struct bdb_lvds_options *lvds_options;123struct bdb_lvds_lfp_data *lvds_lfp_data;124struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;125struct bdb_lvds_lfp_data_entry *entry;126struct lvds_dvo_timing *dvo_timing;127struct drm_display_mode *panel_fixed_mode;128int lfp_data_size, dvo_timing_offset;129int i, temp_downclock;130struct drm_display_mode *temp_mode;131132lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);133if (!lvds_options)134return;135136dev_priv->lvds_dither = lvds_options->pixel_dither;137if (lvds_options->panel_type == 0xff)138return;139140panel_type = lvds_options->panel_type;141142lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);143if (!lvds_lfp_data)144return;145146lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);147if (!lvds_lfp_data_ptrs)148return;149150dev_priv->lvds_vbt = 1;151152lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -153lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;154entry = (struct bdb_lvds_lfp_data_entry *)155((uint8_t *)lvds_lfp_data->data + (lfp_data_size *156lvds_options->panel_type));157dvo_timing_offset = lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -158lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;159160/*161* the size of fp_timing varies on the different platform.162* So calculate the DVO timing relative offset in LVDS data163* entry to get the DVO timing entry164*/165dvo_timing = (struct lvds_dvo_timing *)166((unsigned char *)entry + dvo_timing_offset);167168panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);169if (!panel_fixed_mode)170return;171172fill_detail_timing_data(panel_fixed_mode, dvo_timing);173174dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;175176DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");177drm_mode_debug_printmodeline(panel_fixed_mode);178179temp_mode = kzalloc(sizeof(*temp_mode), GFP_KERNEL);180temp_downclock = panel_fixed_mode->clock;181/*182* enumerate the LVDS panel timing info entry in VBT to check whether183* the LVDS downclock is found.184*/185for (i = 0; i < 16; i++) {186entry = (struct bdb_lvds_lfp_data_entry *)187((uint8_t *)lvds_lfp_data->data + (lfp_data_size * i));188dvo_timing = (struct lvds_dvo_timing *)189((unsigned char *)entry + dvo_timing_offset);190191fill_detail_timing_data(temp_mode, dvo_timing);192193if (temp_mode->hdisplay == panel_fixed_mode->hdisplay &&194temp_mode->hsync_start == panel_fixed_mode->hsync_start &&195temp_mode->hsync_end == panel_fixed_mode->hsync_end &&196temp_mode->htotal == panel_fixed_mode->htotal &&197temp_mode->vdisplay == panel_fixed_mode->vdisplay &&198temp_mode->vsync_start == panel_fixed_mode->vsync_start &&199temp_mode->vsync_end == panel_fixed_mode->vsync_end &&200temp_mode->vtotal == panel_fixed_mode->vtotal &&201temp_mode->clock < temp_downclock) {202/*203* downclock is already found. But we expect204* to find the lower downclock.205*/206temp_downclock = temp_mode->clock;207}208/* clear it to zero */209memset(temp_mode, 0, sizeof(*temp_mode));210}211kfree(temp_mode);212if (temp_downclock < panel_fixed_mode->clock &&213i915_lvds_downclock) {214dev_priv->lvds_downclock_avail = 1;215dev_priv->lvds_downclock = temp_downclock;216DRM_DEBUG_KMS("LVDS downclock is found in VBT. "217"Normal Clock %dKHz, downclock %dKHz\n",218temp_downclock, panel_fixed_mode->clock);219}220return;221}222223/* Try to find sdvo panel data */224static void225parse_sdvo_panel_data(struct drm_i915_private *dev_priv,226struct bdb_header *bdb)227{228struct lvds_dvo_timing *dvo_timing;229struct drm_display_mode *panel_fixed_mode;230int index;231232index = i915_vbt_sdvo_panel_type;233if (index == -1) {234struct bdb_sdvo_lvds_options *sdvo_lvds_options;235236sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);237if (!sdvo_lvds_options)238return;239240index = sdvo_lvds_options->panel_type;241}242243dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);244if (!dvo_timing)245return;246247panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);248if (!panel_fixed_mode)249return;250251fill_detail_timing_data(panel_fixed_mode, dvo_timing + index);252253dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;254255DRM_DEBUG_KMS("Found SDVO panel mode in BIOS VBT tables:\n");256drm_mode_debug_printmodeline(panel_fixed_mode);257}258259static int intel_bios_ssc_frequency(struct drm_device *dev,260bool alternate)261{262switch (INTEL_INFO(dev)->gen) {263case 2:264return alternate ? 66 : 48;265case 3:266case 4:267return alternate ? 100 : 96;268default:269return alternate ? 100 : 120;270}271}272273static void274parse_general_features(struct drm_i915_private *dev_priv,275struct bdb_header *bdb)276{277struct drm_device *dev = dev_priv->dev;278struct bdb_general_features *general;279280general = find_section(bdb, BDB_GENERAL_FEATURES);281if (general) {282dev_priv->int_tv_support = general->int_tv_support;283dev_priv->int_crt_support = general->int_crt_support;284dev_priv->lvds_use_ssc = general->enable_ssc;285dev_priv->lvds_ssc_freq =286intel_bios_ssc_frequency(dev, general->ssc_freq);287}288}289290static void291parse_general_definitions(struct drm_i915_private *dev_priv,292struct bdb_header *bdb)293{294struct bdb_general_definitions *general;295296general = find_section(bdb, BDB_GENERAL_DEFINITIONS);297if (general) {298u16 block_size = get_blocksize(general);299if (block_size >= sizeof(*general)) {300int bus_pin = general->crt_ddc_gmbus_pin;301DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);302if (bus_pin >= 1 && bus_pin <= 6)303dev_priv->crt_ddc_pin = bus_pin;304} else {305DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",306block_size);307}308}309}310311static void312parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,313struct bdb_header *bdb)314{315struct sdvo_device_mapping *p_mapping;316struct bdb_general_definitions *p_defs;317struct child_device_config *p_child;318int i, child_device_num, count;319u16 block_size;320321p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);322if (!p_defs) {323DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n");324return;325}326/* judge whether the size of child device meets the requirements.327* If the child device size obtained from general definition block328* is different with sizeof(struct child_device_config), skip the329* parsing of sdvo device info330*/331if (p_defs->child_dev_size != sizeof(*p_child)) {332/* different child dev size . Ignore it */333DRM_DEBUG_KMS("different child size is found. Invalid.\n");334return;335}336/* get the block size of general definitions */337block_size = get_blocksize(p_defs);338/* get the number of child device */339child_device_num = (block_size - sizeof(*p_defs)) /340sizeof(*p_child);341count = 0;342for (i = 0; i < child_device_num; i++) {343p_child = &(p_defs->devices[i]);344if (!p_child->device_type) {345/* skip the device block if device type is invalid */346continue;347}348if (p_child->slave_addr != SLAVE_ADDR1 &&349p_child->slave_addr != SLAVE_ADDR2) {350/*351* If the slave address is neither 0x70 nor 0x72,352* it is not a SDVO device. Skip it.353*/354continue;355}356if (p_child->dvo_port != DEVICE_PORT_DVOB &&357p_child->dvo_port != DEVICE_PORT_DVOC) {358/* skip the incorrect SDVO port */359DRM_DEBUG_KMS("Incorrect SDVO port. Skip it \n");360continue;361}362DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"363" %s port\n",364p_child->slave_addr,365(p_child->dvo_port == DEVICE_PORT_DVOB) ?366"SDVOB" : "SDVOC");367p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);368if (!p_mapping->initialized) {369p_mapping->dvo_port = p_child->dvo_port;370p_mapping->slave_addr = p_child->slave_addr;371p_mapping->dvo_wiring = p_child->dvo_wiring;372p_mapping->ddc_pin = p_child->ddc_pin;373p_mapping->i2c_pin = p_child->i2c_pin;374p_mapping->i2c_speed = p_child->i2c_speed;375p_mapping->initialized = 1;376DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d, i2c_speed=%d\n",377p_mapping->dvo_port,378p_mapping->slave_addr,379p_mapping->dvo_wiring,380p_mapping->ddc_pin,381p_mapping->i2c_pin,382p_mapping->i2c_speed);383} else {384DRM_DEBUG_KMS("Maybe one SDVO port is shared by "385"two SDVO device.\n");386}387if (p_child->slave2_addr) {388/* Maybe this is a SDVO device with multiple inputs */389/* And the mapping info is not added */390DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"391" is a SDVO device with multiple inputs.\n");392}393count++;394}395396if (!count) {397/* No SDVO device info is found */398DRM_DEBUG_KMS("No SDVO device info is found in VBT\n");399}400return;401}402403static void404parse_driver_features(struct drm_i915_private *dev_priv,405struct bdb_header *bdb)406{407struct drm_device *dev = dev_priv->dev;408struct bdb_driver_features *driver;409410driver = find_section(bdb, BDB_DRIVER_FEATURES);411if (!driver)412return;413414if (SUPPORTS_EDP(dev) &&415driver->lvds_config == BDB_DRIVER_FEATURE_EDP)416dev_priv->edp.support = 1;417418if (driver->dual_frequency)419dev_priv->render_reclock_avail = true;420}421422static void423parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)424{425struct bdb_edp *edp;426struct edp_power_seq *edp_pps;427struct edp_link_params *edp_link_params;428429edp = find_section(bdb, BDB_EDP);430if (!edp) {431if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) {432DRM_DEBUG_KMS("No eDP BDB found but eDP panel "433"supported, assume %dbpp panel color "434"depth.\n",435dev_priv->edp.bpp);436}437return;438}439440switch ((edp->color_depth >> (panel_type * 2)) & 3) {441case EDP_18BPP:442dev_priv->edp.bpp = 18;443break;444case EDP_24BPP:445dev_priv->edp.bpp = 24;446break;447case EDP_30BPP:448dev_priv->edp.bpp = 30;449break;450}451452/* Get the eDP sequencing and link info */453edp_pps = &edp->power_seqs[panel_type];454edp_link_params = &edp->link_params[panel_type];455456dev_priv->edp.pps = *edp_pps;457458dev_priv->edp.rate = edp_link_params->rate ? DP_LINK_BW_2_7 :459DP_LINK_BW_1_62;460switch (edp_link_params->lanes) {461case 0:462dev_priv->edp.lanes = 1;463break;464case 1:465dev_priv->edp.lanes = 2;466break;467case 3:468default:469dev_priv->edp.lanes = 4;470break;471}472switch (edp_link_params->preemphasis) {473case 0:474dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_0;475break;476case 1:477dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5;478break;479case 2:480dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_6;481break;482case 3:483dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5;484break;485}486switch (edp_link_params->vswing) {487case 0:488dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_400;489break;490case 1:491dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_600;492break;493case 2:494dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_800;495break;496case 3:497dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_1200;498break;499}500}501502static void503parse_device_mapping(struct drm_i915_private *dev_priv,504struct bdb_header *bdb)505{506struct bdb_general_definitions *p_defs;507struct child_device_config *p_child, *child_dev_ptr;508int i, child_device_num, count;509u16 block_size;510511p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);512if (!p_defs) {513DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");514return;515}516/* judge whether the size of child device meets the requirements.517* If the child device size obtained from general definition block518* is different with sizeof(struct child_device_config), skip the519* parsing of sdvo device info520*/521if (p_defs->child_dev_size != sizeof(*p_child)) {522/* different child dev size . Ignore it */523DRM_DEBUG_KMS("different child size is found. Invalid.\n");524return;525}526/* get the block size of general definitions */527block_size = get_blocksize(p_defs);528/* get the number of child device */529child_device_num = (block_size - sizeof(*p_defs)) /530sizeof(*p_child);531count = 0;532/* get the number of child device that is present */533for (i = 0; i < child_device_num; i++) {534p_child = &(p_defs->devices[i]);535if (!p_child->device_type) {536/* skip the device block if device type is invalid */537continue;538}539count++;540}541if (!count) {542DRM_DEBUG_KMS("no child dev is parsed from VBT \n");543return;544}545dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL);546if (!dev_priv->child_dev) {547DRM_DEBUG_KMS("No memory space for child device\n");548return;549}550551dev_priv->child_dev_num = count;552count = 0;553for (i = 0; i < child_device_num; i++) {554p_child = &(p_defs->devices[i]);555if (!p_child->device_type) {556/* skip the device block if device type is invalid */557continue;558}559child_dev_ptr = dev_priv->child_dev + count;560count++;561memcpy((void *)child_dev_ptr, (void *)p_child,562sizeof(*p_child));563}564return;565}566567static void568init_vbt_defaults(struct drm_i915_private *dev_priv)569{570struct drm_device *dev = dev_priv->dev;571572dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC;573574/* LFP panel data */575dev_priv->lvds_dither = 1;576dev_priv->lvds_vbt = 0;577578/* SDVO panel data */579dev_priv->sdvo_lvds_vbt_mode = NULL;580581/* general features */582dev_priv->int_tv_support = 1;583dev_priv->int_crt_support = 1;584585/* Default to using SSC */586dev_priv->lvds_use_ssc = 1;587dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);588DRM_DEBUG("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);589590/* eDP data */591dev_priv->edp.bpp = 18;592}593594/**595* intel_parse_bios - find VBT and initialize settings from the BIOS596* @dev: DRM device597*598* Loads the Video BIOS and checks that the VBT exists. Sets scratch registers599* to appropriate values.600*601* Returns 0 on success, nonzero on failure.602*/603bool604intel_parse_bios(struct drm_device *dev)605{606struct drm_i915_private *dev_priv = dev->dev_private;607struct pci_dev *pdev = dev->pdev;608struct bdb_header *bdb = NULL;609u8 __iomem *bios = NULL;610611init_vbt_defaults(dev_priv);612613/* XXX Should this validation be moved to intel_opregion.c? */614if (dev_priv->opregion.vbt) {615struct vbt_header *vbt = dev_priv->opregion.vbt;616if (memcmp(vbt->signature, "$VBT", 4) == 0) {617DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n",618vbt->signature);619bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);620} else621dev_priv->opregion.vbt = NULL;622}623624if (bdb == NULL) {625struct vbt_header *vbt = NULL;626size_t size;627int i;628629bios = pci_map_rom(pdev, &size);630if (!bios)631return -1;632633/* Scour memory looking for the VBT signature */634for (i = 0; i + 4 < size; i++) {635if (!memcmp(bios + i, "$VBT", 4)) {636vbt = (struct vbt_header *)(bios + i);637break;638}639}640641if (!vbt) {642DRM_ERROR("VBT signature missing\n");643pci_unmap_rom(pdev, bios);644return -1;645}646647bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);648}649650/* Grab useful general definitions */651parse_general_features(dev_priv, bdb);652parse_general_definitions(dev_priv, bdb);653parse_lfp_panel_data(dev_priv, bdb);654parse_sdvo_panel_data(dev_priv, bdb);655parse_sdvo_device_mapping(dev_priv, bdb);656parse_device_mapping(dev_priv, bdb);657parse_driver_features(dev_priv, bdb);658parse_edp(dev_priv, bdb);659660if (bios)661pci_unmap_rom(pdev, bios);662663return 0;664}665666/* Ensure that vital registers have been initialised, even if the BIOS667* is absent or just failing to do its job.668*/669void intel_setup_bios(struct drm_device *dev)670{671struct drm_i915_private *dev_priv = dev->dev_private;672673/* Set the Panel Power On/Off timings if uninitialized. */674if ((I915_READ(PP_ON_DELAYS) == 0) && (I915_READ(PP_OFF_DELAYS) == 0)) {675/* Set T2 to 40ms and T5 to 200ms */676I915_WRITE(PP_ON_DELAYS, 0x019007d0);677678/* Set T3 to 35ms and Tx to 200ms */679I915_WRITE(PP_OFF_DELAYS, 0x015e07d0);680}681}682683684