diff options
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 44 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 16 |
2 files changed, 59 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e48d47ced57b..517a8cc27bec 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -3632,6 +3632,42 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | |||
3632 | I915_READ(pp_div_reg)); | 3632 | I915_READ(pp_div_reg)); |
3633 | } | 3633 | } |
3634 | 3634 | ||
3635 | static struct drm_display_mode * | ||
3636 | intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, | ||
3637 | struct intel_connector *intel_connector, | ||
3638 | struct drm_display_mode *fixed_mode) | ||
3639 | { | ||
3640 | struct drm_connector *connector = &intel_connector->base; | ||
3641 | struct intel_dp *intel_dp = &intel_dig_port->dp; | ||
3642 | struct drm_device *dev = intel_dig_port->base.base.dev; | ||
3643 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
3644 | struct drm_display_mode *downclock_mode = NULL; | ||
3645 | |||
3646 | if (INTEL_INFO(dev)->gen <= 6) { | ||
3647 | DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n"); | ||
3648 | return NULL; | ||
3649 | } | ||
3650 | |||
3651 | if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) { | ||
3652 | DRM_INFO("VBT doesn't support DRRS\n"); | ||
3653 | return NULL; | ||
3654 | } | ||
3655 | |||
3656 | downclock_mode = intel_find_panel_downclock | ||
3657 | (dev, fixed_mode, connector); | ||
3658 | |||
3659 | if (!downclock_mode) { | ||
3660 | DRM_INFO("DRRS not supported\n"); | ||
3661 | return NULL; | ||
3662 | } | ||
3663 | |||
3664 | intel_dp->drrs_state.type = dev_priv->vbt.drrs_type; | ||
3665 | |||
3666 | intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR; | ||
3667 | DRM_INFO("seamless DRRS supported for eDP panel.\n"); | ||
3668 | return downclock_mode; | ||
3669 | } | ||
3670 | |||
3635 | static bool intel_edp_init_connector(struct intel_dp *intel_dp, | 3671 | static bool intel_edp_init_connector(struct intel_dp *intel_dp, |
3636 | struct intel_connector *intel_connector, | 3672 | struct intel_connector *intel_connector, |
3637 | struct edp_power_seq *power_seq) | 3673 | struct edp_power_seq *power_seq) |
@@ -3641,10 +3677,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, | |||
3641 | struct drm_device *dev = intel_dig_port->base.base.dev; | 3677 | struct drm_device *dev = intel_dig_port->base.base.dev; |
3642 | struct drm_i915_private *dev_priv = dev->dev_private; | 3678 | struct drm_i915_private *dev_priv = dev->dev_private; |
3643 | struct drm_display_mode *fixed_mode = NULL; | 3679 | struct drm_display_mode *fixed_mode = NULL; |
3680 | struct drm_display_mode *downclock_mode = NULL; | ||
3644 | bool has_dpcd; | 3681 | bool has_dpcd; |
3645 | struct drm_display_mode *scan; | 3682 | struct drm_display_mode *scan; |
3646 | struct edid *edid; | 3683 | struct edid *edid; |
3647 | 3684 | ||
3685 | intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED; | ||
3686 | |||
3648 | if (!is_edp(intel_dp)) | 3687 | if (!is_edp(intel_dp)) |
3649 | return true; | 3688 | return true; |
3650 | 3689 | ||
@@ -3687,6 +3726,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, | |||
3687 | list_for_each_entry(scan, &connector->probed_modes, head) { | 3726 | list_for_each_entry(scan, &connector->probed_modes, head) { |
3688 | if ((scan->type & DRM_MODE_TYPE_PREFERRED)) { | 3727 | if ((scan->type & DRM_MODE_TYPE_PREFERRED)) { |
3689 | fixed_mode = drm_mode_duplicate(dev, scan); | 3728 | fixed_mode = drm_mode_duplicate(dev, scan); |
3729 | downclock_mode = intel_dp_drrs_init( | ||
3730 | intel_dig_port, | ||
3731 | intel_connector, fixed_mode); | ||
3690 | break; | 3732 | break; |
3691 | } | 3733 | } |
3692 | } | 3734 | } |
@@ -3700,7 +3742,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, | |||
3700 | } | 3742 | } |
3701 | mutex_unlock(&dev->mode_config.mutex); | 3743 | mutex_unlock(&dev->mode_config.mutex); |
3702 | 3744 | ||
3703 | intel_panel_init(&intel_connector->panel, fixed_mode, NULL); | 3745 | intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode); |
3704 | intel_panel_setup_backlight(connector); | 3746 | intel_panel_setup_backlight(connector); |
3705 | 3747 | ||
3706 | return true; | 3748 | return true; |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6b512607b2f5..41038d9b434f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -485,6 +485,17 @@ struct intel_hdmi { | |||
485 | 485 | ||
486 | #define DP_MAX_DOWNSTREAM_PORTS 0x10 | 486 | #define DP_MAX_DOWNSTREAM_PORTS 0x10 |
487 | 487 | ||
488 | /** | ||
489 | * HIGH_RR is the highest eDP panel refresh rate read from EDID | ||
490 | * LOW_RR is the lowest eDP panel refresh rate found from EDID | ||
491 | * parsing for same resolution. | ||
492 | */ | ||
493 | enum edp_drrs_refresh_rate_type { | ||
494 | DRRS_HIGH_RR, | ||
495 | DRRS_LOW_RR, | ||
496 | DRRS_MAX_RR, /* RR count */ | ||
497 | }; | ||
498 | |||
488 | struct intel_dp { | 499 | struct intel_dp { |
489 | uint32_t output_reg; | 500 | uint32_t output_reg; |
490 | uint32_t aux_ch_ctl_reg; | 501 | uint32_t aux_ch_ctl_reg; |
@@ -523,6 +534,11 @@ struct intel_dp { | |||
523 | bool has_aux_irq, | 534 | bool has_aux_irq, |
524 | int send_bytes, | 535 | int send_bytes, |
525 | uint32_t aux_clock_divider); | 536 | uint32_t aux_clock_divider); |
537 | struct { | ||
538 | enum drrs_support_type type; | ||
539 | enum edp_drrs_refresh_rate_type refresh_rate_type; | ||
540 | } drrs_state; | ||
541 | |||
526 | }; | 542 | }; |
527 | 543 | ||
528 | struct intel_digital_port { | 544 | struct intel_digital_port { |