589 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2006 Intel Corporation4 *5 * Authors:6 * Eric Anholt <eric@anholt.net>7 */8 9#include <drm/display/drm_dp_helper.h>10#include <drm/drm.h>11 12#include "intel_bios.h"13#include "psb_drv.h"14#include "psb_intel_drv.h"15#include "psb_intel_reg.h"16 17#define TARGET_ADDR1 0x7018#define TARGET_ADDR2 0x7219 20static void *find_section(struct bdb_header *bdb, int section_id)21{22 u8 *base = (u8 *)bdb;23 int index = 0;24 u16 total, current_size;25 u8 current_id;26 27 /* skip to first section */28 index += bdb->header_size;29 total = bdb->bdb_size;30 31 /* walk the sections looking for section_id */32 while (index < total) {33 current_id = *(base + index);34 index++;35 current_size = *((u16 *)(base + index));36 index += 2;37 if (current_id == section_id)38 return base + index;39 index += current_size;40 }41 42 return NULL;43}44 45static void46parse_edp(struct drm_psb_private *dev_priv, struct bdb_header *bdb)47{48 struct bdb_edp *edp;49 struct edp_power_seq *edp_pps;50 struct edp_link_params *edp_link_params;51 uint8_t panel_type;52 53 edp = find_section(bdb, BDB_EDP);54 55 dev_priv->edp.bpp = 18;56 if (!edp) {57 if (dev_priv->edp.support) {58 DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported, assume %dbpp panel color depth.\n",59 dev_priv->edp.bpp);60 }61 return;62 }63 64 panel_type = dev_priv->panel_type;65 switch ((edp->color_depth >> (panel_type * 2)) & 3) {66 case EDP_18BPP:67 dev_priv->edp.bpp = 18;68 break;69 case EDP_24BPP:70 dev_priv->edp.bpp = 24;71 break;72 case EDP_30BPP:73 dev_priv->edp.bpp = 30;74 break;75 }76 77 /* Get the eDP sequencing and link info */78 edp_pps = &edp->power_seqs[panel_type];79 edp_link_params = &edp->link_params[panel_type];80 81 dev_priv->edp.pps = *edp_pps;82 83 DRM_DEBUG_KMS("EDP timing in vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",84 dev_priv->edp.pps.t1_t3, dev_priv->edp.pps.t8,85 dev_priv->edp.pps.t9, dev_priv->edp.pps.t10,86 dev_priv->edp.pps.t11_t12);87 88 dev_priv->edp.rate = edp_link_params->rate ? DP_LINK_BW_2_7 :89 DP_LINK_BW_1_62;90 switch (edp_link_params->lanes) {91 case 0:92 dev_priv->edp.lanes = 1;93 break;94 case 1:95 dev_priv->edp.lanes = 2;96 break;97 case 3:98 default:99 dev_priv->edp.lanes = 4;100 break;101 }102 DRM_DEBUG_KMS("VBT reports EDP: Lane_count %d, Lane_rate %d, Bpp %d\n",103 dev_priv->edp.lanes, dev_priv->edp.rate, dev_priv->edp.bpp);104 105 switch (edp_link_params->preemphasis) {106 case 0:107 dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0;108 break;109 case 1:110 dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1;111 break;112 case 2:113 dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2;114 break;115 case 3:116 dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3;117 break;118 }119 switch (edp_link_params->vswing) {120 case 0:121 dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;122 break;123 case 1:124 dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1;125 break;126 case 2:127 dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2;128 break;129 case 3:130 dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3;131 break;132 }133 DRM_DEBUG_KMS("VBT reports EDP: VSwing %d, Preemph %d\n",134 dev_priv->edp.vswing, dev_priv->edp.preemphasis);135}136 137static u16138get_blocksize(void *p)139{140 u16 *block_ptr, block_size;141 142 block_ptr = (u16 *)((char *)p - 2);143 block_size = *block_ptr;144 return block_size;145}146 147static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,148 struct lvds_dvo_timing *dvo_timing)149{150 panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |151 dvo_timing->hactive_lo;152 panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +153 ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);154 panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +155 dvo_timing->hsync_pulse_width;156 panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +157 ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);158 159 panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |160 dvo_timing->vactive_lo;161 panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +162 dvo_timing->vsync_off;163 panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +164 dvo_timing->vsync_pulse_width;165 panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +166 ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);167 panel_fixed_mode->clock = dvo_timing->clock * 10;168 panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;169 170 if (dvo_timing->hsync_positive)171 panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;172 else173 panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;174 175 if (dvo_timing->vsync_positive)176 panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;177 else178 panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;179 180 /* Some VBTs have bogus h/vtotal values */181 if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)182 panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;183 if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)184 panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;185 186 drm_mode_set_name(panel_fixed_mode);187}188 189static void parse_backlight_data(struct drm_psb_private *dev_priv,190 struct bdb_header *bdb)191{192 struct bdb_lvds_backlight *vbt_lvds_bl = NULL;193 struct bdb_lvds_backlight *lvds_bl;194 u8 p_type = 0;195 void *bl_start = NULL;196 struct bdb_lvds_options *lvds_opts197 = find_section(bdb, BDB_LVDS_OPTIONS);198 199 dev_priv->lvds_bl = NULL;200 201 if (lvds_opts)202 p_type = lvds_opts->panel_type;203 else204 return;205 206 bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT);207 vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type;208 209 lvds_bl = kmemdup(vbt_lvds_bl, sizeof(*vbt_lvds_bl), GFP_KERNEL);210 if (!lvds_bl) {211 dev_err(dev_priv->dev.dev, "out of memory for backlight data\n");212 return;213 }214 dev_priv->lvds_bl = lvds_bl;215}216 217/* Try to find integrated panel data */218static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,219 struct bdb_header *bdb)220{221 struct bdb_lvds_options *lvds_options;222 struct bdb_lvds_lfp_data *lvds_lfp_data;223 struct bdb_lvds_lfp_data_entry *entry;224 struct lvds_dvo_timing *dvo_timing;225 struct drm_display_mode *panel_fixed_mode;226 227 /* Defaults if we can't find VBT info */228 dev_priv->lvds_dither = 0;229 dev_priv->lvds_vbt = 0;230 231 lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);232 if (!lvds_options)233 return;234 235 dev_priv->lvds_dither = lvds_options->pixel_dither;236 dev_priv->panel_type = lvds_options->panel_type;237 238 if (lvds_options->panel_type == 0xff)239 return;240 241 lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);242 if (!lvds_lfp_data)243 return;244 245 246 entry = &lvds_lfp_data->data[lvds_options->panel_type];247 dvo_timing = &entry->dvo_timing;248 249 panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode),250 GFP_KERNEL);251 if (panel_fixed_mode == NULL) {252 dev_err(dev_priv->dev.dev, "out of memory for fixed panel mode\n");253 return;254 }255 256 dev_priv->lvds_vbt = 1;257 fill_detail_timing_data(panel_fixed_mode, dvo_timing);258 259 if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) {260 dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;261 drm_mode_debug_printmodeline(panel_fixed_mode);262 } else {263 dev_dbg(dev_priv->dev.dev, "ignoring invalid LVDS VBT\n");264 dev_priv->lvds_vbt = 0;265 kfree(panel_fixed_mode);266 }267 return;268}269 270/* Try to find sdvo panel data */271static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv,272 struct bdb_header *bdb)273{274 struct bdb_sdvo_lvds_options *sdvo_lvds_options;275 struct lvds_dvo_timing *dvo_timing;276 struct drm_display_mode *panel_fixed_mode;277 278 dev_priv->sdvo_lvds_vbt_mode = NULL;279 280 sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);281 if (!sdvo_lvds_options)282 return;283 284 dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);285 if (!dvo_timing)286 return;287 288 panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);289 290 if (!panel_fixed_mode)291 return;292 293 fill_detail_timing_data(panel_fixed_mode,294 dvo_timing + sdvo_lvds_options->panel_type);295 296 dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;297 298 return;299}300 301static void parse_general_features(struct drm_psb_private *dev_priv,302 struct bdb_header *bdb)303{304 struct bdb_general_features *general;305 306 /* Set sensible defaults in case we can't find the general block */307 dev_priv->int_tv_support = 1;308 dev_priv->int_crt_support = 1;309 310 general = find_section(bdb, BDB_GENERAL_FEATURES);311 if (general) {312 dev_priv->int_tv_support = general->int_tv_support;313 dev_priv->int_crt_support = general->int_crt_support;314 dev_priv->lvds_use_ssc = general->enable_ssc;315 316 if (dev_priv->lvds_use_ssc) {317 dev_priv->lvds_ssc_freq318 = general->ssc_freq ? 100 : 96;319 }320 }321}322 323static void324parse_sdvo_device_mapping(struct drm_psb_private *dev_priv,325 struct bdb_header *bdb)326{327 struct sdvo_device_mapping *p_mapping;328 struct bdb_general_definitions *p_defs;329 struct child_device_config *p_child;330 int i, child_device_num, count;331 u16 block_size;332 333 p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);334 if (!p_defs) {335 DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n");336 return;337 }338 /* judge whether the size of child device meets the requirements.339 * If the child device size obtained from general definition block340 * is different with sizeof(struct child_device_config), skip the341 * parsing of sdvo device info342 */343 if (p_defs->child_dev_size != sizeof(*p_child)) {344 /* different child dev size . Ignore it */345 DRM_DEBUG_KMS("different child size is found. Invalid.\n");346 return;347 }348 /* get the block size of general definitions */349 block_size = get_blocksize(p_defs);350 /* get the number of child device */351 child_device_num = (block_size - sizeof(*p_defs)) /352 sizeof(*p_child);353 count = 0;354 for (i = 0; i < child_device_num; i++) {355 p_child = &(p_defs->devices[i]);356 if (!p_child->device_type) {357 /* skip the device block if device type is invalid */358 continue;359 }360 if (p_child->target_addr != TARGET_ADDR1 &&361 p_child->target_addr != TARGET_ADDR2) {362 /*363 * If the target address is neither 0x70 nor 0x72,364 * it is not a SDVO device. Skip it.365 */366 continue;367 }368 if (p_child->dvo_port != DEVICE_PORT_DVOB &&369 p_child->dvo_port != DEVICE_PORT_DVOC) {370 /* skip the incorrect SDVO port */371 DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");372 continue;373 }374 DRM_DEBUG_KMS("the SDVO device with target addr %2x is found on"375 " %s port\n",376 p_child->target_addr,377 (p_child->dvo_port == DEVICE_PORT_DVOB) ?378 "SDVOB" : "SDVOC");379 p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);380 if (!p_mapping->initialized) {381 p_mapping->dvo_port = p_child->dvo_port;382 p_mapping->target_addr = p_child->target_addr;383 p_mapping->dvo_wiring = p_child->dvo_wiring;384 p_mapping->ddc_pin = p_child->ddc_pin;385 p_mapping->i2c_pin = p_child->i2c_pin;386 p_mapping->initialized = 1;387 DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",388 p_mapping->dvo_port,389 p_mapping->target_addr,390 p_mapping->dvo_wiring,391 p_mapping->ddc_pin,392 p_mapping->i2c_pin);393 } else {394 DRM_DEBUG_KMS("Maybe one SDVO port is shared by "395 "two SDVO device.\n");396 }397 if (p_child->target2_addr) {398 /* Maybe this is a SDVO device with multiple inputs */399 /* And the mapping info is not added */400 DRM_DEBUG_KMS("there exists the target2_addr. Maybe this"401 " is a SDVO device with multiple inputs.\n");402 }403 count++;404 }405 406 if (!count) {407 /* No SDVO device info is found */408 DRM_DEBUG_KMS("No SDVO device info is found in VBT\n");409 }410 return;411}412 413 414static void415parse_driver_features(struct drm_psb_private *dev_priv,416 struct bdb_header *bdb)417{418 struct bdb_driver_features *driver;419 420 driver = find_section(bdb, BDB_DRIVER_FEATURES);421 if (!driver)422 return;423 424 if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)425 dev_priv->edp.support = 1;426 427 dev_priv->lvds_enabled_in_vbt = driver->lvds_config != 0;428 DRM_DEBUG_KMS("LVDS VBT config bits: 0x%x\n", driver->lvds_config);429 430 /* This bit means to use 96Mhz for DPLL_A or not */431 if (driver->primary_lfp_id)432 dev_priv->dplla_96mhz = true;433 else434 dev_priv->dplla_96mhz = false;435}436 437static void438parse_device_mapping(struct drm_psb_private *dev_priv,439 struct bdb_header *bdb)440{441 struct bdb_general_definitions *p_defs;442 struct child_device_config *p_child, *child_dev_ptr;443 int i, child_device_num, count;444 u16 block_size;445 446 p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);447 if (!p_defs) {448 DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");449 return;450 }451 /* judge whether the size of child device meets the requirements.452 * If the child device size obtained from general definition block453 * is different with sizeof(struct child_device_config), skip the454 * parsing of sdvo device info455 */456 if (p_defs->child_dev_size != sizeof(*p_child)) {457 /* different child dev size . Ignore it */458 DRM_DEBUG_KMS("different child size is found. Invalid.\n");459 return;460 }461 /* get the block size of general definitions */462 block_size = get_blocksize(p_defs);463 /* get the number of child device */464 child_device_num = (block_size - sizeof(*p_defs)) /465 sizeof(*p_child);466 count = 0;467 /* get the number of child devices that are present */468 for (i = 0; i < child_device_num; i++) {469 p_child = &(p_defs->devices[i]);470 if (!p_child->device_type) {471 /* skip the device block if device type is invalid */472 continue;473 }474 count++;475 }476 if (!count) {477 DRM_DEBUG_KMS("no child dev is parsed from VBT\n");478 return;479 }480 dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL);481 if (!dev_priv->child_dev) {482 DRM_DEBUG_KMS("No memory space for child devices\n");483 return;484 }485 486 dev_priv->child_dev_num = count;487 count = 0;488 for (i = 0; i < child_device_num; i++) {489 p_child = &(p_defs->devices[i]);490 if (!p_child->device_type) {491 /* skip the device block if device type is invalid */492 continue;493 }494 child_dev_ptr = dev_priv->child_dev + count;495 count++;496 memcpy((void *)child_dev_ptr, (void *)p_child,497 sizeof(*p_child));498 }499 return;500}501 502 503/**504 * psb_intel_init_bios - initialize VBIOS settings & find VBT505 * @dev: DRM device506 *507 * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers508 * to appropriate values.509 *510 * VBT existence is a sanity check that is relied on by other i830_bios.c code.511 * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may512 * feed an updated VBT back through that, compared to what we'll fetch using513 * this method of groping around in the BIOS data.514 *515 * Returns 0 on success, nonzero on failure.516 */517int psb_intel_init_bios(struct drm_device *dev)518{519 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);520 struct pci_dev *pdev = to_pci_dev(dev->dev);521 struct vbt_header *vbt = NULL;522 struct bdb_header *bdb = NULL;523 u8 __iomem *bios = NULL;524 size_t size;525 int i;526 527 528 dev_priv->panel_type = 0xff;529 530 /* XXX Should this validation be moved to intel_opregion.c? */531 if (dev_priv->opregion.vbt) {532 struct vbt_header *vbt = dev_priv->opregion.vbt;533 if (memcmp(vbt->signature, "$VBT", 4) == 0) {534 DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",535 vbt->signature);536 bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);537 } else538 dev_priv->opregion.vbt = NULL;539 }540 541 if (bdb == NULL) {542 bios = pci_map_rom(pdev, &size);543 if (!bios)544 return -1;545 546 /* Scour memory looking for the VBT signature */547 for (i = 0; i + 4 < size; i++) {548 if (!memcmp(bios + i, "$VBT", 4)) {549 vbt = (struct vbt_header *)(bios + i);550 break;551 }552 }553 554 if (!vbt) {555 dev_err(dev->dev, "VBT signature missing\n");556 pci_unmap_rom(pdev, bios);557 return -1;558 }559 bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);560 }561 562 /* Grab useful general dxefinitions */563 parse_general_features(dev_priv, bdb);564 parse_driver_features(dev_priv, bdb);565 parse_lfp_panel_data(dev_priv, bdb);566 parse_sdvo_panel_data(dev_priv, bdb);567 parse_sdvo_device_mapping(dev_priv, bdb);568 parse_device_mapping(dev_priv, bdb);569 parse_backlight_data(dev_priv, bdb);570 parse_edp(dev_priv, bdb);571 572 if (bios)573 pci_unmap_rom(pdev, bios);574 575 return 0;576}577 578/*579 * Destroy and free VBT data580 */581void psb_intel_destroy_bios(struct drm_device *dev)582{583 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);584 585 kfree(dev_priv->sdvo_lvds_vbt_mode);586 kfree(dev_priv->lfp_lvds_vbt_mode);587 kfree(dev_priv->lvds_bl);588}589