diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp_mst.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp_mst.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index f05427b74e34..5899debe2184 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c | |||
@@ -30,9 +30,9 @@ | |||
30 | #include <drm/drm_crtc_helper.h> | 30 | #include <drm/drm_crtc_helper.h> |
31 | #include <drm/drm_edid.h> | 31 | #include <drm/drm_edid.h> |
32 | 32 | ||
33 | static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, | 33 | static int intel_dp_mst_compute_config(struct intel_encoder *encoder, |
34 | struct intel_crtc_state *pipe_config, | 34 | struct intel_crtc_state *pipe_config, |
35 | struct drm_connector_state *conn_state) | 35 | struct drm_connector_state *conn_state) |
36 | { | 36 | { |
37 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 37 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
38 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); | 38 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); |
@@ -41,15 +41,19 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, | |||
41 | struct drm_connector *connector = conn_state->connector; | 41 | struct drm_connector *connector = conn_state->connector; |
42 | void *port = to_intel_connector(connector)->port; | 42 | void *port = to_intel_connector(connector)->port; |
43 | struct drm_atomic_state *state = pipe_config->base.state; | 43 | struct drm_atomic_state *state = pipe_config->base.state; |
44 | struct drm_crtc *crtc = pipe_config->base.crtc; | ||
45 | struct drm_crtc_state *old_crtc_state = | ||
46 | drm_atomic_get_old_crtc_state(state, crtc); | ||
44 | int bpp; | 47 | int bpp; |
45 | int lane_count, slots = 0; | 48 | int lane_count, slots = |
49 | to_intel_crtc_state(old_crtc_state)->dp_m_n.tu; | ||
46 | const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; | 50 | const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
47 | int mst_pbn; | 51 | int mst_pbn; |
48 | bool constant_n = drm_dp_has_quirk(&intel_dp->desc, | 52 | bool constant_n = drm_dp_has_quirk(&intel_dp->desc, |
49 | DP_DPCD_QUIRK_CONSTANT_N); | 53 | DP_DPCD_QUIRK_CONSTANT_N); |
50 | 54 | ||
51 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) | 55 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) |
52 | return false; | 56 | return -EINVAL; |
53 | 57 | ||
54 | pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; | 58 | pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; |
55 | pipe_config->has_pch_encoder = false; | 59 | pipe_config->has_pch_encoder = false; |
@@ -86,7 +90,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, | |||
86 | if (slots < 0) { | 90 | if (slots < 0) { |
87 | DRM_DEBUG_KMS("failed finding vcpi slots:%d\n", | 91 | DRM_DEBUG_KMS("failed finding vcpi slots:%d\n", |
88 | slots); | 92 | slots); |
89 | return false; | 93 | return slots; |
90 | } | 94 | } |
91 | } | 95 | } |
92 | 96 | ||
@@ -104,38 +108,42 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, | |||
104 | 108 | ||
105 | intel_ddi_compute_min_voltage_level(dev_priv, pipe_config); | 109 | intel_ddi_compute_min_voltage_level(dev_priv, pipe_config); |
106 | 110 | ||
107 | return true; | 111 | return 0; |
108 | } | 112 | } |
109 | 113 | ||
110 | static int intel_dp_mst_atomic_check(struct drm_connector *connector, | 114 | static int |
111 | struct drm_connector_state *new_conn_state) | 115 | intel_dp_mst_atomic_check(struct drm_connector *connector, |
116 | struct drm_connector_state *new_conn_state) | ||
112 | { | 117 | { |
113 | struct drm_atomic_state *state = new_conn_state->state; | 118 | struct drm_atomic_state *state = new_conn_state->state; |
114 | struct drm_connector_state *old_conn_state; | 119 | struct drm_connector_state *old_conn_state = |
115 | struct drm_crtc *old_crtc; | 120 | drm_atomic_get_old_connector_state(state, connector); |
121 | struct intel_connector *intel_connector = | ||
122 | to_intel_connector(connector); | ||
123 | struct drm_crtc *new_crtc = new_conn_state->crtc; | ||
116 | struct drm_crtc_state *crtc_state; | 124 | struct drm_crtc_state *crtc_state; |
117 | int slots, ret = 0; | 125 | struct drm_dp_mst_topology_mgr *mgr; |
118 | 126 | int ret = 0; | |
119 | old_conn_state = drm_atomic_get_old_connector_state(state, connector); | ||
120 | old_crtc = old_conn_state->crtc; | ||
121 | if (!old_crtc) | ||
122 | return ret; | ||
123 | 127 | ||
124 | crtc_state = drm_atomic_get_new_crtc_state(state, old_crtc); | 128 | if (!old_conn_state->crtc) |
125 | slots = to_intel_crtc_state(crtc_state)->dp_m_n.tu; | 129 | return 0; |
126 | if (drm_atomic_crtc_needs_modeset(crtc_state) && slots > 0) { | ||
127 | struct drm_dp_mst_topology_mgr *mgr; | ||
128 | struct drm_encoder *old_encoder; | ||
129 | 130 | ||
130 | old_encoder = old_conn_state->best_encoder; | 131 | /* We only want to free VCPI if this state disables the CRTC on this |
131 | mgr = &enc_to_mst(old_encoder)->primary->dp.mst_mgr; | 132 | * connector |
133 | */ | ||
134 | if (new_crtc) { | ||
135 | crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); | ||
132 | 136 | ||
133 | ret = drm_dp_atomic_release_vcpi_slots(state, mgr, slots); | 137 | if (!crtc_state || |
134 | if (ret) | 138 | !drm_atomic_crtc_needs_modeset(crtc_state) || |
135 | DRM_DEBUG_KMS("failed releasing %d vcpi slots:%d\n", slots, ret); | 139 | crtc_state->enable) |
136 | else | 140 | return 0; |
137 | to_intel_crtc_state(crtc_state)->dp_m_n.tu = 0; | ||
138 | } | 141 | } |
142 | |||
143 | mgr = &enc_to_mst(old_conn_state->best_encoder)->primary->dp.mst_mgr; | ||
144 | ret = drm_dp_atomic_release_vcpi_slots(state, mgr, | ||
145 | intel_connector->port); | ||
146 | |||
139 | return ret; | 147 | return ret; |
140 | } | 148 | } |
141 | 149 | ||
@@ -457,6 +465,7 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo | |||
457 | intel_connector->get_hw_state = intel_dp_mst_get_hw_state; | 465 | intel_connector->get_hw_state = intel_dp_mst_get_hw_state; |
458 | intel_connector->mst_port = intel_dp; | 466 | intel_connector->mst_port = intel_dp; |
459 | intel_connector->port = port; | 467 | intel_connector->port = port; |
468 | drm_dp_mst_get_port_malloc(port); | ||
460 | 469 | ||
461 | connector = &intel_connector->base; | 470 | connector = &intel_connector->base; |
462 | ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, | 471 | ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, |