aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvd0_display.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-11-15 20:40:34 -0500
committerBen Skeggs <bskeggs@redhat.com>2012-11-28 18:57:55 -0500
commit419e8dc0afa4e0b2746f39dbef287f0c4befbbf2 (patch)
tree283d583eeed0773c47d6ab721a83d857a633ee76 /drivers/gpu/drm/nouveau/nvd0_display.c
parent97b19b5c6f32842c92800b62b367cc5a91555188 (diff)
drm/nvd0/disp: implement sor support for older display classes
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvd0_display.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvd0_display.c106
1 files changed, 61 insertions, 45 deletions
diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c
index 037602b72d6c..daf3e668212d 100644
--- a/drivers/gpu/drm/nouveau/nvd0_display.c
+++ b/drivers/gpu/drm/nouveau/nvd0_display.c
@@ -1529,26 +1529,33 @@ static void
1529nvd0_sor_disconnect(struct drm_encoder *encoder) 1529nvd0_sor_disconnect(struct drm_encoder *encoder)
1530{ 1530{
1531 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1531 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1532 struct drm_device *dev = encoder->dev; 1532 struct nvd0_mast *mast = nvd0_mast(encoder->dev);
1533 const int or = nv_encoder->or;
1533 u32 *push; 1534 u32 *push;
1534 1535
1535 if (nv_encoder->crtc) { 1536 if (nv_encoder->crtc) {
1536 nvd0_crtc_prepare(nv_encoder->crtc); 1537 nvd0_crtc_prepare(nv_encoder->crtc);
1537 1538
1538 push = evo_wait(nvd0_mast(dev), 4); 1539 push = evo_wait(mast, 4);
1539 if (push) { 1540 if (push) {
1540 evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); 1541 if (nvd0_vers(mast) < NVD0_DISP_MAST_CLASS) {
1541 evo_data(push, 0x00000000); 1542 evo_mthd(push, 0x0600 + (or * 0x40), 1);
1543 evo_data(push, 0x00000000);
1544 } else {
1545 evo_mthd(push, 0x0200 + (or * 0x20), 1);
1546 evo_data(push, 0x00000000);
1547 }
1548
1542 evo_mthd(push, 0x0080, 1); 1549 evo_mthd(push, 0x0080, 1);
1543 evo_data(push, 0x00000000); 1550 evo_data(push, 0x00000000);
1544 evo_kick(push, nvd0_mast(dev)); 1551 evo_kick(push, mast);
1545 } 1552 }
1546 1553
1547 nvd0_hdmi_disconnect(encoder); 1554 nvd0_hdmi_disconnect(encoder);
1548
1549 nv_encoder->crtc = NULL;
1550 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
1551 } 1555 }
1556
1557 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
1558 nv_encoder->crtc = NULL;
1552} 1559}
1553 1560
1554static void 1561static void
@@ -1569,84 +1576,76 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
1569 struct drm_display_mode *mode) 1576 struct drm_display_mode *mode)
1570{ 1577{
1571 struct nvd0_disp *disp = nvd0_disp(encoder->dev); 1578 struct nvd0_disp *disp = nvd0_disp(encoder->dev);
1579 struct nvd0_mast *mast = nvd0_mast(encoder->dev);
1572 struct drm_device *dev = encoder->dev; 1580 struct drm_device *dev = encoder->dev;
1573 struct nouveau_drm *drm = nouveau_drm(dev); 1581 struct nouveau_drm *drm = nouveau_drm(dev);
1574 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1582 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
1575 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); 1583 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
1576 struct nouveau_connector *nv_connector; 1584 struct nouveau_connector *nv_connector;
1577 struct nvbios *bios = &drm->vbios; 1585 struct nvbios *bios = &drm->vbios;
1578 int or = nv_encoder->or; 1586 u32 *push, lvds = 0;
1579 u32 mode_ctrl = (1 << nv_crtc->index); 1587 u8 owner = 1 << nv_crtc->index;
1580 u32 syncs, magic, *push; 1588 u8 proto = 0xf;
1581 u32 or_config; 1589 u8 depth = 0x0;
1582
1583 syncs = 0x00000001;
1584 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1585 syncs |= 0x00000008;
1586 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1587 syncs |= 0x00000010;
1588
1589 magic = 0x31ec6000 | (nv_crtc->index << 25);
1590 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1591 magic |= 0x00000001;
1592 1590
1593 nv_connector = nouveau_encoder_connector_get(nv_encoder); 1591 nv_connector = nouveau_encoder_connector_get(nv_encoder);
1594 switch (nv_encoder->dcb->type) { 1592 switch (nv_encoder->dcb->type) {
1595 case DCB_OUTPUT_TMDS: 1593 case DCB_OUTPUT_TMDS:
1596 if (nv_encoder->dcb->sorconf.link & 1) { 1594 if (nv_encoder->dcb->sorconf.link & 1) {
1597 if (mode->clock < 165000) 1595 if (mode->clock < 165000)
1598 mode_ctrl |= 0x00000100; 1596 proto = 0x1;
1599 else 1597 else
1600 mode_ctrl |= 0x00000500; 1598 proto = 0x5;
1601 } else { 1599 } else {
1602 mode_ctrl |= 0x00000200; 1600 proto = 0x2;
1603 } 1601 }
1604 1602
1605 nvd0_hdmi_mode_set(encoder, mode); 1603 nvd0_hdmi_mode_set(encoder, mode);
1606 break; 1604 break;
1607 case DCB_OUTPUT_LVDS: 1605 case DCB_OUTPUT_LVDS:
1608 or_config = (mode_ctrl & 0x00000f00) >> 8; 1606 proto = 0x0;
1607
1609 if (bios->fp_no_ddc) { 1608 if (bios->fp_no_ddc) {
1610 if (bios->fp.dual_link) 1609 if (bios->fp.dual_link)
1611 or_config |= 0x0100; 1610 lvds |= 0x0100;
1612 if (bios->fp.if_is_24bit) 1611 if (bios->fp.if_is_24bit)
1613 or_config |= 0x0200; 1612 lvds |= 0x0200;
1614 } else { 1613 } else {
1615 if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { 1614 if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) {
1616 if (((u8 *)nv_connector->edid)[121] == 2) 1615 if (((u8 *)nv_connector->edid)[121] == 2)
1617 or_config |= 0x0100; 1616 lvds |= 0x0100;
1618 } else 1617 } else
1619 if (mode->clock >= bios->fp.duallink_transition_clk) { 1618 if (mode->clock >= bios->fp.duallink_transition_clk) {
1620 or_config |= 0x0100; 1619 lvds |= 0x0100;
1621 } 1620 }
1622 1621
1623 if (or_config & 0x0100) { 1622 if (lvds & 0x0100) {
1624 if (bios->fp.strapless_is_24bit & 2) 1623 if (bios->fp.strapless_is_24bit & 2)
1625 or_config |= 0x0200; 1624 lvds |= 0x0200;
1626 } else { 1625 } else {
1627 if (bios->fp.strapless_is_24bit & 1) 1626 if (bios->fp.strapless_is_24bit & 1)
1628 or_config |= 0x0200; 1627 lvds |= 0x0200;
1629 } 1628 }
1630 1629
1631 if (nv_connector->base.display_info.bpc == 8) 1630 if (nv_connector->base.display_info.bpc == 8)
1632 or_config |= 0x0200; 1631 lvds |= 0x0200;
1633 } 1632 }
1634 1633
1635 nv_call(disp->core, NV50_DISP_SOR_LVDS_SCRIPT + or, or_config); 1634 nv_call(disp->core, NV50_DISP_SOR_LVDS_SCRIPT + nv_encoder->or, lvds);
1636 break; 1635 break;
1637 case DCB_OUTPUT_DP: 1636 case DCB_OUTPUT_DP:
1638 if (nv_connector->base.display_info.bpc == 6) { 1637 if (nv_connector->base.display_info.bpc == 6) {
1639 nv_encoder->dp.datarate = mode->clock * 18 / 8; 1638 nv_encoder->dp.datarate = mode->clock * 18 / 8;
1640 syncs |= 0x00000002 << 6; 1639 depth = 0x2;
1641 } else { 1640 } else {
1642 nv_encoder->dp.datarate = mode->clock * 24 / 8; 1641 nv_encoder->dp.datarate = mode->clock * 24 / 8;
1643 syncs |= 0x00000005 << 6; 1642 depth = 0x5;
1644 } 1643 }
1645 1644
1646 if (nv_encoder->dcb->sorconf.link & 1) 1645 if (nv_encoder->dcb->sorconf.link & 1)
1647 mode_ctrl |= 0x00000800; 1646 proto = 0x8;
1648 else 1647 else
1649 mode_ctrl |= 0x00000900; 1648 proto = 0x9;
1650 break; 1649 break;
1651 default: 1650 default:
1652 BUG_ON(1); 1651 BUG_ON(1);
@@ -1657,12 +1656,29 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
1657 1656
1658 push = evo_wait(nvd0_mast(dev), 8); 1657 push = evo_wait(nvd0_mast(dev), 8);
1659 if (push) { 1658 if (push) {
1660 evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); 1659 if (nvd0_vers(mast) < NVD0_DISP_CLASS) {
1661 evo_data(push, syncs); 1660 evo_mthd(push, 0x0600 + (nv_encoder->or * 0x040), 1);
1662 evo_data(push, magic); 1661 evo_data(push, (depth << 16) | (proto << 8) | owner);
1663 evo_mthd(push, 0x0200 + (nv_encoder->or * 0x020), 1); 1662 } else {
1664 evo_data(push, mode_ctrl); 1663 u32 magic = 0x31ec6000 | (nv_crtc->index << 25);
1665 evo_kick(push, nvd0_mast(dev)); 1664 u32 syncs = 0x00000001;
1665
1666 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1667 syncs |= 0x00000008;
1668 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1669 syncs |= 0x00000010;
1670
1671 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1672 magic |= 0x00000001;
1673
1674 evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2);
1675 evo_data(push, syncs | (depth << 6));
1676 evo_data(push, magic);
1677 evo_mthd(push, 0x0200 + (nv_encoder->or * 0x020), 1);
1678 evo_data(push, owner | (proto << 8));
1679 }
1680
1681 evo_kick(push, mast);
1666 } 1682 }
1667 1683
1668 nv_encoder->crtc = encoder->crtc; 1684 nv_encoder->crtc = encoder->crtc;