aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h6
-rw-r--r--drivers/gpu/drm/nouveau/nv50_crtc.c31
-rw-r--r--drivers/gpu/drm/nouveau/nv50_dac.c17
-rw-r--r--drivers/gpu/drm/nouveau/nv50_sor.c32
4 files changed, 41 insertions, 45 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index e4442e28b568..a1a0d48ae70c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -38,13 +38,15 @@ struct nouveau_encoder {
38 struct dcb_entry *dcb; 38 struct dcb_entry *dcb;
39 int or; 39 int or;
40 40
41 /* different to drm_encoder.crtc, this reflects what's
42 * actually programmed on the hw, not the proposed crtc */
43 struct drm_crtc *crtc;
44
41 struct drm_display_mode mode; 45 struct drm_display_mode mode;
42 int last_dpms; 46 int last_dpms;
43 47
44 struct nv04_output_reg restore; 48 struct nv04_output_reg restore;
45 49
46 void (*disconnect)(struct nouveau_encoder *encoder);
47
48 union { 50 union {
49 struct { 51 struct {
50 int mc_unknown; 52 int mc_unknown;
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index b4e4a3b05eae..fb3ed5d80aa6 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -440,40 +440,9 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
440{ 440{
441 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 441 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
442 struct drm_device *dev = crtc->dev; 442 struct drm_device *dev = crtc->dev;
443 struct drm_encoder *encoder;
444 uint32_t dac = 0, sor = 0;
445 443
446 NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); 444 NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
447 445
448 /* Disconnect all unused encoders. */
449 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
450 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
451
452 if (!drm_helper_encoder_in_use(encoder))
453 continue;
454
455 if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
456 nv_encoder->dcb->type == OUTPUT_TV)
457 dac |= (1 << nv_encoder->or);
458 else
459 sor |= (1 << nv_encoder->or);
460 }
461
462 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
463 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
464
465 if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
466 nv_encoder->dcb->type == OUTPUT_TV) {
467 if (dac & (1 << nv_encoder->or))
468 continue;
469 } else {
470 if (sor & (1 << nv_encoder->or))
471 continue;
472 }
473
474 nv_encoder->disconnect(nv_encoder);
475 }
476
477 nv50_crtc_blank(nv_crtc, true); 446 nv50_crtc_blank(nv_crtc, true);
478} 447}
479 448
diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c
index e114f818751d..f5fd35a657c3 100644
--- a/drivers/gpu/drm/nouveau/nv50_dac.c
+++ b/drivers/gpu/drm/nouveau/nv50_dac.c
@@ -37,13 +37,17 @@
37#include "nv50_display.h" 37#include "nv50_display.h"
38 38
39static void 39static void
40nv50_dac_disconnect(struct nouveau_encoder *nv_encoder) 40nv50_dac_disconnect(struct drm_encoder *encoder)
41{ 41{
42 struct drm_device *dev = to_drm_encoder(nv_encoder)->dev; 42 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
43 struct drm_device *dev = encoder->dev;
43 struct drm_nouveau_private *dev_priv = dev->dev_private; 44 struct drm_nouveau_private *dev_priv = dev->dev_private;
44 struct nouveau_channel *evo = dev_priv->evo; 45 struct nouveau_channel *evo = dev_priv->evo;
45 int ret; 46 int ret;
46 47
48 if (!nv_encoder->crtc)
49 return;
50
47 NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or); 51 NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or);
48 52
49 ret = RING_SPACE(evo, 2); 53 ret = RING_SPACE(evo, 2);
@@ -53,6 +57,8 @@ nv50_dac_disconnect(struct nouveau_encoder *nv_encoder)
53 } 57 }
54 BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1); 58 BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1);
55 OUT_RING(evo, 0); 59 OUT_RING(evo, 0);
60
61 nv_encoder->crtc = NULL;
56} 62}
57 63
58static enum drm_connector_status 64static enum drm_connector_status
@@ -243,6 +249,8 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
243 BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2); 249 BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2);
244 OUT_RING(evo, mode_ctl); 250 OUT_RING(evo, mode_ctl);
245 OUT_RING(evo, mode_ctl2); 251 OUT_RING(evo, mode_ctl2);
252
253 nv_encoder->crtc = encoder->crtc;
246} 254}
247 255
248static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = { 256static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = {
@@ -253,7 +261,8 @@ static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = {
253 .prepare = nv50_dac_prepare, 261 .prepare = nv50_dac_prepare,
254 .commit = nv50_dac_commit, 262 .commit = nv50_dac_commit,
255 .mode_set = nv50_dac_mode_set, 263 .mode_set = nv50_dac_mode_set,
256 .detect = nv50_dac_detect 264 .detect = nv50_dac_detect,
265 .disable = nv50_dac_disconnect
257}; 266};
258 267
259static void 268static void
@@ -288,8 +297,6 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_entry *entry)
288 nv_encoder->dcb = entry; 297 nv_encoder->dcb = entry;
289 nv_encoder->or = ffs(entry->or) - 1; 298 nv_encoder->or = ffs(entry->or) - 1;
290 299
291 nv_encoder->disconnect = nv50_dac_disconnect;
292
293 drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs, 300 drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs,
294 DRM_MODE_ENCODER_DAC); 301 DRM_MODE_ENCODER_DAC);
295 drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs); 302 drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs);
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
index 4832bba7c43a..b259d63202eb 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -37,13 +37,17 @@
37#include "nv50_display.h" 37#include "nv50_display.h"
38 38
39static void 39static void
40nv50_sor_disconnect(struct nouveau_encoder *nv_encoder) 40nv50_sor_disconnect(struct drm_encoder *encoder)
41{ 41{
42 struct drm_device *dev = to_drm_encoder(nv_encoder)->dev; 42 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
43 struct drm_device *dev = encoder->dev;
43 struct drm_nouveau_private *dev_priv = dev->dev_private; 44 struct drm_nouveau_private *dev_priv = dev->dev_private;
44 struct nouveau_channel *evo = dev_priv->evo; 45 struct nouveau_channel *evo = dev_priv->evo;
45 int ret; 46 int ret;
46 47
48 if (!nv_encoder->crtc)
49 return;
50
47 NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or); 51 NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or);
48 52
49 ret = RING_SPACE(evo, 2); 53 ret = RING_SPACE(evo, 2);
@@ -53,6 +57,9 @@ nv50_sor_disconnect(struct nouveau_encoder *nv_encoder)
53 } 57 }
54 BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); 58 BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
55 OUT_RING(evo, 0); 59 OUT_RING(evo, 0);
60
61 nv_encoder->crtc = NULL;
62 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
56} 63}
57 64
58static void 65static void
@@ -94,14 +101,16 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
94 uint32_t val; 101 uint32_t val;
95 int or = nv_encoder->or; 102 int or = nv_encoder->or;
96 103
97 NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); 104 NV_DEBUG_KMS(dev, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode);
98 105
99 nv_encoder->last_dpms = mode; 106 nv_encoder->last_dpms = mode;
100 list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { 107 list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
101 struct nouveau_encoder *nvenc = nouveau_encoder(enc); 108 struct nouveau_encoder *nvenc = nouveau_encoder(enc);
102 109
103 if (nvenc == nv_encoder || 110 if (nvenc == nv_encoder ||
104 nvenc->disconnect != nv50_sor_disconnect || 111 (nvenc->dcb->type != OUTPUT_TMDS &&
112 nvenc->dcb->type != OUTPUT_LVDS &&
113 nvenc->dcb->type != OUTPUT_DP) ||
105 nvenc->dcb->or != nv_encoder->dcb->or) 114 nvenc->dcb->or != nv_encoder->dcb->or)
106 continue; 115 continue;
107 116
@@ -239,6 +248,14 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
239 } 248 }
240 BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); 249 BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
241 OUT_RING(evo, mode_ctl); 250 OUT_RING(evo, mode_ctl);
251
252 nv_encoder->crtc = encoder->crtc;
253}
254
255static struct drm_crtc *
256nv50_sor_crtc_get(struct drm_encoder *encoder)
257{
258 return nouveau_encoder(encoder)->crtc;
242} 259}
243 260
244static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = { 261static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = {
@@ -249,7 +266,9 @@ static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = {
249 .prepare = nv50_sor_prepare, 266 .prepare = nv50_sor_prepare,
250 .commit = nv50_sor_commit, 267 .commit = nv50_sor_commit,
251 .mode_set = nv50_sor_mode_set, 268 .mode_set = nv50_sor_mode_set,
252 .detect = NULL 269 .get_crtc = nv50_sor_crtc_get,
270 .detect = NULL,
271 .disable = nv50_sor_disconnect
253}; 272};
254 273
255static void 274static void
@@ -300,8 +319,7 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry)
300 319
301 nv_encoder->dcb = entry; 320 nv_encoder->dcb = entry;
302 nv_encoder->or = ffs(entry->or) - 1; 321 nv_encoder->or = ffs(entry->or) - 1;
303 322 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
304 nv_encoder->disconnect = nv50_sor_disconnect;
305 323
306 drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type); 324 drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type);
307 drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs); 325 drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs);