aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2010-07-04 10:14:42 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-07-12 20:13:20 -0400
commit8ccfe9e098d5975ef65d17de477f6b7dc0c446db (patch)
tree1fe23accc759ac779ee41e048769d8ddadf89ea3
parentbe8860ac0c99c4cd67dfc364c6f57d299f8d7e9d (diff)
drm/nv04-nv40: Prevent invalid DAC/TVDAC combinations.
Signed-off-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nv04_dac.c21
-rw-r--r--drivers/gpu/drm/nouveau/nv17_tv.c6
3 files changed, 26 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index e3c8bd4f99c9..565981dfd69b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -1076,6 +1076,7 @@ extern int nv04_dac_create(struct drm_connector *, struct dcb_entry *);
1076extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder); 1076extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder);
1077extern int nv04_dac_output_offset(struct drm_encoder *encoder); 1077extern int nv04_dac_output_offset(struct drm_encoder *encoder);
1078extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); 1078extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable);
1079extern bool nv04_dac_in_use(struct drm_encoder *encoder);
1079 1080
1080/* nv04_dfp.c */ 1081/* nv04_dfp.c */
1081extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *); 1082extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *);
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)
314{ 314{
315 struct drm_device *dev = encoder->dev; 315 struct drm_device *dev = encoder->dev;
316 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; 316 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
317 uint32_t sample = nv17_dac_sample_load(encoder);
318 317
319 if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { 318 if (nv04_dac_in_use(encoder))
319 return connector_status_disconnected;
320
321 if (nv17_dac_sample_load(encoder) &
322 NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
320 NV_INFO(dev, "Load detected on output %c\n", 323 NV_INFO(dev, "Load detected on output %c\n",
321 '@' + ffs(dcb->or)); 324 '@' + ffs(dcb->or));
322 return connector_status_connected; 325 return connector_status_connected;
@@ -329,6 +332,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder,
329 struct drm_display_mode *mode, 332 struct drm_display_mode *mode,
330 struct drm_display_mode *adjusted_mode) 333 struct drm_display_mode *adjusted_mode)
331{ 334{
335 if (nv04_dac_in_use(encoder))
336 return false;
337
332 return true; 338 return true;
333} 339}
334 340
@@ -427,6 +433,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
427 } 433 }
428} 434}
429 435
436/* Check if the DAC corresponding to 'encoder' is being used by
437 * someone else. */
438bool nv04_dac_in_use(struct drm_encoder *encoder)
439{
440 struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
441 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
442
443 return nv_gf4_disp_arch(encoder->dev) &&
444 (dev_priv->dac_users[ffs(dcb->or) - 1] & ~(1 << dcb->index));
445}
446
430static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) 447static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
431{ 448{
432 struct drm_device *dev = encoder->dev; 449 struct drm_device *dev = encoder->dev;
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c
index 44437ff46394..864867ed951a 100644
--- a/drivers/gpu/drm/nouveau/nv17_tv.c
+++ b/drivers/gpu/drm/nouveau/nv17_tv.c
@@ -125,6 +125,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
125 struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); 125 struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
126 struct dcb_entry *dcb = tv_enc->base.dcb; 126 struct dcb_entry *dcb = tv_enc->base.dcb;
127 127
128 if (nv04_dac_in_use(encoder))
129 return connector_status_disconnected;
130
128 if (dev_priv->chipset == 0x42 || 131 if (dev_priv->chipset == 0x42 ||
129 dev_priv->chipset == 0x43) 132 dev_priv->chipset == 0x43)
130 tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe; 133 tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe;
@@ -296,6 +299,9 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder,
296{ 299{
297 struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); 300 struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
298 301
302 if (nv04_dac_in_use(encoder))
303 return false;
304
299 if (tv_norm->kind == CTV_ENC_MODE) 305 if (tv_norm->kind == CTV_ENC_MODE)
300 adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock; 306 adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock;
301 else 307 else