aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/gma500/intel_bios.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/gma500/intel_bios.c')
-rw-r--r--drivers/gpu/drm/gma500/intel_bios.c274
1 files changed, 234 insertions, 40 deletions
diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c
index d4d0c5b8bf91..973d7f6d66b7 100644
--- a/drivers/gpu/drm/gma500/intel_bios.c
+++ b/drivers/gpu/drm/gma500/intel_bios.c
@@ -26,6 +26,8 @@
26#include "psb_intel_reg.h" 26#include "psb_intel_reg.h"
27#include "intel_bios.h" 27#include "intel_bios.h"
28 28
29#define SLAVE_ADDR1 0x70
30#define SLAVE_ADDR2 0x72
29 31
30static void *find_section(struct bdb_header *bdb, int section_id) 32static void *find_section(struct bdb_header *bdb, int section_id)
31{ 33{
@@ -52,6 +54,16 @@ static void *find_section(struct bdb_header *bdb, int section_id)
52 return NULL; 54 return NULL;
53} 55}
54 56
57static u16
58get_blocksize(void *p)
59{
60 u16 *block_ptr, block_size;
61
62 block_ptr = (u16 *)((char *)p - 2);
63 block_size = *block_ptr;
64 return block_size;
65}
66
55static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, 67static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
56 struct lvds_dvo_timing *dvo_timing) 68 struct lvds_dvo_timing *dvo_timing)
57{ 69{
@@ -75,6 +87,16 @@ static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
75 panel_fixed_mode->clock = dvo_timing->clock * 10; 87 panel_fixed_mode->clock = dvo_timing->clock * 10;
76 panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; 88 panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
77 89
90 if (dvo_timing->hsync_positive)
91 panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
92 else
93 panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
94
95 if (dvo_timing->vsync_positive)
96 panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
97 else
98 panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
99
78 /* Some VBTs have bogus h/vtotal values */ 100 /* Some VBTs have bogus h/vtotal values */
79 if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) 101 if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
80 panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; 102 panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
@@ -217,6 +239,180 @@ static void parse_general_features(struct drm_psb_private *dev_priv,
217 } 239 }
218} 240}
219 241
242static void
243parse_sdvo_device_mapping(struct drm_psb_private *dev_priv,
244 struct bdb_header *bdb)
245{
246 struct sdvo_device_mapping *p_mapping;
247 struct bdb_general_definitions *p_defs;
248 struct child_device_config *p_child;
249 int i, child_device_num, count;
250 u16 block_size;
251
252 p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
253 if (!p_defs) {
254 DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n");
255 return;
256 }
257 /* judge whether the size of child device meets the requirements.
258 * If the child device size obtained from general definition block
259 * is different with sizeof(struct child_device_config), skip the
260 * parsing of sdvo device info
261 */
262 if (p_defs->child_dev_size != sizeof(*p_child)) {
263 /* different child dev size . Ignore it */
264 DRM_DEBUG_KMS("different child size is found. Invalid.\n");
265 return;
266 }
267 /* get the block size of general definitions */
268 block_size = get_blocksize(p_defs);
269 /* get the number of child device */
270 child_device_num = (block_size - sizeof(*p_defs)) /
271 sizeof(*p_child);
272 count = 0;
273 for (i = 0; i < child_device_num; i++) {
274 p_child = &(p_defs->devices[i]);
275 if (!p_child->device_type) {
276 /* skip the device block if device type is invalid */
277 continue;
278 }
279 if (p_child->slave_addr != SLAVE_ADDR1 &&
280 p_child->slave_addr != SLAVE_ADDR2) {
281 /*
282 * If the slave address is neither 0x70 nor 0x72,
283 * it is not a SDVO device. Skip it.
284 */
285 continue;
286 }
287 if (p_child->dvo_port != DEVICE_PORT_DVOB &&
288 p_child->dvo_port != DEVICE_PORT_DVOC) {
289 /* skip the incorrect SDVO port */
290 DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
291 continue;
292 }
293 DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
294 " %s port\n",
295 p_child->slave_addr,
296 (p_child->dvo_port == DEVICE_PORT_DVOB) ?
297 "SDVOB" : "SDVOC");
298 p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);
299 if (!p_mapping->initialized) {
300 p_mapping->dvo_port = p_child->dvo_port;
301 p_mapping->slave_addr = p_child->slave_addr;
302 p_mapping->dvo_wiring = p_child->dvo_wiring;
303 p_mapping->ddc_pin = p_child->ddc_pin;
304 p_mapping->i2c_pin = p_child->i2c_pin;
305 p_mapping->initialized = 1;
306 DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
307 p_mapping->dvo_port,
308 p_mapping->slave_addr,
309 p_mapping->dvo_wiring,
310 p_mapping->ddc_pin,
311 p_mapping->i2c_pin);
312 } else {
313 DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
314 "two SDVO device.\n");
315 }
316 if (p_child->slave2_addr) {
317 /* Maybe this is a SDVO device with multiple inputs */
318 /* And the mapping info is not added */
319 DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
320 " is a SDVO device with multiple inputs.\n");
321 }
322 count++;
323 }
324
325 if (!count) {
326 /* No SDVO device info is found */
327 DRM_DEBUG_KMS("No SDVO device info is found in VBT\n");
328 }
329 return;
330}
331
332
333static void
334parse_driver_features(struct drm_psb_private *dev_priv,
335 struct bdb_header *bdb)
336{
337 struct bdb_driver_features *driver;
338
339 driver = find_section(bdb, BDB_DRIVER_FEATURES);
340 if (!driver)
341 return;
342
343 /* This bit means to use 96Mhz for DPLL_A or not */
344 if (driver->primary_lfp_id)
345 dev_priv->dplla_96mhz = true;
346 else
347 dev_priv->dplla_96mhz = false;
348}
349
350static void
351parse_device_mapping(struct drm_psb_private *dev_priv,
352 struct bdb_header *bdb)
353{
354 struct bdb_general_definitions *p_defs;
355 struct child_device_config *p_child, *child_dev_ptr;
356 int i, child_device_num, count;
357 u16 block_size;
358
359 p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
360 if (!p_defs) {
361 DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
362 return;
363 }
364 /* judge whether the size of child device meets the requirements.
365 * If the child device size obtained from general definition block
366 * is different with sizeof(struct child_device_config), skip the
367 * parsing of sdvo device info
368 */
369 if (p_defs->child_dev_size != sizeof(*p_child)) {
370 /* different child dev size . Ignore it */
371 DRM_DEBUG_KMS("different child size is found. Invalid.\n");
372 return;
373 }
374 /* get the block size of general definitions */
375 block_size = get_blocksize(p_defs);
376 /* get the number of child device */
377 child_device_num = (block_size - sizeof(*p_defs)) /
378 sizeof(*p_child);
379 count = 0;
380 /* get the number of child devices that are present */
381 for (i = 0; i < child_device_num; i++) {
382 p_child = &(p_defs->devices[i]);
383 if (!p_child->device_type) {
384 /* skip the device block if device type is invalid */
385 continue;
386 }
387 count++;
388 }
389 if (!count) {
390 DRM_DEBUG_KMS("no child dev is parsed from VBT\n");
391 return;
392 }
393 dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL);
394 if (!dev_priv->child_dev) {
395 DRM_DEBUG_KMS("No memory space for child devices\n");
396 return;
397 }
398
399 dev_priv->child_dev_num = count;
400 count = 0;
401 for (i = 0; i < child_device_num; i++) {
402 p_child = &(p_defs->devices[i]);
403 if (!p_child->device_type) {
404 /* skip the device block if device type is invalid */
405 continue;
406 }
407 child_dev_ptr = dev_priv->child_dev + count;
408 count++;
409 memcpy((void *)child_dev_ptr, (void *)p_child,
410 sizeof(*p_child));
411 }
412 return;
413}
414
415
220/** 416/**
221 * psb_intel_init_bios - initialize VBIOS settings & find VBT 417 * psb_intel_init_bios - initialize VBIOS settings & find VBT
222 * @dev: DRM device 418 * @dev: DRM device
@@ -236,38 +432,54 @@ bool psb_intel_init_bios(struct drm_device *dev)
236 struct drm_psb_private *dev_priv = dev->dev_private; 432 struct drm_psb_private *dev_priv = dev->dev_private;
237 struct pci_dev *pdev = dev->pdev; 433 struct pci_dev *pdev = dev->pdev;
238 struct vbt_header *vbt = NULL; 434 struct vbt_header *vbt = NULL;
239 struct bdb_header *bdb; 435 struct bdb_header *bdb = NULL;
240 u8 __iomem *bios; 436 u8 __iomem *bios = NULL;
241 size_t size; 437 size_t size;
242 int i; 438 int i;
243 439
244 bios = pci_map_rom(pdev, &size); 440 /* XXX Should this validation be moved to intel_opregion.c? */
245 if (!bios) 441 if (dev_priv->opregion.vbt) {
246 return -1; 442 struct vbt_header *vbt = dev_priv->opregion.vbt;
443 if (memcmp(vbt->signature, "$VBT", 4) == 0) {
444 DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
445 vbt->signature);
446 bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
447 } else
448 dev_priv->opregion.vbt = NULL;
449 }
247 450
248 /* Scour memory looking for the VBT signature */ 451 if (bdb == NULL) {
249 for (i = 0; i + 4 < size; i++) { 452 bios = pci_map_rom(pdev, &size);
250 if (!memcmp(bios + i, "$VBT", 4)) { 453 if (!bios)
251 vbt = (struct vbt_header *)(bios + i); 454 return -1;
252 break; 455
456 /* Scour memory looking for the VBT signature */
457 for (i = 0; i + 4 < size; i++) {
458 if (!memcmp(bios + i, "$VBT", 4)) {
459 vbt = (struct vbt_header *)(bios + i);
460 break;
461 }
253 } 462 }
254 }
255 463
256 if (!vbt) { 464 if (!vbt) {
257 dev_err(dev->dev, "VBT signature missing\n"); 465 dev_err(dev->dev, "VBT signature missing\n");
258 pci_unmap_rom(pdev, bios); 466 pci_unmap_rom(pdev, bios);
259 return -1; 467 return -1;
468 }
469 bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
260 } 470 }
261 471
262 bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); 472 /* Grab useful general dxefinitions */
263
264 /* Grab useful general definitions */
265 parse_general_features(dev_priv, bdb); 473 parse_general_features(dev_priv, bdb);
474 parse_driver_features(dev_priv, bdb);
266 parse_lfp_panel_data(dev_priv, bdb); 475 parse_lfp_panel_data(dev_priv, bdb);
267 parse_sdvo_panel_data(dev_priv, bdb); 476 parse_sdvo_panel_data(dev_priv, bdb);
477 parse_sdvo_device_mapping(dev_priv, bdb);
478 parse_device_mapping(dev_priv, bdb);
268 parse_backlight_data(dev_priv, bdb); 479 parse_backlight_data(dev_priv, bdb);
269 480
270 pci_unmap_rom(pdev, bios); 481 if (bios)
482 pci_unmap_rom(pdev, bios);
271 483
272 return 0; 484 return 0;
273} 485}
@@ -278,26 +490,8 @@ bool psb_intel_init_bios(struct drm_device *dev)
278void psb_intel_destroy_bios(struct drm_device *dev) 490void psb_intel_destroy_bios(struct drm_device *dev)
279{ 491{
280 struct drm_psb_private *dev_priv = dev->dev_private; 492 struct drm_psb_private *dev_priv = dev->dev_private;
281 struct drm_display_mode *sdvo_lvds_vbt_mode =
282 dev_priv->sdvo_lvds_vbt_mode;
283 struct drm_display_mode *lfp_lvds_vbt_mode =
284 dev_priv->lfp_lvds_vbt_mode;
285 struct bdb_lvds_backlight *lvds_bl =
286 dev_priv->lvds_bl;
287
288 /*free sdvo panel mode*/
289 if (sdvo_lvds_vbt_mode) {
290 dev_priv->sdvo_lvds_vbt_mode = NULL;
291 kfree(sdvo_lvds_vbt_mode);
292 }
293 493
294 if (lfp_lvds_vbt_mode) { 494 kfree(dev_priv->sdvo_lvds_vbt_mode);
295 dev_priv->lfp_lvds_vbt_mode = NULL; 495 kfree(dev_priv->lfp_lvds_vbt_mode);
296 kfree(lfp_lvds_vbt_mode); 496 kfree(dev_priv->lvds_bl);
297 }
298
299 if (lvds_bl) {
300 dev_priv->lvds_bl = NULL;
301 kfree(lvds_bl);
302 }
303} 497}