diff options
| -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; |
