Commit 8ccfe9e0 authored by Francisco Jerez's avatar Francisco Jerez Committed by Ben Skeggs

drm/nv04-nv40: Prevent invalid DAC/TVDAC combinations.

Signed-off-by: default avatarFrancisco Jerez <currojerez@riseup.net>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent be8860ac
...@@ -1076,6 +1076,7 @@ extern int nv04_dac_create(struct drm_connector *, struct dcb_entry *); ...@@ -1076,6 +1076,7 @@ extern int nv04_dac_create(struct drm_connector *, struct dcb_entry *);
extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder); extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder);
extern int nv04_dac_output_offset(struct drm_encoder *encoder); extern int nv04_dac_output_offset(struct drm_encoder *encoder);
extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable);
extern bool nv04_dac_in_use(struct drm_encoder *encoder);
/* nv04_dfp.c */ /* nv04_dfp.c */
extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *); extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *);
......
...@@ -314,9 +314,12 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) ...@@ -314,9 +314,12 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; 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", NV_INFO(dev, "Load detected on output %c\n",
'@' + ffs(dcb->or)); '@' + ffs(dcb->or));
return connector_status_connected; return connector_status_connected;
...@@ -329,6 +332,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, ...@@ -329,6 +332,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
if (nv04_dac_in_use(encoder))
return false;
return true; return true;
} }
...@@ -427,6 +433,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) ...@@ -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) static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
......
...@@ -125,6 +125,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) ...@@ -125,6 +125,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
struct dcb_entry *dcb = tv_enc->base.dcb; struct dcb_entry *dcb = tv_enc->base.dcb;
if (nv04_dac_in_use(encoder))
return connector_status_disconnected;
if (dev_priv->chipset == 0x42 || if (dev_priv->chipset == 0x42 ||
dev_priv->chipset == 0x43) dev_priv->chipset == 0x43)
tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe; 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,6 +299,9 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder,
{ {
struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
if (nv04_dac_in_use(encoder))
return false;
if (tv_norm->kind == CTV_ENC_MODE) if (tv_norm->kind == CTV_ENC_MODE)
adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock; adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock;
else else
......
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