diff options
author | Thierry Reding <treding@nvidia.com> | 2015-08-03 09:46:15 -0400 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2016-07-04 05:31:22 -0400 |
commit | 2bd1dd399fcd2e23efb1583df3ba846b20429739 (patch) | |
tree | df261b36112856380b6e46184a36ee2e7efc2a82 | |
parent | 402f6bcd94fa3437b833931da8e1fbfc1fb6c444 (diff) |
drm/tegra: sor: Extract tegra_sor_mode_set()
The code to set a video mode is common to all types of outputs that the
SOR can drive. Extract it into a separate function so that it can be
shared.
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | drivers/gpu/drm/tegra/sor.c | 226 |
1 files changed, 93 insertions, 133 deletions
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 5d9a9f2ba4de..01b31805f719 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c | |||
@@ -718,6 +718,83 @@ static void tegra_sor_apply_config(struct tegra_sor *sor, | |||
718 | tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS); | 718 | tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS); |
719 | } | 719 | } |
720 | 720 | ||
721 | static void tegra_sor_mode_set(struct tegra_sor *sor, | ||
722 | const struct drm_display_mode *mode, | ||
723 | const struct drm_display_info *info) | ||
724 | { | ||
725 | struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc); | ||
726 | unsigned int vbe, vse, hbe, hse, vbs, hbs; | ||
727 | u32 value; | ||
728 | |||
729 | value = tegra_sor_readl(sor, SOR_STATE1); | ||
730 | value &= ~SOR_STATE_ASY_PIXELDEPTH_MASK; | ||
731 | value &= ~SOR_STATE_ASY_CRC_MODE_MASK; | ||
732 | value &= ~SOR_STATE_ASY_OWNER_MASK; | ||
733 | |||
734 | value |= SOR_STATE_ASY_CRC_MODE_COMPLETE | | ||
735 | SOR_STATE_ASY_OWNER(dc->pipe + 1); | ||
736 | |||
737 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) | ||
738 | value &= ~SOR_STATE_ASY_HSYNCPOL; | ||
739 | |||
740 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
741 | value |= SOR_STATE_ASY_HSYNCPOL; | ||
742 | |||
743 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) | ||
744 | value &= ~SOR_STATE_ASY_VSYNCPOL; | ||
745 | |||
746 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
747 | value |= SOR_STATE_ASY_VSYNCPOL; | ||
748 | |||
749 | switch (info->bpc) { | ||
750 | case 8: | ||
751 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444; | ||
752 | break; | ||
753 | |||
754 | case 6: | ||
755 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444; | ||
756 | break; | ||
757 | |||
758 | default: | ||
759 | BUG(); | ||
760 | break; | ||
761 | } | ||
762 | |||
763 | tegra_sor_writel(sor, value, SOR_STATE1); | ||
764 | |||
765 | /* | ||
766 | * TODO: The video timing programming below doesn't seem to match the | ||
767 | * register definitions. | ||
768 | */ | ||
769 | |||
770 | value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff); | ||
771 | tegra_sor_writel(sor, value, SOR_HEAD_STATE1(dc->pipe)); | ||
772 | |||
773 | /* sync end = sync width - 1 */ | ||
774 | vse = mode->vsync_end - mode->vsync_start - 1; | ||
775 | hse = mode->hsync_end - mode->hsync_start - 1; | ||
776 | |||
777 | value = ((vse & 0x7fff) << 16) | (hse & 0x7fff); | ||
778 | tegra_sor_writel(sor, value, SOR_HEAD_STATE2(dc->pipe)); | ||
779 | |||
780 | /* blank end = sync end + back porch */ | ||
781 | vbe = vse + (mode->vtotal - mode->vsync_end); | ||
782 | hbe = hse + (mode->htotal - mode->hsync_end); | ||
783 | |||
784 | value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff); | ||
785 | tegra_sor_writel(sor, value, SOR_HEAD_STATE3(dc->pipe)); | ||
786 | |||
787 | /* blank start = blank end + active */ | ||
788 | vbs = vbe + mode->vdisplay; | ||
789 | hbs = hbe + mode->hdisplay; | ||
790 | |||
791 | value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff); | ||
792 | tegra_sor_writel(sor, value, SOR_HEAD_STATE4(dc->pipe)); | ||
793 | |||
794 | /* XXX interlacing support */ | ||
795 | tegra_sor_writel(sor, 0x001, SOR_HEAD_STATE5(dc->pipe)); | ||
796 | } | ||
797 | |||
721 | static int tegra_sor_detach(struct tegra_sor *sor) | 798 | static int tegra_sor_detach(struct tegra_sor *sor) |
722 | { | 799 | { |
723 | unsigned long value, timeout; | 800 | unsigned long value, timeout; |
@@ -1250,14 +1327,17 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) | |||
1250 | struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; | 1327 | struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; |
1251 | struct tegra_output *output = encoder_to_output(encoder); | 1328 | struct tegra_output *output = encoder_to_output(encoder); |
1252 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | 1329 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); |
1253 | unsigned int vbe, vse, hbe, hse, vbs, hbs, i; | ||
1254 | struct tegra_sor *sor = to_sor(output); | 1330 | struct tegra_sor *sor = to_sor(output); |
1255 | struct tegra_sor_config config; | 1331 | struct tegra_sor_config config; |
1332 | struct drm_display_info *info; | ||
1256 | struct drm_dp_link link; | 1333 | struct drm_dp_link link; |
1257 | u8 rate, lanes; | 1334 | u8 rate, lanes; |
1335 | unsigned int i; | ||
1258 | int err = 0; | 1336 | int err = 0; |
1259 | u32 value; | 1337 | u32 value; |
1260 | 1338 | ||
1339 | info = &output->connector.display_info; | ||
1340 | |||
1261 | err = clk_prepare_enable(sor->clk); | 1341 | err = clk_prepare_enable(sor->clk); |
1262 | if (err < 0) | 1342 | if (err < 0) |
1263 | dev_err(sor->dev, "failed to enable clock: %d\n", err); | 1343 | dev_err(sor->dev, "failed to enable clock: %d\n", err); |
@@ -1505,75 +1585,19 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) | |||
1505 | if (err < 0) | 1585 | if (err < 0) |
1506 | dev_err(sor->dev, "failed to power up SOR: %d\n", err); | 1586 | dev_err(sor->dev, "failed to power up SOR: %d\n", err); |
1507 | 1587 | ||
1508 | /* | ||
1509 | * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete | ||
1510 | * raster, associate with display controller) | ||
1511 | */ | ||
1512 | value = SOR_STATE_ASY_PROTOCOL_DP_A | | ||
1513 | SOR_STATE_ASY_CRC_MODE_COMPLETE | | ||
1514 | SOR_STATE_ASY_OWNER(dc->pipe + 1); | ||
1515 | |||
1516 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) | ||
1517 | value &= ~SOR_STATE_ASY_HSYNCPOL; | ||
1518 | |||
1519 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
1520 | value |= SOR_STATE_ASY_HSYNCPOL; | ||
1521 | |||
1522 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) | ||
1523 | value &= ~SOR_STATE_ASY_VSYNCPOL; | ||
1524 | |||
1525 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
1526 | value |= SOR_STATE_ASY_VSYNCPOL; | ||
1527 | |||
1528 | switch (config.bits_per_pixel) { | ||
1529 | case 24: | ||
1530 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444; | ||
1531 | break; | ||
1532 | |||
1533 | case 18: | ||
1534 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444; | ||
1535 | break; | ||
1536 | |||
1537 | default: | ||
1538 | BUG(); | ||
1539 | break; | ||
1540 | } | ||
1541 | |||
1542 | tegra_sor_writel(sor, value, SOR_STATE1); | ||
1543 | |||
1544 | /* | ||
1545 | * TODO: The video timing programming below doesn't seem to match the | ||
1546 | * register definitions. | ||
1547 | */ | ||
1548 | |||
1549 | value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff); | ||
1550 | tegra_sor_writel(sor, value, SOR_HEAD_STATE1(dc->pipe)); | ||
1551 | |||
1552 | vse = mode->vsync_end - mode->vsync_start - 1; | ||
1553 | hse = mode->hsync_end - mode->hsync_start - 1; | ||
1554 | |||
1555 | value = ((vse & 0x7fff) << 16) | (hse & 0x7fff); | ||
1556 | tegra_sor_writel(sor, value, SOR_HEAD_STATE2(dc->pipe)); | ||
1557 | |||
1558 | vbe = vse + (mode->vsync_start - mode->vdisplay); | ||
1559 | hbe = hse + (mode->hsync_start - mode->hdisplay); | ||
1560 | |||
1561 | value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff); | ||
1562 | tegra_sor_writel(sor, value, SOR_HEAD_STATE3(dc->pipe)); | ||
1563 | |||
1564 | vbs = vbe + mode->vdisplay; | ||
1565 | hbs = hbe + mode->hdisplay; | ||
1566 | |||
1567 | value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff); | ||
1568 | tegra_sor_writel(sor, value, SOR_HEAD_STATE4(dc->pipe)); | ||
1569 | |||
1570 | tegra_sor_writel(sor, 0x1, SOR_HEAD_STATE5(dc->pipe)); | ||
1571 | |||
1572 | /* CSTM (LVDS, link A/B, upper) */ | 1588 | /* CSTM (LVDS, link A/B, upper) */ |
1573 | value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_A | SOR_CSTM_LINK_ACT_B | | 1589 | value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_A | SOR_CSTM_LINK_ACT_B | |
1574 | SOR_CSTM_UPPER; | 1590 | SOR_CSTM_UPPER; |
1575 | tegra_sor_writel(sor, value, SOR_CSTM); | 1591 | tegra_sor_writel(sor, value, SOR_CSTM); |
1576 | 1592 | ||
1593 | /* use DP-A protocol */ | ||
1594 | value = tegra_sor_readl(sor, SOR_STATE1); | ||
1595 | value &= ~SOR_STATE_ASY_PROTOCOL_MASK; | ||
1596 | value |= SOR_STATE_ASY_PROTOCOL_DP_A; | ||
1597 | tegra_sor_writel(sor, value, SOR_STATE1); | ||
1598 | |||
1599 | tegra_sor_mode_set(sor, mode, info); | ||
1600 | |||
1577 | /* PWM setup */ | 1601 | /* PWM setup */ |
1578 | err = tegra_sor_setup_pwm(sor, 250); | 1602 | err = tegra_sor_setup_pwm(sor, 250); |
1579 | if (err < 0) | 1603 | if (err < 0) |
@@ -1789,11 +1813,11 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) | |||
1789 | struct tegra_output *output = encoder_to_output(encoder); | 1813 | struct tegra_output *output = encoder_to_output(encoder); |
1790 | unsigned int h_ref_to_sync = 1, pulse_start, max_ac; | 1814 | unsigned int h_ref_to_sync = 1, pulse_start, max_ac; |
1791 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | 1815 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); |
1792 | unsigned int vbe, vse, hbe, hse, vbs, hbs, div; | ||
1793 | struct tegra_sor_hdmi_settings *settings; | 1816 | struct tegra_sor_hdmi_settings *settings; |
1794 | struct tegra_sor *sor = to_sor(output); | 1817 | struct tegra_sor *sor = to_sor(output); |
1795 | struct drm_display_mode *mode; | 1818 | struct drm_display_mode *mode; |
1796 | struct drm_display_info *info; | 1819 | struct drm_display_info *info; |
1820 | unsigned int div; | ||
1797 | u32 value; | 1821 | u32 value; |
1798 | int err; | 1822 | int err; |
1799 | 1823 | ||
@@ -2051,83 +2075,19 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) | |||
2051 | if (err < 0) | 2075 | if (err < 0) |
2052 | dev_err(sor->dev, "failed to power up SOR: %d\n", err); | 2076 | dev_err(sor->dev, "failed to power up SOR: %d\n", err); |
2053 | 2077 | ||
2054 | /* configure mode */ | 2078 | /* configure dynamic range of output */ |
2055 | value = tegra_sor_readl(sor, SOR_STATE1); | ||
2056 | value &= ~SOR_STATE_ASY_PIXELDEPTH_MASK; | ||
2057 | value &= ~SOR_STATE_ASY_CRC_MODE_MASK; | ||
2058 | value &= ~SOR_STATE_ASY_OWNER_MASK; | ||
2059 | |||
2060 | value |= SOR_STATE_ASY_CRC_MODE_COMPLETE | | ||
2061 | SOR_STATE_ASY_OWNER(dc->pipe + 1); | ||
2062 | |||
2063 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) | ||
2064 | value &= ~SOR_STATE_ASY_HSYNCPOL; | ||
2065 | |||
2066 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
2067 | value |= SOR_STATE_ASY_HSYNCPOL; | ||
2068 | |||
2069 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) | ||
2070 | value &= ~SOR_STATE_ASY_VSYNCPOL; | ||
2071 | |||
2072 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
2073 | value |= SOR_STATE_ASY_VSYNCPOL; | ||
2074 | |||
2075 | switch (info->bpc) { | ||
2076 | case 8: | ||
2077 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444; | ||
2078 | break; | ||
2079 | |||
2080 | case 6: | ||
2081 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444; | ||
2082 | break; | ||
2083 | |||
2084 | default: | ||
2085 | BUG(); | ||
2086 | break; | ||
2087 | } | ||
2088 | |||
2089 | tegra_sor_writel(sor, value, SOR_STATE1); | ||
2090 | |||
2091 | value = tegra_sor_readl(sor, SOR_HEAD_STATE0(dc->pipe)); | 2079 | value = tegra_sor_readl(sor, SOR_HEAD_STATE0(dc->pipe)); |
2092 | value &= ~SOR_HEAD_STATE_RANGECOMPRESS_MASK; | 2080 | value &= ~SOR_HEAD_STATE_RANGECOMPRESS_MASK; |
2093 | value &= ~SOR_HEAD_STATE_DYNRANGE_MASK; | 2081 | value &= ~SOR_HEAD_STATE_DYNRANGE_MASK; |
2094 | tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe)); | 2082 | tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe)); |
2095 | 2083 | ||
2084 | /* configure colorspace */ | ||
2096 | value = tegra_sor_readl(sor, SOR_HEAD_STATE0(dc->pipe)); | 2085 | value = tegra_sor_readl(sor, SOR_HEAD_STATE0(dc->pipe)); |
2097 | value &= ~SOR_HEAD_STATE_COLORSPACE_MASK; | 2086 | value &= ~SOR_HEAD_STATE_COLORSPACE_MASK; |
2098 | value |= SOR_HEAD_STATE_COLORSPACE_RGB; | 2087 | value |= SOR_HEAD_STATE_COLORSPACE_RGB; |
2099 | tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe)); | 2088 | tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe)); |
2100 | 2089 | ||
2101 | /* | 2090 | tegra_sor_mode_set(sor, mode, info); |
2102 | * TODO: The video timing programming below doesn't seem to match the | ||
2103 | * register definitions. | ||
2104 | */ | ||
2105 | |||
2106 | value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff); | ||
2107 | tegra_sor_writel(sor, value, SOR_HEAD_STATE1(dc->pipe)); | ||
2108 | |||
2109 | /* sync end = sync width - 1 */ | ||
2110 | vse = mode->vsync_end - mode->vsync_start - 1; | ||
2111 | hse = mode->hsync_end - mode->hsync_start - 1; | ||
2112 | |||
2113 | value = ((vse & 0x7fff) << 16) | (hse & 0x7fff); | ||
2114 | tegra_sor_writel(sor, value, SOR_HEAD_STATE2(dc->pipe)); | ||
2115 | |||
2116 | /* blank end = sync end + back porch */ | ||
2117 | vbe = vse + (mode->vtotal - mode->vsync_end); | ||
2118 | hbe = hse + (mode->htotal - mode->hsync_end); | ||
2119 | |||
2120 | value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff); | ||
2121 | tegra_sor_writel(sor, value, SOR_HEAD_STATE3(dc->pipe)); | ||
2122 | |||
2123 | /* blank start = blank end + active */ | ||
2124 | vbs = vbe + mode->vdisplay; | ||
2125 | hbs = hbe + mode->hdisplay; | ||
2126 | |||
2127 | value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff); | ||
2128 | tegra_sor_writel(sor, value, SOR_HEAD_STATE4(dc->pipe)); | ||
2129 | |||
2130 | tegra_sor_writel(sor, 0x1, SOR_HEAD_STATE5(dc->pipe)); | ||
2131 | 2091 | ||
2132 | tegra_sor_update(sor); | 2092 | tegra_sor_update(sor); |
2133 | 2093 | ||