linux/drivers/gpu/drm/i915/intel_bios.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2006 Intel Corporation
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice (including the next
  12 * paragraph) shall be included in all copies or substantial portions of the
  13 * Software.
  14 *
  15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21 * SOFTWARE.
  22 *
  23 * Authors:
  24 *    Eric Anholt <eric@anholt.net>
  25 *
  26 */
  27#include "drmP.h"
  28#include "drm.h"
  29#include "i915_drm.h"
  30#include "i915_drv.h"
  31#include "intel_bios.h"
  32
  33#define SLAVE_ADDR1     0x70
  34#define SLAVE_ADDR2     0x72
  35
  36static void *
  37find_section(struct bdb_header *bdb, int section_id)
  38{
  39        u8 *base = (u8 *)bdb;
  40        int index = 0;
  41        u16 total, current_size;
  42        u8 current_id;
  43
  44        /* skip to first section */
  45        index += bdb->header_size;
  46        total = bdb->bdb_size;
  47
  48        /* walk the sections looking for section_id */
  49        while (index < total) {
  50                current_id = *(base + index);
  51                index++;
  52                current_size = *((u16 *)(base + index));
  53                index += 2;
  54                if (current_id == section_id)
  55                        return base + index;
  56                index += current_size;
  57        }
  58
  59        return NULL;
  60}
  61
  62static u16
  63get_blocksize(void *p)
  64{
  65        u16 *block_ptr, block_size;
  66
  67        block_ptr = (u16 *)((char *)p - 2);
  68        block_size = *block_ptr;
  69        return block_size;
  70}
  71
  72static void
  73fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
  74                        struct lvds_dvo_timing *dvo_timing)
  75{
  76        panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
  77                dvo_timing->hactive_lo;
  78        panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
  79                ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
  80        panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
  81                dvo_timing->hsync_pulse_width;
  82        panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
  83                ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
  84
  85        panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
  86                dvo_timing->vactive_lo;
  87        panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
  88                dvo_timing->vsync_off;
  89        panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
  90                dvo_timing->vsync_pulse_width;
  91        panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
  92                ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
  93        panel_fixed_mode->clock = dvo_timing->clock * 10;
  94        panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
  95
  96        /* Some VBTs have bogus h/vtotal values */
  97        if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
  98                panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
  99        if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
 100                panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
 101
 102        drm_mode_set_name(panel_fixed_mode);
 103}
 104
 105/* Try to find integrated panel data */
 106static void
 107parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 108                            struct bdb_header *bdb)
 109{
 110        struct bdb_lvds_options *lvds_options;
 111        struct bdb_lvds_lfp_data *lvds_lfp_data;
 112        struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
 113        struct bdb_lvds_lfp_data_entry *entry;
 114        struct lvds_dvo_timing *dvo_timing;
 115        struct drm_display_mode *panel_fixed_mode;
 116        int lfp_data_size, dvo_timing_offset;
 117
 118        /* Defaults if we can't find VBT info */
 119        dev_priv->lvds_dither = 0;
 120        dev_priv->lvds_vbt = 0;
 121
 122        lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
 123        if (!lvds_options)
 124                return;
 125
 126        dev_priv->lvds_dither = lvds_options->pixel_dither;
 127        if (lvds_options->panel_type == 0xff)
 128                return;
 129
 130        lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
 131        if (!lvds_lfp_data)
 132                return;
 133
 134        lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
 135        if (!lvds_lfp_data_ptrs)
 136                return;
 137
 138        dev_priv->lvds_vbt = 1;
 139
 140        lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
 141                lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
 142        entry = (struct bdb_lvds_lfp_data_entry *)
 143                ((uint8_t *)lvds_lfp_data->data + (lfp_data_size *
 144                                                   lvds_options->panel_type));
 145        dvo_timing_offset = lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
 146                lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
 147
 148        /*
 149         * the size of fp_timing varies on the different platform.
 150         * So calculate the DVO timing relative offset in LVDS data
 151         * entry to get the DVO timing entry
 152         */
 153        dvo_timing = (struct lvds_dvo_timing *)
 154                        ((unsigned char *)entry + dvo_timing_offset);
 155
 156        panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
 157
 158        fill_detail_timing_data(panel_fixed_mode, dvo_timing);
 159
 160        dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
 161
 162        DRM_DEBUG("Found panel mode in BIOS VBT tables:\n");
 163        drm_mode_debug_printmodeline(panel_fixed_mode);
 164
 165        return;
 166}
 167
 168/* Try to find sdvo panel data */
 169static void
 170parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
 171                      struct bdb_header *bdb)
 172{
 173        struct bdb_sdvo_lvds_options *sdvo_lvds_options;
 174        struct lvds_dvo_timing *dvo_timing;
 175        struct drm_display_mode *panel_fixed_mode;
 176
 177        dev_priv->sdvo_lvds_vbt_mode = NULL;
 178
 179        sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
 180        if (!sdvo_lvds_options)
 181                return;
 182
 183        dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
 184        if (!dvo_timing)
 185                return;
 186
 187        panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
 188
 189        if (!panel_fixed_mode)
 190                return;
 191
 192        fill_detail_timing_data(panel_fixed_mode,
 193                        dvo_timing + sdvo_lvds_options->panel_type);
 194
 195        dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
 196
 197        return;
 198}
 199
 200static void
 201parse_general_features(struct drm_i915_private *dev_priv,
 202                       struct bdb_header *bdb)
 203{
 204        struct bdb_general_features *general;
 205
 206        /* Set sensible defaults in case we can't find the general block */
 207        dev_priv->int_tv_support = 1;
 208        dev_priv->int_crt_support = 1;
 209
 210        general = find_section(bdb, BDB_GENERAL_FEATURES);
 211        if (general) {
 212                dev_priv->int_tv_support = general->int_tv_support;
 213                dev_priv->int_crt_support = general->int_crt_support;
 214                dev_priv->lvds_use_ssc = general->enable_ssc;
 215
 216                if (dev_priv->lvds_use_ssc) {
 217                        if (IS_I85X(dev_priv->dev))
 218                                dev_priv->lvds_ssc_freq =
 219                                        general->ssc_freq ? 66 : 48;
 220                        else if (IS_IGDNG(dev_priv->dev))
 221                                dev_priv->lvds_ssc_freq =
 222                                        general->ssc_freq ? 100 : 120;
 223                        else
 224                                dev_priv->lvds_ssc_freq =
 225                                        general->ssc_freq ? 100 : 96;
 226                }
 227        }
 228}
 229
 230static void
 231parse_general_definitions(struct drm_i915_private *dev_priv,
 232                          struct bdb_header *bdb)
 233{
 234        struct bdb_general_definitions *general;
 235        const int crt_bus_map_table[] = {
 236                GPIOB,
 237                GPIOA,
 238                GPIOC,
 239                GPIOD,
 240                GPIOE,
 241                GPIOF,
 242        };
 243
 244        /* Set sensible defaults in case we can't find the general block
 245           or it is the wrong chipset */
 246        dev_priv->crt_ddc_bus = -1;
 247
 248        general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
 249        if (general) {
 250                u16 block_size = get_blocksize(general);
 251                if (block_size >= sizeof(*general)) {
 252                        int bus_pin = general->crt_ddc_gmbus_pin;
 253                        DRM_DEBUG("crt_ddc_bus_pin: %d\n", bus_pin);
 254                        if ((bus_pin >= 1) && (bus_pin <= 6)) {
 255                                dev_priv->crt_ddc_bus =
 256                                        crt_bus_map_table[bus_pin-1];
 257                        }
 258                } else {
 259                        DRM_DEBUG("BDB_GD too small (%d). Invalid.\n",
 260                                  block_size);
 261                }
 262        }
 263}
 264
 265static void
 266parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
 267                       struct bdb_header *bdb)
 268{
 269        struct sdvo_device_mapping *p_mapping;
 270        struct bdb_general_definitions *p_defs;
 271        struct child_device_config *p_child;
 272        int i, child_device_num, count;
 273        u16     block_size;
 274
 275        p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
 276        if (!p_defs) {
 277                DRM_DEBUG("No general definition block is found\n");
 278                return;
 279        }
 280        /* judge whether the size of child device meets the requirements.
 281         * If the child device size obtained from general definition block
 282         * is different with sizeof(struct child_device_config), skip the
 283         * parsing of sdvo device info
 284         */
 285        if (p_defs->child_dev_size != sizeof(*p_child)) {
 286                /* different child dev size . Ignore it */
 287                DRM_DEBUG("different child size is found. Invalid.\n");
 288                return;
 289        }
 290        /* get the block size of general definitions */
 291        block_size = get_blocksize(p_defs);
 292        /* get the number of child device */
 293        child_device_num = (block_size - sizeof(*p_defs)) /
 294                                sizeof(*p_child);
 295        count = 0;
 296        for (i = 0; i < child_device_num; i++) {
 297                p_child = &(p_defs->devices[i]);
 298                if (!p_child->device_type) {
 299                        /* skip the device block if device type is invalid */
 300                        continue;
 301                }
 302                if (p_child->slave_addr != SLAVE_ADDR1 &&
 303                        p_child->slave_addr != SLAVE_ADDR2) {
 304                        /*
 305                         * If the slave address is neither 0x70 nor 0x72,
 306                         * it is not a SDVO device. Skip it.
 307                         */
 308                        continue;
 309                }
 310                if (p_child->dvo_port != DEVICE_PORT_DVOB &&
 311                        p_child->dvo_port != DEVICE_PORT_DVOC) {
 312                        /* skip the incorrect SDVO port */
 313                        DRM_DEBUG("Incorrect SDVO port. Skip it \n");
 314                        continue;
 315                }
 316                DRM_DEBUG("the SDVO device with slave addr %2x is found on "
 317                                "%s port\n",
 318                                p_child->slave_addr,
 319                                (p_child->dvo_port == DEVICE_PORT_DVOB) ?
 320                                        "SDVOB" : "SDVOC");
 321                p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);
 322                if (!p_mapping->initialized) {
 323                        p_mapping->dvo_port = p_child->dvo_port;
 324                        p_mapping->slave_addr = p_child->slave_addr;
 325                        p_mapping->dvo_wiring = p_child->dvo_wiring;
 326                        p_mapping->initialized = 1;
 327                } else {
 328                        DRM_DEBUG("Maybe one SDVO port is shared by "
 329                                         "two SDVO device.\n");
 330                }
 331                if (p_child->slave2_addr) {
 332                        /* Maybe this is a SDVO device with multiple inputs */
 333                        /* And the mapping info is not added */
 334                        DRM_DEBUG("there exists the slave2_addr. Maybe this "
 335                                "is a SDVO device with multiple inputs.\n");
 336                }
 337                count++;
 338        }
 339
 340        if (!count) {
 341                /* No SDVO device info is found */
 342                DRM_DEBUG("No SDVO device info is found in VBT\n");
 343        }
 344        return;
 345}
 346
 347static void
 348parse_driver_features(struct drm_i915_private *dev_priv,
 349                       struct bdb_header *bdb)
 350{
 351        struct drm_device *dev = dev_priv->dev;
 352        struct bdb_driver_features *driver;
 353
 354        driver = find_section(bdb, BDB_DRIVER_FEATURES);
 355        if (!driver)
 356                return;
 357
 358        if (driver && SUPPORTS_EDP(dev) &&
 359            driver->lvds_config == BDB_DRIVER_FEATURE_EDP) {
 360                dev_priv->edp_support = 1;
 361        } else {
 362                dev_priv->edp_support = 0;
 363        }
 364
 365        if (driver && driver->dual_frequency)
 366                dev_priv->render_reclock_avail = true;
 367}
 368
 369/**
 370 * intel_init_bios - initialize VBIOS settings & find VBT
 371 * @dev: DRM device
 372 *
 373 * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
 374 * to appropriate values.
 375 *
 376 * VBT existence is a sanity check that is relied on by other i830_bios.c code.
 377 * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
 378 * feed an updated VBT back through that, compared to what we'll fetch using
 379 * this method of groping around in the BIOS data.
 380 *
 381 * Returns 0 on success, nonzero on failure.
 382 */
 383bool
 384intel_init_bios(struct drm_device *dev)
 385{
 386        struct drm_i915_private *dev_priv = dev->dev_private;
 387        struct pci_dev *pdev = dev->pdev;
 388        struct vbt_header *vbt = NULL;
 389        struct bdb_header *bdb;
 390        u8 __iomem *bios;
 391        size_t size;
 392        int i;
 393
 394        bios = pci_map_rom(pdev, &size);
 395        if (!bios)
 396                return -1;
 397
 398        /* Scour memory looking for the VBT signature */
 399        for (i = 0; i + 4 < size; i++) {
 400                if (!memcmp(bios + i, "$VBT", 4)) {
 401                        vbt = (struct vbt_header *)(bios + i);
 402                        break;
 403                }
 404        }
 405
 406        if (!vbt) {
 407                DRM_ERROR("VBT signature missing\n");
 408                pci_unmap_rom(pdev, bios);
 409                return -1;
 410        }
 411
 412        bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
 413
 414        /* Grab useful general definitions */
 415        parse_general_features(dev_priv, bdb);
 416        parse_general_definitions(dev_priv, bdb);
 417        parse_lfp_panel_data(dev_priv, bdb);
 418        parse_sdvo_panel_data(dev_priv, bdb);
 419        parse_sdvo_device_mapping(dev_priv, bdb);
 420        parse_driver_features(dev_priv, bdb);
 421
 422        pci_unmap_rom(pdev, bios);
 423
 424        return 0;
 425}
 426