Commit 58d65b84 authored by Ben Skeggs's avatar Ben Skeggs

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: default avatarBen Skeggs <bskeggs@redhat.com>
parent 134f248b
...@@ -432,6 +432,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc) ...@@ -432,6 +432,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_encoder *encoder; struct drm_encoder *encoder;
uint32_t dac = 0, sor = 0;
NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
...@@ -439,9 +440,28 @@ nv50_crtc_prepare(struct drm_crtc *crtc) ...@@ -439,9 +440,28 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
if (drm_helper_encoder_in_use(encoder)) if (!drm_helper_encoder_in_use(encoder))
continue; 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); nv_encoder->disconnect(nv_encoder);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment