diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-11-15 20:40:34 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-11-28 18:57:55 -0500 |
commit | 419e8dc0afa4e0b2746f39dbef287f0c4befbbf2 (patch) | |
tree | 283d583eeed0773c47d6ab721a83d857a633ee76 /drivers/gpu/drm/nouveau/nvd0_display.c | |
parent | 97b19b5c6f32842c92800b62b367cc5a91555188 (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.c | 106 |
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 | |||
1529 | nvd0_sor_disconnect(struct drm_encoder *encoder) | 1529 | nvd0_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 | ||
1554 | static void | 1561 | static 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; |