aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>2015-07-14 06:17:40 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-07-14 08:00:54 -0400
commitcfb23ed622d040619abb91e625fcba74d356b8a8 (patch)
tree237d0b1a1f251c8a1193f3d590a32119baafaa41 /drivers/gpu/drm/i915/intel_display.c
parent8e9ba31a0f6c217e05f84efe9c569f9010a8ad26 (diff)
drm/i915: Allow fuzzy matching in pipe_config_compare, v2.
Instead of doing ad-hoc checks we already have a way of checking if the state is compatible or not. Use this to force a modeset. Only during modesets, or with PIPE_CONFIG_QUIRK_INHERITED_MODE we should check if a full modeset is really needed. Fastboot will allow the adjust parameter to ignore some stuff too, and it will fix up differences in state that are ignored by the compare function. Changes since v1: - Increase the value of the lowest m/n to prevent truncation. - Dump pipe config when fastboot's used, without a modeset. - Add adjust parameter to intel_compare_link_m_n, which is used to adjust m2_n2 if it's a multiple of m_n. - Add exact parameter intel_compare_m_n. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Daniel Stone <daniels@collabora.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c218
1 files changed, 157 insertions, 61 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 99897b152091..541d2a841279 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12288,19 +12288,6 @@ encoder_retry:
12288 DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n", 12288 DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n",
12289 base_bpp, pipe_config->pipe_bpp, pipe_config->dither); 12289 base_bpp, pipe_config->pipe_bpp, pipe_config->dither);
12290 12290
12291 /* Check if we need to force a modeset */
12292 if (pipe_config->has_audio !=
12293 to_intel_crtc_state(crtc->state)->has_audio) {
12294 pipe_config->base.mode_changed = true;
12295 ret = drm_atomic_add_affected_planes(state, crtc);
12296 }
12297
12298 /*
12299 * Note we have an issue here with infoframes: current code
12300 * only updates them on the full mode set path per hw
12301 * requirements. So here we should be checking for any
12302 * required changes and forcing a mode set.
12303 */
12304fail: 12291fail:
12305 return ret; 12292 return ret;
12306} 12293}
@@ -12404,27 +12391,133 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2)
12404 base.head) \ 12391 base.head) \
12405 if (mask & (1 <<(intel_crtc)->pipe)) 12392 if (mask & (1 <<(intel_crtc)->pipe))
12406 12393
12394
12395static bool
12396intel_compare_m_n(unsigned int m, unsigned int n,
12397 unsigned int m2, unsigned int n2,
12398 bool exact)
12399{
12400 if (m == m2 && n == n2)
12401 return true;
12402
12403 if (exact || !m || !n || !m2 || !n2)
12404 return false;
12405
12406 BUILD_BUG_ON(DATA_LINK_M_N_MASK > INT_MAX);
12407
12408 if (m > m2) {
12409 while (m > m2) {
12410 m2 <<= 1;
12411 n2 <<= 1;
12412 }
12413 } else if (m < m2) {
12414 while (m < m2) {
12415 m <<= 1;
12416 n <<= 1;
12417 }
12418 }
12419
12420 return m == m2 && n == n2;
12421}
12422
12423static bool
12424intel_compare_link_m_n(const struct intel_link_m_n *m_n,
12425 struct intel_link_m_n *m2_n2,
12426 bool adjust)
12427{
12428 if (m_n->tu == m2_n2->tu &&
12429 intel_compare_m_n(m_n->gmch_m, m_n->gmch_n,
12430 m2_n2->gmch_m, m2_n2->gmch_n, !adjust) &&
12431 intel_compare_m_n(m_n->link_m, m_n->link_n,
12432 m2_n2->link_m, m2_n2->link_n, !adjust)) {
12433 if (adjust)
12434 *m2_n2 = *m_n;
12435
12436 return true;
12437 }
12438
12439 return false;
12440}
12441
12407static bool 12442static bool
12408intel_pipe_config_compare(struct drm_device *dev, 12443intel_pipe_config_compare(struct drm_device *dev,
12409 struct intel_crtc_state *current_config, 12444 struct intel_crtc_state *current_config,
12410 struct intel_crtc_state *pipe_config) 12445 struct intel_crtc_state *pipe_config,
12446 bool adjust)
12411{ 12447{
12448 bool ret = true;
12449
12450#define INTEL_ERR_OR_DBG_KMS(fmt, ...) \
12451 do { \
12452 if (!adjust) \
12453 DRM_ERROR(fmt, ##__VA_ARGS__); \
12454 else \
12455 DRM_DEBUG_KMS(fmt, ##__VA_ARGS__); \
12456 } while (0)
12457
12412#define PIPE_CONF_CHECK_X(name) \ 12458#define PIPE_CONF_CHECK_X(name) \
12413 if (current_config->name != pipe_config->name) { \ 12459 if (current_config->name != pipe_config->name) { \
12414 DRM_ERROR("mismatch in " #name " " \ 12460 INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
12415 "(expected 0x%08x, found 0x%08x)\n", \ 12461 "(expected 0x%08x, found 0x%08x)\n", \
12416 current_config->name, \ 12462 current_config->name, \
12417 pipe_config->name); \ 12463 pipe_config->name); \
12418 return false; \ 12464 ret = false; \
12419 } 12465 }
12420 12466
12421#define PIPE_CONF_CHECK_I(name) \ 12467#define PIPE_CONF_CHECK_I(name) \
12422 if (current_config->name != pipe_config->name) { \ 12468 if (current_config->name != pipe_config->name) { \
12423 DRM_ERROR("mismatch in " #name " " \ 12469 INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
12424 "(expected %i, found %i)\n", \ 12470 "(expected %i, found %i)\n", \
12425 current_config->name, \ 12471 current_config->name, \
12426 pipe_config->name); \ 12472 pipe_config->name); \
12427 return false; \ 12473 ret = false; \
12474 }
12475
12476#define PIPE_CONF_CHECK_M_N(name) \
12477 if (!intel_compare_link_m_n(&current_config->name, \
12478 &pipe_config->name,\
12479 adjust)) { \
12480 INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
12481 "(expected tu %i gmch %i/%i link %i/%i, " \
12482 "found tu %i, gmch %i/%i link %i/%i)\n", \
12483 current_config->name.tu, \
12484 current_config->name.gmch_m, \
12485 current_config->name.gmch_n, \
12486 current_config->name.link_m, \
12487 current_config->name.link_n, \
12488 pipe_config->name.tu, \
12489 pipe_config->name.gmch_m, \
12490 pipe_config->name.gmch_n, \
12491 pipe_config->name.link_m, \
12492 pipe_config->name.link_n); \
12493 ret = false; \
12494 }
12495
12496#define PIPE_CONF_CHECK_M_N_ALT(name, alt_name) \
12497 if (!intel_compare_link_m_n(&current_config->name, \
12498 &pipe_config->name, adjust) && \
12499 !intel_compare_link_m_n(&current_config->alt_name, \
12500 &pipe_config->name, adjust)) { \
12501 INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
12502 "(expected tu %i gmch %i/%i link %i/%i, " \
12503 "or tu %i gmch %i/%i link %i/%i, " \
12504 "found tu %i, gmch %i/%i link %i/%i)\n", \
12505 current_config->name.tu, \
12506 current_config->name.gmch_m, \
12507 current_config->name.gmch_n, \
12508 current_config->name.link_m, \
12509 current_config->name.link_n, \
12510 current_config->alt_name.tu, \
12511 current_config->alt_name.gmch_m, \
12512 current_config->alt_name.gmch_n, \
12513 current_config->alt_name.link_m, \
12514 current_config->alt_name.link_n, \
12515 pipe_config->name.tu, \
12516 pipe_config->name.gmch_m, \
12517 pipe_config->name.gmch_n, \
12518 pipe_config->name.link_m, \
12519 pipe_config->name.link_n); \
12520 ret = false; \
12428 } 12521 }
12429 12522
12430/* This is required for BDW+ where there is only one set of registers for 12523/* This is required for BDW+ where there is only one set of registers for
@@ -12435,30 +12528,30 @@ intel_pipe_config_compare(struct drm_device *dev,
12435#define PIPE_CONF_CHECK_I_ALT(name, alt_name) \ 12528#define PIPE_CONF_CHECK_I_ALT(name, alt_name) \
12436 if ((current_config->name != pipe_config->name) && \ 12529 if ((current_config->name != pipe_config->name) && \
12437 (current_config->alt_name != pipe_config->name)) { \ 12530 (current_config->alt_name != pipe_config->name)) { \
12438 DRM_ERROR("mismatch in " #name " " \ 12531 INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
12439 "(expected %i or %i, found %i)\n", \ 12532 "(expected %i or %i, found %i)\n", \
12440 current_config->name, \ 12533 current_config->name, \
12441 current_config->alt_name, \ 12534 current_config->alt_name, \
12442 pipe_config->name); \ 12535 pipe_config->name); \
12443 return false; \ 12536 ret = false; \
12444 } 12537 }
12445 12538
12446#define PIPE_CONF_CHECK_FLAGS(name, mask) \ 12539#define PIPE_CONF_CHECK_FLAGS(name, mask) \
12447 if ((current_config->name ^ pipe_config->name) & (mask)) { \ 12540 if ((current_config->name ^ pipe_config->name) & (mask)) { \
12448 DRM_ERROR("mismatch in " #name "(" #mask ") " \ 12541 INTEL_ERR_OR_DBG_KMS("mismatch in " #name "(" #mask ") " \
12449 "(expected %i, found %i)\n", \ 12542 "(expected %i, found %i)\n", \
12450 current_config->name & (mask), \ 12543 current_config->name & (mask), \
12451 pipe_config->name & (mask)); \ 12544 pipe_config->name & (mask)); \
12452 return false; \ 12545 ret = false; \
12453 } 12546 }
12454 12547
12455#define PIPE_CONF_CHECK_CLOCK_FUZZY(name) \ 12548#define PIPE_CONF_CHECK_CLOCK_FUZZY(name) \
12456 if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) { \ 12549 if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) { \
12457 DRM_ERROR("mismatch in " #name " " \ 12550 INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
12458 "(expected %i, found %i)\n", \ 12551 "(expected %i, found %i)\n", \
12459 current_config->name, \ 12552 current_config->name, \
12460 pipe_config->name); \ 12553 pipe_config->name); \
12461 return false; \ 12554 ret = false; \
12462 } 12555 }
12463 12556
12464#define PIPE_CONF_QUIRK(quirk) \ 12557#define PIPE_CONF_QUIRK(quirk) \
@@ -12468,35 +12561,18 @@ intel_pipe_config_compare(struct drm_device *dev,
12468 12561
12469 PIPE_CONF_CHECK_I(has_pch_encoder); 12562 PIPE_CONF_CHECK_I(has_pch_encoder);
12470 PIPE_CONF_CHECK_I(fdi_lanes); 12563 PIPE_CONF_CHECK_I(fdi_lanes);
12471 PIPE_CONF_CHECK_I(fdi_m_n.gmch_m); 12564 PIPE_CONF_CHECK_M_N(fdi_m_n);
12472 PIPE_CONF_CHECK_I(fdi_m_n.gmch_n);
12473 PIPE_CONF_CHECK_I(fdi_m_n.link_m);
12474 PIPE_CONF_CHECK_I(fdi_m_n.link_n);
12475 PIPE_CONF_CHECK_I(fdi_m_n.tu);
12476 12565
12477 PIPE_CONF_CHECK_I(has_dp_encoder); 12566 PIPE_CONF_CHECK_I(has_dp_encoder);
12478 12567
12479 if (INTEL_INFO(dev)->gen < 8) { 12568 if (INTEL_INFO(dev)->gen < 8) {
12480 PIPE_CONF_CHECK_I(dp_m_n.gmch_m); 12569 PIPE_CONF_CHECK_M_N(dp_m_n);
12481 PIPE_CONF_CHECK_I(dp_m_n.gmch_n); 12570
12482 PIPE_CONF_CHECK_I(dp_m_n.link_m); 12571 PIPE_CONF_CHECK_I(has_drrs);
12483 PIPE_CONF_CHECK_I(dp_m_n.link_n); 12572 if (current_config->has_drrs)
12484 PIPE_CONF_CHECK_I(dp_m_n.tu); 12573 PIPE_CONF_CHECK_M_N(dp_m2_n2);
12485 12574 } else
12486 if (current_config->has_drrs) { 12575 PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2);
12487 PIPE_CONF_CHECK_I(dp_m2_n2.gmch_m);
12488 PIPE_CONF_CHECK_I(dp_m2_n2.gmch_n);
12489 PIPE_CONF_CHECK_I(dp_m2_n2.link_m);
12490 PIPE_CONF_CHECK_I(dp_m2_n2.link_n);
12491 PIPE_CONF_CHECK_I(dp_m2_n2.tu);
12492 }
12493 } else {
12494 PIPE_CONF_CHECK_I_ALT(dp_m_n.gmch_m, dp_m2_n2.gmch_m);
12495 PIPE_CONF_CHECK_I_ALT(dp_m_n.gmch_n, dp_m2_n2.gmch_n);
12496 PIPE_CONF_CHECK_I_ALT(dp_m_n.link_m, dp_m2_n2.link_m);
12497 PIPE_CONF_CHECK_I_ALT(dp_m_n.link_n, dp_m2_n2.link_n);
12498 PIPE_CONF_CHECK_I_ALT(dp_m_n.tu, dp_m2_n2.tu);
12499 }
12500 12576
12501 PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hdisplay); 12577 PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hdisplay);
12502 PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_htotal); 12578 PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_htotal);
@@ -12592,8 +12668,9 @@ intel_pipe_config_compare(struct drm_device *dev,
12592#undef PIPE_CONF_CHECK_FLAGS 12668#undef PIPE_CONF_CHECK_FLAGS
12593#undef PIPE_CONF_CHECK_CLOCK_FUZZY 12669#undef PIPE_CONF_CHECK_CLOCK_FUZZY
12594#undef PIPE_CONF_QUIRK 12670#undef PIPE_CONF_QUIRK
12671#undef INTEL_ERR_OR_DBG_KMS
12595 12672
12596 return true; 12673 return ret;
12597} 12674}
12598 12675
12599static void check_wm_state(struct drm_device *dev) 12676static void check_wm_state(struct drm_device *dev)
@@ -12785,8 +12862,11 @@ check_crtc_state(struct drm_device *dev)
12785 "transitional active state does not match atomic hw state " 12862 "transitional active state does not match atomic hw state "
12786 "(expected %i, found %i)\n", crtc->base.state->active, crtc->active); 12863 "(expected %i, found %i)\n", crtc->base.state->active, crtc->active);
12787 12864
12788 if (active && 12865 if (!active)
12789 !intel_pipe_config_compare(dev, crtc->config, &pipe_config)) { 12866 continue;
12867
12868 if (!intel_pipe_config_compare(dev, crtc->config,
12869 &pipe_config, false)) {
12790 I915_STATE_WARN(1, "pipe state doesn't match!\n"); 12870 I915_STATE_WARN(1, "pipe state doesn't match!\n");
12791 intel_dump_pipe_config(crtc, &pipe_config, 12871 intel_dump_pipe_config(crtc, &pipe_config,
12792 "[hw state]"); 12872 "[hw state]");
@@ -13087,14 +13167,17 @@ intel_modeset_compute_config(struct drm_atomic_state *state)
13087 return ret; 13167 return ret;
13088 13168
13089 for_each_crtc_in_state(state, crtc, crtc_state, i) { 13169 for_each_crtc_in_state(state, crtc, crtc_state, i) {
13170 struct intel_crtc_state *pipe_config =
13171 to_intel_crtc_state(crtc_state);
13172 bool modeset, recalc;
13173
13090 if (!crtc_state->enable) { 13174 if (!crtc_state->enable) {
13091 if (needs_modeset(crtc_state)) 13175 if (needs_modeset(crtc_state))
13092 any_ms = true; 13176 any_ms = true;
13093 continue; 13177 continue;
13094 } 13178 }
13095 13179
13096 if (to_intel_crtc_state(crtc_state)->quirks & 13180 if (pipe_config->quirks & PIPE_CONFIG_QUIRK_INITIAL_PLANES) {
13097 PIPE_CONFIG_QUIRK_INITIAL_PLANES) {
13098 ret = drm_atomic_add_affected_planes(state, crtc); 13181 ret = drm_atomic_add_affected_planes(state, crtc);
13099 if (ret) 13182 if (ret)
13100 return ret; 13183 return ret;
@@ -13107,23 +13190,36 @@ intel_modeset_compute_config(struct drm_atomic_state *state)
13107 */ 13190 */
13108 } 13191 }
13109 13192
13110 if (!needs_modeset(crtc_state)) { 13193 modeset = needs_modeset(crtc_state);
13194 recalc = pipe_config->quirks & PIPE_CONFIG_QUIRK_INHERITED_MODE;
13195
13196 if (!modeset && !recalc)
13197 continue;
13198
13199 if (recalc) {
13111 ret = drm_atomic_add_affected_connectors(state, crtc); 13200 ret = drm_atomic_add_affected_connectors(state, crtc);
13112 if (ret) 13201 if (ret)
13113 return ret; 13202 return ret;
13114 } 13203 }
13115 13204
13116 ret = intel_modeset_pipe_config(crtc, 13205 ret = intel_modeset_pipe_config(crtc, pipe_config);
13117 to_intel_crtc_state(crtc_state));
13118 if (ret) 13206 if (ret)
13119 return ret; 13207 return ret;
13120 13208
13121 if (needs_modeset(crtc_state)) 13209 if (recalc && !intel_pipe_config_compare(state->dev,
13122 any_ms = true; 13210 to_intel_crtc_state(crtc->state),
13211 pipe_config, true)) {
13212 modeset = crtc_state->mode_changed = true;
13213
13214 ret = drm_atomic_add_affected_planes(state, crtc);
13215 if (ret)
13216 return ret;
13217 }
13123 13218
13219 any_ms = modeset;
13124 intel_dump_pipe_config(to_intel_crtc(crtc), 13220 intel_dump_pipe_config(to_intel_crtc(crtc),
13125 to_intel_crtc_state(crtc_state), 13221 pipe_config,
13126 "[modeset]"); 13222 modeset ? "[modeset]" : "[fastboot]");
13127 } 13223 }
13128 13224
13129 if (any_ms) { 13225 if (any_ms) {