summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv04_dac.c
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2010-07-04 16:14:42 +0200
committerBen Skeggs <bskeggs@redhat.com>2010-07-13 10:13:20 +1000
commit8ccfe9e098d5975ef65d17de477f6b7dc0c446db (patch)
tree1fe23accc759ac779ee41e048769d8ddadf89ea3 /drivers/gpu/drm/nouveau/nv04_dac.c
parentbe8860ac0c99c4cd67dfc364c6f57d299f8d7e9d (diff)
downloadlinux-8ccfe9e098d5975ef65d17de477f6b7dc0c446db.tar.bz2
drm/nv04-nv40: Prevent invalid DAC/TVDAC combinations.
Signed-off-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv04_dac.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv04_dac.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c
index bcc8090adb23..2d0fee5f09ce 100644
--- a/drivers/gpu/drm/nouveau/nv04_dac.c
+++ b/drivers/gpu/drm/nouveau/nv04_dac.c
@@ -314,9 +314,12 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
- uint32_t sample = nv17_dac_sample_load(encoder);
- if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
+ if (nv04_dac_in_use(encoder))
+ return connector_status_disconnected;
+
+ if (nv17_dac_sample_load(encoder) &
+ NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
NV_INFO(dev, "Load detected on output %c\n",
'@' + ffs(dcb->or));
return connector_status_connected;
@@ -329,6 +332,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
+ if (nv04_dac_in_use(encoder))
+ return false;
+
return true;
}
@@ -427,6 +433,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
}
}
+/* Check if the DAC corresponding to 'encoder' is being used by
+ * someone else. */
+bool nv04_dac_in_use(struct drm_encoder *encoder)
+{
+ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
+ struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
+
+ return nv_gf4_disp_arch(encoder->dev) &&
+ (dev_priv->dac_users[ffs(dcb->or) - 1] & ~(1 << dcb->index));
+}
+
static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;