diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-07-04 10:14:42 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-07-12 20:13:20 -0400 |
commit | 8ccfe9e098d5975ef65d17de477f6b7dc0c446db (patch) | |
tree | 1fe23accc759ac779ee41e048769d8ddadf89ea3 | |
parent | be8860ac0c99c4cd67dfc364c6f57d299f8d7e9d (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.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_dac.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv17_tv.c | 6 |
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 *); | |||
1076 | extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder); | 1076 | extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder); |
1077 | extern int nv04_dac_output_offset(struct drm_encoder *encoder); | 1077 | extern int nv04_dac_output_offset(struct drm_encoder *encoder); |
1078 | extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); | 1078 | extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); |
1079 | extern bool nv04_dac_in_use(struct drm_encoder *encoder); | ||
1079 | 1080 | ||
1080 | /* nv04_dfp.c */ | 1081 | /* nv04_dfp.c */ |
1081 | extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *); | 1082 | extern 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. */ | ||
438 | bool 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 | |||
430 | static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) | 447 | static 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 |