diff options
| author | Ben Skeggs <bskeggs@redhat.com> | 2010-01-17 17:52:35 -0500 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2010-01-17 18:56:27 -0500 |
| commit | 58d65b84dee524b0a4a8b747b8eb8bbf2fb16d9d (patch) | |
| tree | de9c4ef82d3c1a51d3fc0267b499e3dfcb02528a | |
| parent | 134f248bea4bf5c3169b4950eb49c6651b09eb0e (diff) | |
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>
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv50_crtc.c | 22 |
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) | |||
| 432 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 432 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
| 433 | struct drm_device *dev = crtc->dev; | 433 | struct drm_device *dev = crtc->dev; |
| 434 | struct drm_encoder *encoder; | 434 | struct drm_encoder *encoder; |
| 435 | uint32_t dac = 0, sor = 0; | ||
| 435 | 436 | ||
| 436 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 437 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); |
| 437 | 438 | ||
| @@ -439,9 +440,28 @@ nv50_crtc_prepare(struct drm_crtc *crtc) | |||
| 439 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 440 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
| 440 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 441 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
| 441 | 442 | ||
| 442 | if (drm_helper_encoder_in_use(encoder)) | 443 | if (!drm_helper_encoder_in_use(encoder)) |
| 443 | continue; | 444 | continue; |
| 444 | 445 | ||
| 446 | if (nv_encoder->dcb->type == OUTPUT_ANALOG || | ||
| 447 | nv_encoder->dcb->type == OUTPUT_TV) | ||
| 448 | dac |= (1 << nv_encoder->or); | ||
| 449 | else | ||
| 450 | sor |= (1 << nv_encoder->or); | ||
| 451 | } | ||
| 452 | |||
| 453 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 454 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||
| 455 | |||
| 456 | if (nv_encoder->dcb->type == OUTPUT_ANALOG || | ||
| 457 | nv_encoder->dcb->type == OUTPUT_TV) { | ||
| 458 | if (dac & (1 << nv_encoder->or)) | ||
| 459 | continue; | ||
| 460 | } else { | ||
| 461 | if (sor & (1 << nv_encoder->or)) | ||
| 462 | continue; | ||
| 463 | } | ||
| 464 | |||
| 445 | nv_encoder->disconnect(nv_encoder); | 465 | nv_encoder->disconnect(nv_encoder); |
| 446 | } | 466 | } |
| 447 | 467 | ||
