diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-02-25 12:49:30 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-02-25 12:49:30 -0500 |
commit | c15d8a6499d04e5d2cac07f8120f207bb275f60f (patch) | |
tree | 4cde78329a06fdf07e3d780881481d9ae1d021fb | |
parent | 490213556ad5bc1b46857bce1bc2c6db41d3e63d (diff) | |
parent | e08fb4f6d1dc95eff5b3fc1d0412bcb5afcae7f2 (diff) |
Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
drm/i915: convert DRM_ERROR to DRM_DEBUG in phys object pwrite path
drm/i915: make hw page ioremap use ioremap_wc
drm: edid revision 0 is valid
drm: Correct unbalanced drm_vblank_put() during mode setting.
drm: disable encoders before re-routing them
drm: Fix ordering of bit fields in EDID structure leading huge vsync values.
drm: Fix shifts of EDID vsync offset/width fields.
drm/i915: handle bogus VBT panel timing
drm/i915: remove PLL debugging messages
-rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 76 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 2 | ||||
-rw-r--r-- | include/drm/drm_crtc_helper.h | 1 | ||||
-rw-r--r-- | include/drm/drm_edid.h | 4 |
9 files changed, 97 insertions, 16 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 733028b4d45e..1c3a8c557140 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -452,6 +452,59 @@ static void drm_setup_crtcs(struct drm_device *dev) | |||
452 | kfree(modes); | 452 | kfree(modes); |
453 | kfree(enabled); | 453 | kfree(enabled); |
454 | } | 454 | } |
455 | |||
456 | /** | ||
457 | * drm_encoder_crtc_ok - can a given crtc drive a given encoder? | ||
458 | * @encoder: encoder to test | ||
459 | * @crtc: crtc to test | ||
460 | * | ||
461 | * Return false if @encoder can't be driven by @crtc, true otherwise. | ||
462 | */ | ||
463 | static bool drm_encoder_crtc_ok(struct drm_encoder *encoder, | ||
464 | struct drm_crtc *crtc) | ||
465 | { | ||
466 | struct drm_device *dev; | ||
467 | struct drm_crtc *tmp; | ||
468 | int crtc_mask = 1; | ||
469 | |||
470 | WARN(!crtc, "checking null crtc?"); | ||
471 | |||
472 | dev = crtc->dev; | ||
473 | |||
474 | list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) { | ||
475 | if (tmp == crtc) | ||
476 | break; | ||
477 | crtc_mask <<= 1; | ||
478 | } | ||
479 | |||
480 | if (encoder->possible_crtcs & crtc_mask) | ||
481 | return true; | ||
482 | return false; | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | * Check the CRTC we're going to map each output to vs. its current | ||
487 | * CRTC. If they don't match, we have to disable the output and the CRTC | ||
488 | * since the driver will have to re-route things. | ||
489 | */ | ||
490 | static void | ||
491 | drm_crtc_prepare_encoders(struct drm_device *dev) | ||
492 | { | ||
493 | struct drm_encoder_helper_funcs *encoder_funcs; | ||
494 | struct drm_encoder *encoder; | ||
495 | |||
496 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
497 | encoder_funcs = encoder->helper_private; | ||
498 | /* Disable unused encoders */ | ||
499 | if (encoder->crtc == NULL) | ||
500 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); | ||
501 | /* Disable encoders whose CRTC is about to change */ | ||
502 | if (encoder_funcs->get_crtc && | ||
503 | encoder->crtc != (*encoder_funcs->get_crtc)(encoder)) | ||
504 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); | ||
505 | } | ||
506 | } | ||
507 | |||
455 | /** | 508 | /** |
456 | * drm_crtc_set_mode - set a mode | 509 | * drm_crtc_set_mode - set a mode |
457 | * @crtc: CRTC to program | 510 | * @crtc: CRTC to program |
@@ -547,6 +600,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | |||
547 | encoder_funcs->prepare(encoder); | 600 | encoder_funcs->prepare(encoder); |
548 | } | 601 | } |
549 | 602 | ||
603 | drm_crtc_prepare_encoders(dev); | ||
604 | |||
550 | crtc_funcs->prepare(crtc); | 605 | crtc_funcs->prepare(crtc); |
551 | 606 | ||
552 | /* Set up the DPLL and any encoders state that needs to adjust or depend | 607 | /* Set up the DPLL and any encoders state that needs to adjust or depend |
@@ -617,7 +672,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
617 | struct drm_device *dev; | 672 | struct drm_device *dev; |
618 | struct drm_crtc **save_crtcs, *new_crtc; | 673 | struct drm_crtc **save_crtcs, *new_crtc; |
619 | struct drm_encoder **save_encoders, *new_encoder; | 674 | struct drm_encoder **save_encoders, *new_encoder; |
620 | struct drm_framebuffer *old_fb; | 675 | struct drm_framebuffer *old_fb = NULL; |
621 | bool save_enabled; | 676 | bool save_enabled; |
622 | bool mode_changed = false; | 677 | bool mode_changed = false; |
623 | bool fb_changed = false; | 678 | bool fb_changed = false; |
@@ -668,9 +723,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
668 | * and then just flip_or_move it */ | 723 | * and then just flip_or_move it */ |
669 | if (set->crtc->fb != set->fb) { | 724 | if (set->crtc->fb != set->fb) { |
670 | /* If we have no fb then treat it as a full mode set */ | 725 | /* If we have no fb then treat it as a full mode set */ |
671 | if (set->crtc->fb == NULL) | 726 | if (set->crtc->fb == NULL) { |
727 | DRM_DEBUG("crtc has no fb, full mode set\n"); | ||
672 | mode_changed = true; | 728 | mode_changed = true; |
673 | else if ((set->fb->bits_per_pixel != | 729 | } else if ((set->fb->bits_per_pixel != |
674 | set->crtc->fb->bits_per_pixel) || | 730 | set->crtc->fb->bits_per_pixel) || |
675 | set->fb->depth != set->crtc->fb->depth) | 731 | set->fb->depth != set->crtc->fb->depth) |
676 | fb_changed = true; | 732 | fb_changed = true; |
@@ -682,7 +738,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
682 | fb_changed = true; | 738 | fb_changed = true; |
683 | 739 | ||
684 | if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { | 740 | if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { |
685 | DRM_DEBUG("modes are different\n"); | 741 | DRM_DEBUG("modes are different, full mode set\n"); |
686 | drm_mode_debug_printmodeline(&set->crtc->mode); | 742 | drm_mode_debug_printmodeline(&set->crtc->mode); |
687 | drm_mode_debug_printmodeline(set->mode); | 743 | drm_mode_debug_printmodeline(set->mode); |
688 | mode_changed = true; | 744 | mode_changed = true; |
@@ -708,6 +764,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
708 | } | 764 | } |
709 | 765 | ||
710 | if (new_encoder != connector->encoder) { | 766 | if (new_encoder != connector->encoder) { |
767 | DRM_DEBUG("encoder changed, full mode switch\n"); | ||
711 | mode_changed = true; | 768 | mode_changed = true; |
712 | connector->encoder = new_encoder; | 769 | connector->encoder = new_encoder; |
713 | } | 770 | } |
@@ -734,10 +791,20 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
734 | if (set->connectors[ro] == connector) | 791 | if (set->connectors[ro] == connector) |
735 | new_crtc = set->crtc; | 792 | new_crtc = set->crtc; |
736 | } | 793 | } |
794 | |||
795 | /* Make sure the new CRTC will work with the encoder */ | ||
796 | if (new_crtc && | ||
797 | !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { | ||
798 | ret = -EINVAL; | ||
799 | goto fail_set_mode; | ||
800 | } | ||
737 | if (new_crtc != connector->encoder->crtc) { | 801 | if (new_crtc != connector->encoder->crtc) { |
802 | DRM_DEBUG("crtc changed, full mode switch\n"); | ||
738 | mode_changed = true; | 803 | mode_changed = true; |
739 | connector->encoder->crtc = new_crtc; | 804 | connector->encoder->crtc = new_crtc; |
740 | } | 805 | } |
806 | DRM_DEBUG("setting connector %d crtc to %p\n", | ||
807 | connector->base.id, new_crtc); | ||
741 | } | 808 | } |
742 | 809 | ||
743 | /* mode_set_base is not a required function */ | 810 | /* mode_set_base is not a required function */ |
@@ -781,6 +848,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
781 | 848 | ||
782 | fail_set_mode: | 849 | fail_set_mode: |
783 | set->crtc->enabled = save_enabled; | 850 | set->crtc->enabled = save_enabled; |
851 | set->crtc->fb = old_fb; | ||
784 | count = 0; | 852 | count = 0; |
785 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 853 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
786 | if (!connector->encoder) | 854 | if (!connector->encoder) |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 5a4d3244758a..a839a28d8ee6 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -125,7 +125,7 @@ static bool edid_is_valid(struct edid *edid) | |||
125 | DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); | 125 | DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); |
126 | goto bad; | 126 | goto bad; |
127 | } | 127 | } |
128 | if (edid->revision <= 0 || edid->revision > 3) { | 128 | if (edid->revision > 3) { |
129 | DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision); | 129 | DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision); |
130 | goto bad; | 130 | goto bad; |
131 | } | 131 | } |
@@ -320,10 +320,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
320 | mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo); | 320 | mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo); |
321 | 321 | ||
322 | mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo; | 322 | mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo; |
323 | mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) | | 323 | mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 4) | |
324 | pt->vsync_offset_lo); | 324 | pt->vsync_offset_lo); |
325 | mode->vsync_end = mode->vsync_start + | 325 | mode->vsync_end = mode->vsync_start + |
326 | ((pt->vsync_pulse_width_hi << 8) | | 326 | ((pt->vsync_pulse_width_hi << 4) | |
327 | pt->vsync_pulse_width_lo); | 327 | pt->vsync_pulse_width_lo); |
328 | mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo); | 328 | mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo); |
329 | 329 | ||
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3795dbc0f50c..93e677a481f5 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -435,6 +435,8 @@ EXPORT_SYMBOL(drm_vblank_get); | |||
435 | */ | 435 | */ |
436 | void drm_vblank_put(struct drm_device *dev, int crtc) | 436 | void drm_vblank_put(struct drm_device *dev, int crtc) |
437 | { | 437 | { |
438 | BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0); | ||
439 | |||
438 | /* Last user schedules interrupt disable */ | 440 | /* Last user schedules interrupt disable */ |
439 | if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) | 441 | if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) |
440 | mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); | 442 | mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); |
@@ -460,8 +462,9 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) | |||
460 | * so that interrupts remain enabled in the interim. | 462 | * so that interrupts remain enabled in the interim. |
461 | */ | 463 | */ |
462 | if (!dev->vblank_inmodeset[crtc]) { | 464 | if (!dev->vblank_inmodeset[crtc]) { |
463 | dev->vblank_inmodeset[crtc] = 1; | 465 | dev->vblank_inmodeset[crtc] = 0x1; |
464 | drm_vblank_get(dev, crtc); | 466 | if (drm_vblank_get(dev, crtc) == 0) |
467 | dev->vblank_inmodeset[crtc] |= 0x2; | ||
465 | } | 468 | } |
466 | } | 469 | } |
467 | EXPORT_SYMBOL(drm_vblank_pre_modeset); | 470 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
@@ -473,9 +476,12 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc) | |||
473 | if (dev->vblank_inmodeset[crtc]) { | 476 | if (dev->vblank_inmodeset[crtc]) { |
474 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 477 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
475 | dev->vblank_disable_allowed = 1; | 478 | dev->vblank_disable_allowed = 1; |
476 | dev->vblank_inmodeset[crtc] = 0; | ||
477 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | 479 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
478 | drm_vblank_put(dev, crtc); | 480 | |
481 | if (dev->vblank_inmodeset[crtc] & 0x2) | ||
482 | drm_vblank_put(dev, crtc); | ||
483 | |||
484 | dev->vblank_inmodeset[crtc] = 0; | ||
479 | } | 485 | } |
480 | } | 486 | } |
481 | EXPORT_SYMBOL(drm_vblank_post_modeset); | 487 | EXPORT_SYMBOL(drm_vblank_post_modeset); |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2d797ffe8137..cc4649577a61 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -811,7 +811,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data, | |||
811 | dev_priv->hws_map.flags = 0; | 811 | dev_priv->hws_map.flags = 0; |
812 | dev_priv->hws_map.mtrr = 0; | 812 | dev_priv->hws_map.mtrr = 0; |
813 | 813 | ||
814 | drm_core_ioremap(&dev_priv->hws_map, dev); | 814 | drm_core_ioremap_wc(&dev_priv->hws_map, dev); |
815 | if (dev_priv->hws_map.handle == NULL) { | 815 | if (dev_priv->hws_map.handle == NULL) { |
816 | i915_dma_cleanup(dev); | 816 | i915_dma_cleanup(dev); |
817 | dev_priv->status_gfx_addr = 0; | 817 | dev_priv->status_gfx_addr = 0; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 28b726d07a0c..85685bfd12da 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -3548,7 +3548,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | |||
3548 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 3548 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
3549 | obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; | 3549 | obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; |
3550 | 3550 | ||
3551 | DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size); | 3551 | DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size); |
3552 | ret = copy_from_user(obj_addr, user_data, args->size); | 3552 | ret = copy_from_user(obj_addr, user_data, args->size); |
3553 | if (ret) | 3553 | if (ret) |
3554 | return -EFAULT; | 3554 | return -EFAULT; |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 65be30dccc77..fc28e2bbd542 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -111,6 +111,12 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | |||
111 | panel_fixed_mode->clock = dvo_timing->clock * 10; | 111 | panel_fixed_mode->clock = dvo_timing->clock * 10; |
112 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; | 112 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; |
113 | 113 | ||
114 | /* Some VBTs have bogus h/vtotal values */ | ||
115 | if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) | ||
116 | panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; | ||
117 | if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) | ||
118 | panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; | ||
119 | |||
114 | drm_mode_set_name(panel_fixed_mode); | 120 | drm_mode_set_name(panel_fixed_mode); |
115 | 121 | ||
116 | dev_priv->vbt_mode = panel_fixed_mode; | 122 | dev_priv->vbt_mode = panel_fixed_mode; |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 65b635ce28c8..a2834276cb38 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -217,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type) | |||
217 | return false; | 217 | return false; |
218 | } | 218 | } |
219 | 219 | ||
220 | #define INTELPllInvalid(s) do { DRM_DEBUG(s); return false; } while (0) | 220 | #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) |
221 | /** | 221 | /** |
222 | * Returns whether the given set of divisors are valid for a given refclk with | 222 | * Returns whether the given set of divisors are valid for a given refclk with |
223 | * the given connectors. | 223 | * the given connectors. |
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 0b0d236c2154..c7d4b2e606a5 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h | |||
@@ -76,6 +76,7 @@ struct drm_encoder_helper_funcs { | |||
76 | void (*mode_set)(struct drm_encoder *encoder, | 76 | void (*mode_set)(struct drm_encoder *encoder, |
77 | struct drm_display_mode *mode, | 77 | struct drm_display_mode *mode, |
78 | struct drm_display_mode *adjusted_mode); | 78 | struct drm_display_mode *adjusted_mode); |
79 | struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder); | ||
79 | /* detect for DAC style encoders */ | 80 | /* detect for DAC style encoders */ |
80 | enum drm_connector_status (*detect)(struct drm_encoder *encoder, | 81 | enum drm_connector_status (*detect)(struct drm_encoder *encoder, |
81 | struct drm_connector *connector); | 82 | struct drm_connector *connector); |
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index c707c15f5164..ff8d27af4786 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h | |||
@@ -58,10 +58,10 @@ struct detailed_pixel_timing { | |||
58 | u8 hsync_pulse_width_lo; | 58 | u8 hsync_pulse_width_lo; |
59 | u8 vsync_pulse_width_lo:4; | 59 | u8 vsync_pulse_width_lo:4; |
60 | u8 vsync_offset_lo:4; | 60 | u8 vsync_offset_lo:4; |
61 | u8 hsync_pulse_width_hi:2; | ||
62 | u8 hsync_offset_hi:2; | ||
63 | u8 vsync_pulse_width_hi:2; | 61 | u8 vsync_pulse_width_hi:2; |
64 | u8 vsync_offset_hi:2; | 62 | u8 vsync_offset_hi:2; |
63 | u8 hsync_pulse_width_hi:2; | ||
64 | u8 hsync_offset_hi:2; | ||
65 | u8 width_mm_lo; | 65 | u8 width_mm_lo; |
66 | u8 height_mm_lo; | 66 | u8 height_mm_lo; |
67 | u8 height_mm_hi:4; | 67 | u8 height_mm_hi:4; |