diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_display.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 91 |
1 files changed, 37 insertions, 54 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 12c5ee63495..61a89f2dc55 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -188,7 +188,7 @@ nv50_display_init(struct drm_device *dev) uint64_t start; int ret, i; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004)); /* @@ -232,7 +232,7 @@ nv50_display_init(struct drm_device *dev) nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0); /* RAM is clamped to 256 MiB. */ ram_amount = nouveau_mem_fb_amount(dev); - NV_DEBUG(dev, "ram_amount %d\n", ram_amount); + NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount); if (ram_amount > 256*1024*1024) ram_amount = 256*1024*1024; nv_wr32(dev, NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1); @@ -370,9 +370,7 @@ nv50_display_init(struct drm_device *dev) struct nouveau_connector *conn = nouveau_connector(connector); struct dcb_gpio_entry *gpio; - if (connector->connector_type != DRM_MODE_CONNECTOR_DVII && - connector->connector_type != DRM_MODE_CONNECTOR_DVID && - connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) + if (conn->dcb->gpio_tag == 0xff) continue; gpio = nouveau_bios_gpio_entry(dev, conn->dcb->gpio_tag); @@ -398,7 +396,7 @@ static int nv50_display_disable(struct drm_device *dev) struct drm_crtc *drm_crtc; int ret, i; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc); @@ -465,11 +463,10 @@ static int nv50_display_disable(struct drm_device *dev) int nv50_display_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct parsed_dcb *dcb = dev_priv->vbios->dcb; - uint32_t connector[16] = {}; + struct dcb_table *dcb = &dev_priv->vbios.dcb; int ret, i; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); /* init basic kernel modesetting */ drm_mode_config_init(dev); @@ -522,44 +519,13 @@ int nv50_display_create(struct drm_device *dev) NV_WARN(dev, "DCB encoder %d unknown\n", entry->type); continue; } - - connector[entry->connector] |= (1 << entry->type); } - /* It appears that DCB 3.0+ VBIOS has a connector table, however, - * I'm not 100% certain how to decode it correctly yet so just - * look at what encoders are present on each connector index and - * attempt to derive the connector type from that. - */ - for (i = 0 ; i < dcb->entries; i++) { - struct dcb_entry *entry = &dcb->entry[i]; - uint16_t encoders; - int type; - - encoders = connector[entry->connector]; - if (!(encoders & (1 << entry->type))) - continue; - connector[entry->connector] = 0; - - if (encoders & (1 << OUTPUT_DP)) { - type = DRM_MODE_CONNECTOR_DisplayPort; - } else if (encoders & (1 << OUTPUT_TMDS)) { - if (encoders & (1 << OUTPUT_ANALOG)) - type = DRM_MODE_CONNECTOR_DVII; - else - type = DRM_MODE_CONNECTOR_DVID; - } else if (encoders & (1 << OUTPUT_ANALOG)) { - type = DRM_MODE_CONNECTOR_VGA; - } else if (encoders & (1 << OUTPUT_LVDS)) { - type = DRM_MODE_CONNECTOR_LVDS; - } else { - type = DRM_MODE_CONNECTOR_Unknown; - } - - if (type == DRM_MODE_CONNECTOR_Unknown) + for (i = 0 ; i < dcb->connector.entries; i++) { + if (i != 0 && dcb->connector.entry[i].index == + dcb->connector.entry[i - 1].index) continue; - - nouveau_connector_create(dev, entry->connector, type); + nouveau_connector_create(dev, &dcb->connector.entry[i]); } ret = nv50_display_init(dev); @@ -573,7 +539,7 @@ int nv50_display_destroy(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); drm_mode_config_cleanup(dev); @@ -617,7 +583,7 @@ nv50_display_irq_head(struct drm_device *dev, int *phead, * CRTC separately, and submission will be blocked by the GPU * until we handle each in turn. */ - NV_DEBUG(dev, "0x610030: 0x%08x\n", unk30); + NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); head = ffs((unk30 >> 9) & 3) - 1; if (head < 0) return -EINVAL; @@ -661,14 +627,14 @@ nv50_display_irq_head(struct drm_device *dev, int *phead, or = i; } - NV_DEBUG(dev, "type %d, or %d\n", type, or); + NV_DEBUG_KMS(dev, "type %d, or %d\n", type, or); if (type == OUTPUT_ANY) { NV_ERROR(dev, "unknown encoder!!\n"); return -1; } - for (i = 0; i < dev_priv->vbios->dcb->entries; i++) { - struct dcb_entry *dcbent = &dev_priv->vbios->dcb->entry[i]; + for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { + struct dcb_entry *dcbent = &dev_priv->vbios.dcb.entry[i]; if (dcbent->type != type) continue; @@ -690,15 +656,27 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent, int pxclk) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->VBIOS; + struct nouveau_connector *nv_connector = NULL; + struct drm_encoder *encoder; + struct nvbios *bios = &dev_priv->vbios; uint32_t mc, script = 0, or; + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + if (nv_encoder->dcb != dcbent) + continue; + + nv_connector = nouveau_encoder_connector_get(nv_encoder); + break; + } + or = ffs(dcbent->or) - 1; mc = nv50_display_mode_ctrl(dev, dcbent->type != OUTPUT_ANALOG, or); switch (dcbent->type) { case OUTPUT_LVDS: script = (mc >> 8) & 0xf; - if (bios->pub.fp_no_ddc) { + if (bios->fp_no_ddc) { if (bios->fp.dual_link) script |= 0x0100; if (bios->fp.if_is_24bit) @@ -711,6 +689,11 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent, } else if (bios->fp.strapless_is_24bit & 1) script |= 0x0200; + + if (nv_connector && nv_connector->edid && + (nv_connector->edid->revision >= 4) && + (nv_connector->edid->input & 0x70) >= 0x20) + script |= 0x0200; } if (nouveau_uscript_lvds >= 0) { @@ -811,7 +794,7 @@ nv50_display_unk20_handler(struct drm_device *dev) pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff; script = nv50_display_script_select(dev, dcbent, pclk); - NV_DEBUG(dev, "head %d pxclk: %dKHz\n", head, pclk); + NV_DEBUG_KMS(dev, "head %d pxclk: %dKHz\n", head, pclk); if (dcbent->type != OUTPUT_DP) nouveau_bios_run_display_table(dev, dcbent, 0, -2); @@ -870,7 +853,7 @@ nv50_display_irq_handler_bh(struct work_struct *work) uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); - NV_DEBUG(dev, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1); + NV_DEBUG_KMS(dev, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1); if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK10) nv50_display_unk10_handler(dev); @@ -974,7 +957,7 @@ nv50_display_irq_handler(struct drm_device *dev) uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); uint32_t clock; - NV_DEBUG(dev, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1); + NV_DEBUG_KMS(dev, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1); if (!intr0 && !(intr1 & ~delayed)) break; |