aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_dp_mst.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp_mst.c')
-rw-r--r--drivers/gpu/drm/i915/intel_dp_mst.c67
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
33static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, 33static 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
110static int intel_dp_mst_atomic_check(struct drm_connector *connector, 114static int
111 struct drm_connector_state *new_conn_state) 115intel_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,