diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/gpu/drm/i915/intel_bios.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/gpu/drm/i915/intel_bios.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 172 |
1 files changed, 155 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 96cd256e60e6..f9ba452f0cbf 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #define SLAVE_ADDR1 0x70 | 33 | #define SLAVE_ADDR1 0x70 |
34 | #define SLAVE_ADDR2 0x72 | 34 | #define SLAVE_ADDR2 0x72 |
35 | 35 | ||
36 | static int panel_type; | ||
37 | |||
36 | static void * | 38 | static void * |
37 | find_section(struct bdb_header *bdb, int section_id) | 39 | find_section(struct bdb_header *bdb, int section_id) |
38 | { | 40 | { |
@@ -114,6 +116,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
114 | struct lvds_dvo_timing *dvo_timing; | 116 | struct lvds_dvo_timing *dvo_timing; |
115 | struct drm_display_mode *panel_fixed_mode; | 117 | struct drm_display_mode *panel_fixed_mode; |
116 | int lfp_data_size, dvo_timing_offset; | 118 | int lfp_data_size, dvo_timing_offset; |
119 | int i, temp_downclock; | ||
120 | struct drm_display_mode *temp_mode; | ||
117 | 121 | ||
118 | /* Defaults if we can't find VBT info */ | 122 | /* Defaults if we can't find VBT info */ |
119 | dev_priv->lvds_dither = 0; | 123 | dev_priv->lvds_dither = 0; |
@@ -126,6 +130,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
126 | dev_priv->lvds_dither = lvds_options->pixel_dither; | 130 | dev_priv->lvds_dither = lvds_options->pixel_dither; |
127 | if (lvds_options->panel_type == 0xff) | 131 | if (lvds_options->panel_type == 0xff) |
128 | return; | 132 | return; |
133 | panel_type = lvds_options->panel_type; | ||
129 | 134 | ||
130 | lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); | 135 | lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); |
131 | if (!lvds_lfp_data) | 136 | if (!lvds_lfp_data) |
@@ -159,9 +164,50 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
159 | 164 | ||
160 | dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; | 165 | dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; |
161 | 166 | ||
162 | DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); | 167 | DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n"); |
163 | drm_mode_debug_printmodeline(panel_fixed_mode); | 168 | drm_mode_debug_printmodeline(panel_fixed_mode); |
164 | 169 | ||
170 | temp_mode = kzalloc(sizeof(*temp_mode), GFP_KERNEL); | ||
171 | temp_downclock = panel_fixed_mode->clock; | ||
172 | /* | ||
173 | * enumerate the LVDS panel timing info entry in VBT to check whether | ||
174 | * the LVDS downclock is found. | ||
175 | */ | ||
176 | for (i = 0; i < 16; i++) { | ||
177 | entry = (struct bdb_lvds_lfp_data_entry *) | ||
178 | ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * i)); | ||
179 | dvo_timing = (struct lvds_dvo_timing *) | ||
180 | ((unsigned char *)entry + dvo_timing_offset); | ||
181 | |||
182 | fill_detail_timing_data(temp_mode, dvo_timing); | ||
183 | |||
184 | if (temp_mode->hdisplay == panel_fixed_mode->hdisplay && | ||
185 | temp_mode->hsync_start == panel_fixed_mode->hsync_start && | ||
186 | temp_mode->hsync_end == panel_fixed_mode->hsync_end && | ||
187 | temp_mode->htotal == panel_fixed_mode->htotal && | ||
188 | temp_mode->vdisplay == panel_fixed_mode->vdisplay && | ||
189 | temp_mode->vsync_start == panel_fixed_mode->vsync_start && | ||
190 | temp_mode->vsync_end == panel_fixed_mode->vsync_end && | ||
191 | temp_mode->vtotal == panel_fixed_mode->vtotal && | ||
192 | temp_mode->clock < temp_downclock) { | ||
193 | /* | ||
194 | * downclock is already found. But we expect | ||
195 | * to find the lower downclock. | ||
196 | */ | ||
197 | temp_downclock = temp_mode->clock; | ||
198 | } | ||
199 | /* clear it to zero */ | ||
200 | memset(temp_mode, 0, sizeof(*temp_mode)); | ||
201 | } | ||
202 | kfree(temp_mode); | ||
203 | if (temp_downclock < panel_fixed_mode->clock && | ||
204 | i915_lvds_downclock) { | ||
205 | dev_priv->lvds_downclock_avail = 1; | ||
206 | dev_priv->lvds_downclock = temp_downclock; | ||
207 | DRM_DEBUG_KMS("LVDS downclock is found in VBT. ", | ||
208 | "Normal Clock %dKHz, downclock %dKHz\n", | ||
209 | temp_downclock, panel_fixed_mode->clock); | ||
210 | } | ||
165 | return; | 211 | return; |
166 | } | 212 | } |
167 | 213 | ||
@@ -201,6 +247,7 @@ static void | |||
201 | parse_general_features(struct drm_i915_private *dev_priv, | 247 | parse_general_features(struct drm_i915_private *dev_priv, |
202 | struct bdb_header *bdb) | 248 | struct bdb_header *bdb) |
203 | { | 249 | { |
250 | struct drm_device *dev = dev_priv->dev; | ||
204 | struct bdb_general_features *general; | 251 | struct bdb_general_features *general; |
205 | 252 | ||
206 | /* Set sensible defaults in case we can't find the general block */ | 253 | /* Set sensible defaults in case we can't find the general block */ |
@@ -217,7 +264,7 @@ parse_general_features(struct drm_i915_private *dev_priv, | |||
217 | if (IS_I85X(dev_priv->dev)) | 264 | if (IS_I85X(dev_priv->dev)) |
218 | dev_priv->lvds_ssc_freq = | 265 | dev_priv->lvds_ssc_freq = |
219 | general->ssc_freq ? 66 : 48; | 266 | general->ssc_freq ? 66 : 48; |
220 | else if (IS_IGDNG(dev_priv->dev)) | 267 | else if (IS_IRONLAKE(dev_priv->dev) || IS_GEN6(dev)) |
221 | dev_priv->lvds_ssc_freq = | 268 | dev_priv->lvds_ssc_freq = |
222 | general->ssc_freq ? 100 : 120; | 269 | general->ssc_freq ? 100 : 120; |
223 | else | 270 | else |
@@ -241,22 +288,18 @@ parse_general_definitions(struct drm_i915_private *dev_priv, | |||
241 | GPIOF, | 288 | GPIOF, |
242 | }; | 289 | }; |
243 | 290 | ||
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); | 291 | general = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
249 | if (general) { | 292 | if (general) { |
250 | u16 block_size = get_blocksize(general); | 293 | u16 block_size = get_blocksize(general); |
251 | if (block_size >= sizeof(*general)) { | 294 | if (block_size >= sizeof(*general)) { |
252 | int bus_pin = general->crt_ddc_gmbus_pin; | 295 | int bus_pin = general->crt_ddc_gmbus_pin; |
253 | DRM_DEBUG("crt_ddc_bus_pin: %d\n", bus_pin); | 296 | DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); |
254 | if ((bus_pin >= 1) && (bus_pin <= 6)) { | 297 | if ((bus_pin >= 1) && (bus_pin <= 6)) { |
255 | dev_priv->crt_ddc_bus = | 298 | dev_priv->crt_ddc_bus = |
256 | crt_bus_map_table[bus_pin-1]; | 299 | crt_bus_map_table[bus_pin-1]; |
257 | } | 300 | } |
258 | } else { | 301 | } else { |
259 | DRM_DEBUG("BDB_GD too small (%d). Invalid.\n", | 302 | DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", |
260 | block_size); | 303 | block_size); |
261 | } | 304 | } |
262 | } | 305 | } |
@@ -274,7 +317,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
274 | 317 | ||
275 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); | 318 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
276 | if (!p_defs) { | 319 | if (!p_defs) { |
277 | DRM_DEBUG("No general definition block is found\n"); | 320 | DRM_DEBUG_KMS("No general definition block is found\n"); |
278 | return; | 321 | return; |
279 | } | 322 | } |
280 | /* judge whether the size of child device meets the requirements. | 323 | /* judge whether the size of child device meets the requirements. |
@@ -284,7 +327,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
284 | */ | 327 | */ |
285 | if (p_defs->child_dev_size != sizeof(*p_child)) { | 328 | if (p_defs->child_dev_size != sizeof(*p_child)) { |
286 | /* different child dev size . Ignore it */ | 329 | /* different child dev size . Ignore it */ |
287 | DRM_DEBUG("different child size is found. Invalid.\n"); | 330 | DRM_DEBUG_KMS("different child size is found. Invalid.\n"); |
288 | return; | 331 | return; |
289 | } | 332 | } |
290 | /* get the block size of general definitions */ | 333 | /* get the block size of general definitions */ |
@@ -310,11 +353,11 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
310 | if (p_child->dvo_port != DEVICE_PORT_DVOB && | 353 | if (p_child->dvo_port != DEVICE_PORT_DVOB && |
311 | p_child->dvo_port != DEVICE_PORT_DVOC) { | 354 | p_child->dvo_port != DEVICE_PORT_DVOC) { |
312 | /* skip the incorrect SDVO port */ | 355 | /* skip the incorrect SDVO port */ |
313 | DRM_DEBUG("Incorrect SDVO port. Skip it \n"); | 356 | DRM_DEBUG_KMS("Incorrect SDVO port. Skip it \n"); |
314 | continue; | 357 | continue; |
315 | } | 358 | } |
316 | DRM_DEBUG("the SDVO device with slave addr %2x is found on " | 359 | DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" |
317 | "%s port\n", | 360 | " %s port\n", |
318 | p_child->slave_addr, | 361 | p_child->slave_addr, |
319 | (p_child->dvo_port == DEVICE_PORT_DVOB) ? | 362 | (p_child->dvo_port == DEVICE_PORT_DVOB) ? |
320 | "SDVOB" : "SDVOC"); | 363 | "SDVOB" : "SDVOC"); |
@@ -325,21 +368,21 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
325 | p_mapping->dvo_wiring = p_child->dvo_wiring; | 368 | p_mapping->dvo_wiring = p_child->dvo_wiring; |
326 | p_mapping->initialized = 1; | 369 | p_mapping->initialized = 1; |
327 | } else { | 370 | } else { |
328 | DRM_DEBUG("Maybe one SDVO port is shared by " | 371 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " |
329 | "two SDVO device.\n"); | 372 | "two SDVO device.\n"); |
330 | } | 373 | } |
331 | if (p_child->slave2_addr) { | 374 | if (p_child->slave2_addr) { |
332 | /* Maybe this is a SDVO device with multiple inputs */ | 375 | /* Maybe this is a SDVO device with multiple inputs */ |
333 | /* And the mapping info is not added */ | 376 | /* And the mapping info is not added */ |
334 | DRM_DEBUG("there exists the slave2_addr. Maybe this " | 377 | DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this" |
335 | "is a SDVO device with multiple inputs.\n"); | 378 | " is a SDVO device with multiple inputs.\n"); |
336 | } | 379 | } |
337 | count++; | 380 | count++; |
338 | } | 381 | } |
339 | 382 | ||
340 | if (!count) { | 383 | if (!count) { |
341 | /* No SDVO device info is found */ | 384 | /* No SDVO device info is found */ |
342 | DRM_DEBUG("No SDVO device info is found in VBT\n"); | 385 | DRM_DEBUG_KMS("No SDVO device info is found in VBT\n"); |
343 | } | 386 | } |
344 | return; | 387 | return; |
345 | } | 388 | } |
@@ -366,6 +409,99 @@ parse_driver_features(struct drm_i915_private *dev_priv, | |||
366 | dev_priv->render_reclock_avail = true; | 409 | dev_priv->render_reclock_avail = true; |
367 | } | 410 | } |
368 | 411 | ||
412 | static void | ||
413 | parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | ||
414 | { | ||
415 | struct bdb_edp *edp; | ||
416 | |||
417 | edp = find_section(bdb, BDB_EDP); | ||
418 | if (!edp) { | ||
419 | if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) { | ||
420 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel " | ||
421 | "supported, assume 18bpp panel color " | ||
422 | "depth.\n"); | ||
423 | dev_priv->edp_bpp = 18; | ||
424 | } | ||
425 | return; | ||
426 | } | ||
427 | |||
428 | switch ((edp->color_depth >> (panel_type * 2)) & 3) { | ||
429 | case EDP_18BPP: | ||
430 | dev_priv->edp_bpp = 18; | ||
431 | break; | ||
432 | case EDP_24BPP: | ||
433 | dev_priv->edp_bpp = 24; | ||
434 | break; | ||
435 | case EDP_30BPP: | ||
436 | dev_priv->edp_bpp = 30; | ||
437 | break; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | static void | ||
442 | parse_device_mapping(struct drm_i915_private *dev_priv, | ||
443 | struct bdb_header *bdb) | ||
444 | { | ||
445 | struct bdb_general_definitions *p_defs; | ||
446 | struct child_device_config *p_child, *child_dev_ptr; | ||
447 | int i, child_device_num, count; | ||
448 | u16 block_size; | ||
449 | |||
450 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); | ||
451 | if (!p_defs) { | ||
452 | DRM_DEBUG_KMS("No general definition block is found\n"); | ||
453 | return; | ||
454 | } | ||
455 | /* judge whether the size of child device meets the requirements. | ||
456 | * If the child device size obtained from general definition block | ||
457 | * is different with sizeof(struct child_device_config), skip the | ||
458 | * parsing of sdvo device info | ||
459 | */ | ||
460 | if (p_defs->child_dev_size != sizeof(*p_child)) { | ||
461 | /* different child dev size . Ignore it */ | ||
462 | DRM_DEBUG_KMS("different child size is found. Invalid.\n"); | ||
463 | return; | ||
464 | } | ||
465 | /* get the block size of general definitions */ | ||
466 | block_size = get_blocksize(p_defs); | ||
467 | /* get the number of child device */ | ||
468 | child_device_num = (block_size - sizeof(*p_defs)) / | ||
469 | sizeof(*p_child); | ||
470 | count = 0; | ||
471 | /* get the number of child device that is present */ | ||
472 | for (i = 0; i < child_device_num; i++) { | ||
473 | p_child = &(p_defs->devices[i]); | ||
474 | if (!p_child->device_type) { | ||
475 | /* skip the device block if device type is invalid */ | ||
476 | continue; | ||
477 | } | ||
478 | count++; | ||
479 | } | ||
480 | if (!count) { | ||
481 | DRM_DEBUG_KMS("no child dev is parsed from VBT \n"); | ||
482 | return; | ||
483 | } | ||
484 | dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL); | ||
485 | if (!dev_priv->child_dev) { | ||
486 | DRM_DEBUG_KMS("No memory space for child device\n"); | ||
487 | return; | ||
488 | } | ||
489 | |||
490 | dev_priv->child_dev_num = count; | ||
491 | count = 0; | ||
492 | for (i = 0; i < child_device_num; i++) { | ||
493 | p_child = &(p_defs->devices[i]); | ||
494 | if (!p_child->device_type) { | ||
495 | /* skip the device block if device type is invalid */ | ||
496 | continue; | ||
497 | } | ||
498 | child_dev_ptr = dev_priv->child_dev + count; | ||
499 | count++; | ||
500 | memcpy((void *)child_dev_ptr, (void *)p_child, | ||
501 | sizeof(*p_child)); | ||
502 | } | ||
503 | return; | ||
504 | } | ||
369 | /** | 505 | /** |
370 | * intel_init_bios - initialize VBIOS settings & find VBT | 506 | * intel_init_bios - initialize VBIOS settings & find VBT |
371 | * @dev: DRM device | 507 | * @dev: DRM device |
@@ -417,7 +553,9 @@ intel_init_bios(struct drm_device *dev) | |||
417 | parse_lfp_panel_data(dev_priv, bdb); | 553 | parse_lfp_panel_data(dev_priv, bdb); |
418 | parse_sdvo_panel_data(dev_priv, bdb); | 554 | parse_sdvo_panel_data(dev_priv, bdb); |
419 | parse_sdvo_device_mapping(dev_priv, bdb); | 555 | parse_sdvo_device_mapping(dev_priv, bdb); |
556 | parse_device_mapping(dev_priv, bdb); | ||
420 | parse_driver_features(dev_priv, bdb); | 557 | parse_driver_features(dev_priv, bdb); |
558 | parse_edp(dev_priv, bdb); | ||
421 | 559 | ||
422 | pci_unmap_rom(pdev, bios); | 560 | pci_unmap_rom(pdev, bios); |
423 | 561 | ||