summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-01-17 23:52:35 +0100
committerBen Skeggs <bskeggs@redhat.com>2010-01-18 00:56:27 +0100
commit58d65b84dee524b0a4a8b747b8eb8bbf2fb16d9d (patch)
treede9c4ef82d3c1a51d3fc0267b499e3dfcb02528a /drivers/gpu
parentdrm/nv50: fix alignment of per-channel fifo cache (diff)
downloadlinux-58d65b84dee524b0a4a8b747b8eb8bbf2fb16d9d.tar.xz
linux-58d65b84dee524b0a4a8b747b8eb8bbf2fb16d9d.zip
drm/nv50: prevent accidently turning off encoders we're actually using
On most cards the DisplayPort connector is created with 2 encoders sharing a single SOR (for native DP, and for DVI-over-DP). The previous logic for turning off unused encoders didn't take into account that we could have multiple drm_encoders on a single hw encoder and ended up turning off encoders that were actually being used still. This patch fixes that issue. We probably want to look at something a bit better later on, and only expose one drm_encoder per hw encoder block. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/nv50_crtc.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index 118d3285fd8c..40b7360841f8 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -432,6 +432,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_encoder *encoder;
+ uint32_t dac = 0, sor = 0;
NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
@@ -439,9 +440,28 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- if (drm_helper_encoder_in_use(encoder))
+ if (!drm_helper_encoder_in_use(encoder))
continue;
+ if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
+ nv_encoder->dcb->type == OUTPUT_TV)
+ dac |= (1 << nv_encoder->or);
+ else
+ sor |= (1 << nv_encoder->or);
+ }
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+ if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
+ nv_encoder->dcb->type == OUTPUT_TV) {
+ if (dac & (1 << nv_encoder->or))
+ continue;
+ } else {
+ if (sor & (1 << nv_encoder->or))
+ continue;
+ }
+
nv_encoder->disconnect(nv_encoder);
}