diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 123 |
1 files changed, 98 insertions, 25 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 71860f8680f9..beb0374a19f1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -116,6 +116,7 @@ static void skylake_pfit_enable(struct intel_crtc *crtc); | |||
116 | static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force); | 116 | static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force); |
117 | static void ironlake_pfit_enable(struct intel_crtc *crtc); | 117 | static void ironlake_pfit_enable(struct intel_crtc *crtc); |
118 | static void intel_modeset_setup_hw_state(struct drm_device *dev); | 118 | static void intel_modeset_setup_hw_state(struct drm_device *dev); |
119 | static void intel_pre_disable_primary(struct drm_crtc *crtc); | ||
119 | 120 | ||
120 | typedef struct { | 121 | typedef struct { |
121 | int min, max; | 122 | int min, max; |
@@ -2607,6 +2608,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, | |||
2607 | struct drm_i915_gem_object *obj; | 2608 | struct drm_i915_gem_object *obj; |
2608 | struct drm_plane *primary = intel_crtc->base.primary; | 2609 | struct drm_plane *primary = intel_crtc->base.primary; |
2609 | struct drm_plane_state *plane_state = primary->state; | 2610 | struct drm_plane_state *plane_state = primary->state; |
2611 | struct drm_crtc_state *crtc_state = intel_crtc->base.state; | ||
2612 | struct intel_plane *intel_plane = to_intel_plane(primary); | ||
2610 | struct drm_framebuffer *fb; | 2613 | struct drm_framebuffer *fb; |
2611 | 2614 | ||
2612 | if (!plane_config->fb) | 2615 | if (!plane_config->fb) |
@@ -2643,6 +2646,18 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, | |||
2643 | } | 2646 | } |
2644 | } | 2647 | } |
2645 | 2648 | ||
2649 | /* | ||
2650 | * We've failed to reconstruct the BIOS FB. Current display state | ||
2651 | * indicates that the primary plane is visible, but has a NULL FB, | ||
2652 | * which will lead to problems later if we don't fix it up. The | ||
2653 | * simplest solution is to just disable the primary plane now and | ||
2654 | * pretend the BIOS never had it enabled. | ||
2655 | */ | ||
2656 | to_intel_plane_state(plane_state)->visible = false; | ||
2657 | crtc_state->plane_mask &= ~(1 << drm_plane_index(primary)); | ||
2658 | intel_pre_disable_primary(&intel_crtc->base); | ||
2659 | intel_plane->disable_plane(primary, &intel_crtc->base); | ||
2660 | |||
2646 | return; | 2661 | return; |
2647 | 2662 | ||
2648 | valid_fb: | 2663 | valid_fb: |
@@ -5194,11 +5209,31 @@ static enum intel_display_power_domain port_to_power_domain(enum port port) | |||
5194 | case PORT_E: | 5209 | case PORT_E: |
5195 | return POWER_DOMAIN_PORT_DDI_E_2_LANES; | 5210 | return POWER_DOMAIN_PORT_DDI_E_2_LANES; |
5196 | default: | 5211 | default: |
5197 | WARN_ON_ONCE(1); | 5212 | MISSING_CASE(port); |
5198 | return POWER_DOMAIN_PORT_OTHER; | 5213 | return POWER_DOMAIN_PORT_OTHER; |
5199 | } | 5214 | } |
5200 | } | 5215 | } |
5201 | 5216 | ||
5217 | static enum intel_display_power_domain port_to_aux_power_domain(enum port port) | ||
5218 | { | ||
5219 | switch (port) { | ||
5220 | case PORT_A: | ||
5221 | return POWER_DOMAIN_AUX_A; | ||
5222 | case PORT_B: | ||
5223 | return POWER_DOMAIN_AUX_B; | ||
5224 | case PORT_C: | ||
5225 | return POWER_DOMAIN_AUX_C; | ||
5226 | case PORT_D: | ||
5227 | return POWER_DOMAIN_AUX_D; | ||
5228 | case PORT_E: | ||
5229 | /* FIXME: Check VBT for actual wiring of PORT E */ | ||
5230 | return POWER_DOMAIN_AUX_D; | ||
5231 | default: | ||
5232 | MISSING_CASE(port); | ||
5233 | return POWER_DOMAIN_AUX_A; | ||
5234 | } | ||
5235 | } | ||
5236 | |||
5202 | #define for_each_power_domain(domain, mask) \ | 5237 | #define for_each_power_domain(domain, mask) \ |
5203 | for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \ | 5238 | for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \ |
5204 | if ((1 << (domain)) & (mask)) | 5239 | if ((1 << (domain)) & (mask)) |
@@ -5230,6 +5265,36 @@ intel_display_port_power_domain(struct intel_encoder *intel_encoder) | |||
5230 | } | 5265 | } |
5231 | } | 5266 | } |
5232 | 5267 | ||
5268 | enum intel_display_power_domain | ||
5269 | intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder) | ||
5270 | { | ||
5271 | struct drm_device *dev = intel_encoder->base.dev; | ||
5272 | struct intel_digital_port *intel_dig_port; | ||
5273 | |||
5274 | switch (intel_encoder->type) { | ||
5275 | case INTEL_OUTPUT_UNKNOWN: | ||
5276 | case INTEL_OUTPUT_HDMI: | ||
5277 | /* | ||
5278 | * Only DDI platforms should ever use these output types. | ||
5279 | * We can get here after the HDMI detect code has already set | ||
5280 | * the type of the shared encoder. Since we can't be sure | ||
5281 | * what's the status of the given connectors, play safe and | ||
5282 | * run the DP detection too. | ||
5283 | */ | ||
5284 | WARN_ON_ONCE(!HAS_DDI(dev)); | ||
5285 | case INTEL_OUTPUT_DISPLAYPORT: | ||
5286 | case INTEL_OUTPUT_EDP: | ||
5287 | intel_dig_port = enc_to_dig_port(&intel_encoder->base); | ||
5288 | return port_to_aux_power_domain(intel_dig_port->port); | ||
5289 | case INTEL_OUTPUT_DP_MST: | ||
5290 | intel_dig_port = enc_to_mst(&intel_encoder->base)->primary; | ||
5291 | return port_to_aux_power_domain(intel_dig_port->port); | ||
5292 | default: | ||
5293 | MISSING_CASE(intel_encoder->type); | ||
5294 | return POWER_DOMAIN_AUX_A; | ||
5295 | } | ||
5296 | } | ||
5297 | |||
5233 | static unsigned long get_crtc_power_domains(struct drm_crtc *crtc) | 5298 | static unsigned long get_crtc_power_domains(struct drm_crtc *crtc) |
5234 | { | 5299 | { |
5235 | struct drm_device *dev = crtc->dev; | 5300 | struct drm_device *dev = crtc->dev; |
@@ -6259,9 +6324,11 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) | |||
6259 | if (to_intel_plane_state(crtc->primary->state)->visible) { | 6324 | if (to_intel_plane_state(crtc->primary->state)->visible) { |
6260 | intel_crtc_wait_for_pending_flips(crtc); | 6325 | intel_crtc_wait_for_pending_flips(crtc); |
6261 | intel_pre_disable_primary(crtc); | 6326 | intel_pre_disable_primary(crtc); |
6327 | |||
6328 | intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary)); | ||
6329 | to_intel_plane_state(crtc->primary->state)->visible = false; | ||
6262 | } | 6330 | } |
6263 | 6331 | ||
6264 | intel_crtc_disable_planes(crtc, crtc->state->plane_mask); | ||
6265 | dev_priv->display.crtc_disable(crtc); | 6332 | dev_priv->display.crtc_disable(crtc); |
6266 | intel_crtc->active = false; | 6333 | intel_crtc->active = false; |
6267 | intel_update_watermarks(crtc); | 6334 | intel_update_watermarks(crtc); |
@@ -9858,14 +9925,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, | |||
9858 | return true; | 9925 | return true; |
9859 | } | 9926 | } |
9860 | 9927 | ||
9861 | static void i845_update_cursor(struct drm_crtc *crtc, u32 base) | 9928 | static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on) |
9862 | { | 9929 | { |
9863 | struct drm_device *dev = crtc->dev; | 9930 | struct drm_device *dev = crtc->dev; |
9864 | struct drm_i915_private *dev_priv = dev->dev_private; | 9931 | struct drm_i915_private *dev_priv = dev->dev_private; |
9865 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 9932 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
9866 | uint32_t cntl = 0, size = 0; | 9933 | uint32_t cntl = 0, size = 0; |
9867 | 9934 | ||
9868 | if (base) { | 9935 | if (on) { |
9869 | unsigned int width = intel_crtc->base.cursor->state->crtc_w; | 9936 | unsigned int width = intel_crtc->base.cursor->state->crtc_w; |
9870 | unsigned int height = intel_crtc->base.cursor->state->crtc_h; | 9937 | unsigned int height = intel_crtc->base.cursor->state->crtc_h; |
9871 | unsigned int stride = roundup_pow_of_two(width) * 4; | 9938 | unsigned int stride = roundup_pow_of_two(width) * 4; |
@@ -9920,16 +9987,15 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base) | |||
9920 | } | 9987 | } |
9921 | } | 9988 | } |
9922 | 9989 | ||
9923 | static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) | 9990 | static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on) |
9924 | { | 9991 | { |
9925 | struct drm_device *dev = crtc->dev; | 9992 | struct drm_device *dev = crtc->dev; |
9926 | struct drm_i915_private *dev_priv = dev->dev_private; | 9993 | struct drm_i915_private *dev_priv = dev->dev_private; |
9927 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 9994 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
9928 | int pipe = intel_crtc->pipe; | 9995 | int pipe = intel_crtc->pipe; |
9929 | uint32_t cntl; | 9996 | uint32_t cntl = 0; |
9930 | 9997 | ||
9931 | cntl = 0; | 9998 | if (on) { |
9932 | if (base) { | ||
9933 | cntl = MCURSOR_GAMMA_ENABLE; | 9999 | cntl = MCURSOR_GAMMA_ENABLE; |
9934 | switch (intel_crtc->base.cursor->state->crtc_w) { | 10000 | switch (intel_crtc->base.cursor->state->crtc_w) { |
9935 | case 64: | 10001 | case 64: |
@@ -9980,18 +10046,17 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, | |||
9980 | int y = cursor_state->crtc_y; | 10046 | int y = cursor_state->crtc_y; |
9981 | u32 base = 0, pos = 0; | 10047 | u32 base = 0, pos = 0; |
9982 | 10048 | ||
9983 | if (on) | 10049 | base = intel_crtc->cursor_addr; |
9984 | base = intel_crtc->cursor_addr; | ||
9985 | 10050 | ||
9986 | if (x >= intel_crtc->config->pipe_src_w) | 10051 | if (x >= intel_crtc->config->pipe_src_w) |
9987 | base = 0; | 10052 | on = false; |
9988 | 10053 | ||
9989 | if (y >= intel_crtc->config->pipe_src_h) | 10054 | if (y >= intel_crtc->config->pipe_src_h) |
9990 | base = 0; | 10055 | on = false; |
9991 | 10056 | ||
9992 | if (x < 0) { | 10057 | if (x < 0) { |
9993 | if (x + cursor_state->crtc_w <= 0) | 10058 | if (x + cursor_state->crtc_w <= 0) |
9994 | base = 0; | 10059 | on = false; |
9995 | 10060 | ||
9996 | pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; | 10061 | pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; |
9997 | x = -x; | 10062 | x = -x; |
@@ -10000,16 +10065,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, | |||
10000 | 10065 | ||
10001 | if (y < 0) { | 10066 | if (y < 0) { |
10002 | if (y + cursor_state->crtc_h <= 0) | 10067 | if (y + cursor_state->crtc_h <= 0) |
10003 | base = 0; | 10068 | on = false; |
10004 | 10069 | ||
10005 | pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; | 10070 | pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; |
10006 | y = -y; | 10071 | y = -y; |
10007 | } | 10072 | } |
10008 | pos |= y << CURSOR_Y_SHIFT; | 10073 | pos |= y << CURSOR_Y_SHIFT; |
10009 | 10074 | ||
10010 | if (base == 0 && intel_crtc->cursor_base == 0) | ||
10011 | return; | ||
10012 | |||
10013 | I915_WRITE(CURPOS(pipe), pos); | 10075 | I915_WRITE(CURPOS(pipe), pos); |
10014 | 10076 | ||
10015 | /* ILK+ do this automagically */ | 10077 | /* ILK+ do this automagically */ |
@@ -10020,9 +10082,9 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, | |||
10020 | } | 10082 | } |
10021 | 10083 | ||
10022 | if (IS_845G(dev) || IS_I865G(dev)) | 10084 | if (IS_845G(dev) || IS_I865G(dev)) |
10023 | i845_update_cursor(crtc, base); | 10085 | i845_update_cursor(crtc, base, on); |
10024 | else | 10086 | else |
10025 | i9xx_update_cursor(crtc, base); | 10087 | i9xx_update_cursor(crtc, base, on); |
10026 | } | 10088 | } |
10027 | 10089 | ||
10028 | static bool cursor_size_ok(struct drm_device *dev, | 10090 | static bool cursor_size_ok(struct drm_device *dev, |
@@ -12460,7 +12522,6 @@ intel_pipe_config_compare(struct drm_device *dev, | |||
12460 | if (INTEL_INFO(dev)->gen < 8) { | 12522 | if (INTEL_INFO(dev)->gen < 8) { |
12461 | PIPE_CONF_CHECK_M_N(dp_m_n); | 12523 | PIPE_CONF_CHECK_M_N(dp_m_n); |
12462 | 12524 | ||
12463 | PIPE_CONF_CHECK_I(has_drrs); | ||
12464 | if (current_config->has_drrs) | 12525 | if (current_config->has_drrs) |
12465 | PIPE_CONF_CHECK_M_N(dp_m2_n2); | 12526 | PIPE_CONF_CHECK_M_N(dp_m2_n2); |
12466 | } else | 12527 | } else |
@@ -13667,6 +13728,7 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
13667 | struct drm_crtc *crtc = crtc_state->base.crtc; | 13728 | struct drm_crtc *crtc = crtc_state->base.crtc; |
13668 | struct drm_framebuffer *fb = state->base.fb; | 13729 | struct drm_framebuffer *fb = state->base.fb; |
13669 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); | 13730 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); |
13731 | enum pipe pipe = to_intel_plane(plane)->pipe; | ||
13670 | unsigned stride; | 13732 | unsigned stride; |
13671 | int ret; | 13733 | int ret; |
13672 | 13734 | ||
@@ -13700,6 +13762,22 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
13700 | return -EINVAL; | 13762 | return -EINVAL; |
13701 | } | 13763 | } |
13702 | 13764 | ||
13765 | /* | ||
13766 | * There's something wrong with the cursor on CHV pipe C. | ||
13767 | * If it straddles the left edge of the screen then | ||
13768 | * moving it away from the edge or disabling it often | ||
13769 | * results in a pipe underrun, and often that can lead to | ||
13770 | * dead pipe (constant underrun reported, and it scans | ||
13771 | * out just a solid color). To recover from that, the | ||
13772 | * display power well must be turned off and on again. | ||
13773 | * Refuse the put the cursor into that compromised position. | ||
13774 | */ | ||
13775 | if (IS_CHERRYVIEW(plane->dev) && pipe == PIPE_C && | ||
13776 | state->visible && state->base.crtc_x < 0) { | ||
13777 | DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n"); | ||
13778 | return -EINVAL; | ||
13779 | } | ||
13780 | |||
13703 | return 0; | 13781 | return 0; |
13704 | } | 13782 | } |
13705 | 13783 | ||
@@ -13723,9 +13801,6 @@ intel_commit_cursor_plane(struct drm_plane *plane, | |||
13723 | crtc = crtc ? crtc : plane->crtc; | 13801 | crtc = crtc ? crtc : plane->crtc; |
13724 | intel_crtc = to_intel_crtc(crtc); | 13802 | intel_crtc = to_intel_crtc(crtc); |
13725 | 13803 | ||
13726 | if (intel_crtc->cursor_bo == obj) | ||
13727 | goto update; | ||
13728 | |||
13729 | if (!obj) | 13804 | if (!obj) |
13730 | addr = 0; | 13805 | addr = 0; |
13731 | else if (!INTEL_INFO(dev)->cursor_needs_physical) | 13806 | else if (!INTEL_INFO(dev)->cursor_needs_physical) |
@@ -13734,9 +13809,7 @@ intel_commit_cursor_plane(struct drm_plane *plane, | |||
13734 | addr = obj->phys_handle->busaddr; | 13809 | addr = obj->phys_handle->busaddr; |
13735 | 13810 | ||
13736 | intel_crtc->cursor_addr = addr; | 13811 | intel_crtc->cursor_addr = addr; |
13737 | intel_crtc->cursor_bo = obj; | ||
13738 | 13812 | ||
13739 | update: | ||
13740 | if (crtc->state->active) | 13813 | if (crtc->state->active) |
13741 | intel_crtc_update_cursor(crtc, state->visible); | 13814 | intel_crtc_update_cursor(crtc, state->visible); |
13742 | } | 13815 | } |