2 * Copyright © 2012 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * Eugeni Dodonov <eugeni.dodonov@intel.com>
29 #include "intel_drv.h"
31 /* HDMI/DVI modes ignore everything but the last 2 items. So we share
32 * them for both DP and FDI transports, allowing those ports to
33 * automatically adapt to HDMI connections as well
35 static const u32 hsw_ddi_translations_dp[] = {
36 0x00FFFFFF, 0x0006000E, /* DP parameters */
37 0x00D75FFF, 0x0005000A,
38 0x00C30FFF, 0x00040006,
39 0x80AAAFFF, 0x000B0000,
40 0x00FFFFFF, 0x0005000A,
41 0x00D75FFF, 0x000C0004,
42 0x80C30FFF, 0x000B0000,
43 0x00FFFFFF, 0x00040006,
44 0x80D75FFF, 0x000B0000,
45 0x00FFFFFF, 0x00040006 /* HDMI parameters */
48 static const u32 hsw_ddi_translations_fdi[] = {
49 0x00FFFFFF, 0x0007000E, /* FDI parameters */
50 0x00D75FFF, 0x000F000A,
51 0x00C30FFF, 0x00060006,
52 0x00AAAFFF, 0x001E0000,
53 0x00FFFFFF, 0x000F000A,
54 0x00D75FFF, 0x00160004,
55 0x00C30FFF, 0x001E0000,
56 0x00FFFFFF, 0x00060006,
57 0x00D75FFF, 0x001E0000,
58 0x00FFFFFF, 0x00040006 /* HDMI parameters */
61 /* On Haswell, DDI port buffers must be programmed with correct values
62 * in advance. The buffer values are different for FDI and DP modes,
63 * but the HDMI/DVI fields are shared among those. So we program the DDI
64 * in either FDI or DP modes only, as HDMI connections will work with both
67 void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, bool use_fdi_mode)
69 struct drm_i915_private *dev_priv = dev->dev_private;
72 const u32 *ddi_translations = ((use_fdi_mode) ?
73 hsw_ddi_translations_fdi :
74 hsw_ddi_translations_dp);
76 DRM_DEBUG_DRIVER("Initializing DDI buffers for port %c in %s mode\n",
78 use_fdi_mode ? "FDI" : "DP");
80 WARN((use_fdi_mode && (port != PORT_E)),
81 "Programming port %c in FDI mode, this probably will not work.\n",
84 for (i=0, reg=DDI_BUF_TRANS(port); i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) {
85 I915_WRITE(reg, ddi_translations[i]);
90 /* Program DDI buffers translations for DP. By default, program ports A-D in DP
91 * mode and port E for FDI.
93 void intel_prepare_ddi(struct drm_device *dev)
97 if (IS_HASWELL(dev)) {
98 for (port = PORT_A; port < PORT_E; port++)
99 intel_prepare_ddi_buffers(dev, port, false);
101 /* DDI E is the suggested one to work in FDI mode, so program is as such by
102 * default. It will have to be re-programmed in case a digital DP output
103 * will be detected on it
105 intel_prepare_ddi_buffers(dev, PORT_E, true);
109 static const long hsw_ddi_buf_ctl_values[] = {
110 DDI_BUF_EMP_400MV_0DB_HSW,
111 DDI_BUF_EMP_400MV_3_5DB_HSW,
112 DDI_BUF_EMP_400MV_6DB_HSW,
113 DDI_BUF_EMP_400MV_9_5DB_HSW,
114 DDI_BUF_EMP_600MV_0DB_HSW,
115 DDI_BUF_EMP_600MV_3_5DB_HSW,
116 DDI_BUF_EMP_600MV_6DB_HSW,
117 DDI_BUF_EMP_800MV_0DB_HSW,
118 DDI_BUF_EMP_800MV_3_5DB_HSW
122 /* Starting with Haswell, different DDI ports can work in FDI mode for
123 * connection to the PCH-located connectors. For this, it is necessary to train
124 * both the DDI port and PCH receiver for the desired DDI buffer settings.
126 * The recommended port to work in FDI mode is DDI E, which we use here. Also,
127 * please note that when FDI mode is active on DDI E, it shares 2 lines with
128 * DDI A (which is used for eDP)
131 void hsw_fdi_link_train(struct drm_crtc *crtc)
133 struct drm_device *dev = crtc->dev;
134 struct drm_i915_private *dev_priv = dev->dev_private;
135 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
136 int pipe = intel_crtc->pipe;
139 /* Configure CPU PLL, wait for warmup */
142 SPLL_PLL_FREQ_1350MHz |
145 /* Use SPLL to drive the output when in FDI mode */
146 I915_WRITE(PORT_CLK_SEL(PORT_E),
148 I915_WRITE(PIPE_CLK_SEL(pipe),
149 PIPE_CLK_SEL_PORT(PORT_E));
153 /* Start the training iterating through available voltages and emphasis */
154 for (i=0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values); i++) {
155 /* Configure DP_TP_CTL with auto-training */
156 I915_WRITE(DP_TP_CTL(PORT_E),
157 DP_TP_CTL_FDI_AUTOTRAIN |
158 DP_TP_CTL_ENHANCED_FRAME_ENABLE |
159 DP_TP_CTL_LINK_TRAIN_PAT1 |
162 /* Configure and enable DDI_BUF_CTL for DDI E with next voltage */
163 temp = I915_READ(DDI_BUF_CTL(PORT_E));
164 temp = (temp & ~DDI_BUF_EMP_MASK);
165 I915_WRITE(DDI_BUF_CTL(PORT_E),
169 hsw_ddi_buf_ctl_values[i]);
173 /* Enable CPU FDI Receiver with auto-training */
174 reg = FDI_RX_CTL(pipe);
177 FDI_LINK_TRAIN_AUTO |
179 FDI_LINK_TRAIN_PATTERN_1_CPT |
180 FDI_RX_ENHANCE_FRAME_ENABLE |
181 FDI_PORT_WIDTH_2X_LPT |
186 temp = I915_READ(DP_TP_STATUS(PORT_E));
187 if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) {
188 DRM_DEBUG_DRIVER("BUF_CTL training done on %d step\n", i);
190 /* Enable normal pixel sending for FDI */
191 I915_WRITE(DP_TP_CTL(PORT_E),
192 DP_TP_CTL_FDI_AUTOTRAIN |
193 DP_TP_CTL_LINK_TRAIN_NORMAL |
194 DP_TP_CTL_ENHANCED_FRAME_ENABLE |
197 /* Enable PIPE_DDI_FUNC_CTL for the pipe to work in FDI mode */
198 temp = I915_READ(DDI_FUNC_CTL(pipe));
199 temp &= ~PIPE_DDI_PORT_MASK;
200 temp |= PIPE_DDI_SELECT_PORT(PORT_E) |
201 PIPE_DDI_MODE_SELECT_FDI |
202 PIPE_DDI_FUNC_ENABLE |
203 PIPE_DDI_PORT_WIDTH_X2;
204 I915_WRITE(DDI_FUNC_CTL(pipe),
208 DRM_ERROR("Error training BUF_CTL %d\n", i);
210 /* Disable DP_TP_CTL and FDI_RX_CTL) and retry */
211 I915_WRITE(DP_TP_CTL(PORT_E),
212 I915_READ(DP_TP_CTL(PORT_E)) &
214 I915_WRITE(FDI_RX_CTL(pipe),
215 I915_READ(FDI_RX_CTL(pipe)) &
221 DRM_DEBUG_KMS("FDI train done.\n");
224 /* For DDI connections, it is possible to support different outputs over the
225 * same DDI port, such as HDMI or DP or even VGA via FDI. So we don't know by
226 * the time the output is detected what exactly is on the other end of it. This
227 * function aims at providing support for this detection and proper output
230 void intel_ddi_init(struct drm_device *dev, enum port port)
232 /* For now, we don't do any proper output detection and assume that we
233 * handle HDMI only */
237 /* We don't handle eDP and DP yet */
238 DRM_DEBUG_DRIVER("Found digital output on DDI port A\n");
240 /* Assume that the ports B, C and D are working in HDMI mode for now */
244 intel_hdmi_init(dev, DDI_BUF_CTL(port));
247 DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n",
253 /* WRPLL clock dividers */
254 struct wrpll_tmds_clock {
256 u16 p; /* Post divider */
257 u16 n2; /* Feedback divider */
258 u16 r2; /* Reference divider */
261 /* Table of matching values for WRPLL clocks programming for each frequency */
262 static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
278 {27027, 18, 100, 111},
306 {40541, 22, 147, 89},
316 {44900, 20, 108, 65},
332 {54054, 16, 173, 108},
384 {81081, 6, 100, 111},
429 {108108, 8, 173, 108},
437 {111264, 8, 150, 91},
481 {135250, 6, 167, 111},
504 {148352, 4, 100, 91},
526 {162162, 4, 131, 109},
534 {169000, 4, 104, 83},
581 {202000, 4, 112, 75},
583 {203000, 4, 146, 97},
641 void intel_ddi_mode_set(struct drm_encoder *encoder,
642 struct drm_display_mode *mode,
643 struct drm_display_mode *adjusted_mode)
645 struct drm_device *dev = encoder->dev;
646 struct drm_i915_private *dev_priv = dev->dev_private;
647 struct drm_crtc *crtc = encoder->crtc;
648 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
649 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
650 int port = intel_hdmi->ddi_port;
651 int pipe = intel_crtc->pipe;
652 int p, n2, r2, valid=0;
655 /* On Haswell, we need to enable the clocks and prepare DDI function to
656 * work in HDMI mode for this pipe.
658 DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));
660 for (i=0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++) {
661 if (crtc->mode.clock == wrpll_tmds_clock_table[i].clock) {
662 p = wrpll_tmds_clock_table[i].p;
663 n2 = wrpll_tmds_clock_table[i].n2;
664 r2 = wrpll_tmds_clock_table[i].r2;
666 DRM_DEBUG_KMS("WR PLL clock: found settings for %dKHz refresh rate: p=%d, n2=%d, r2=%d\n",
676 DRM_ERROR("Unable to find WR PLL clock settings for %dKHz refresh rate\n",
681 /* Enable LCPLL if disabled */
682 temp = I915_READ(LCPLL_CTL);
683 if (temp & LCPLL_PLL_DISABLE)
684 I915_WRITE(LCPLL_CTL,
685 temp & ~LCPLL_PLL_DISABLE);
687 /* Configure WR PLL 1, program the correct divider values for
688 * the desired frequency and wait for warmup */
689 I915_WRITE(WRPLL_CTL1,
691 WRPLL_PLL_SELECT_LCPLL_2700 |
692 WRPLL_DIVIDER_REFERENCE(r2) |
693 WRPLL_DIVIDER_FEEDBACK(n2) |
694 WRPLL_DIVIDER_POST(p));
698 /* Use WRPLL1 clock to drive the output to the port, and tell the pipe to use
699 * this port for connection.
701 I915_WRITE(PORT_CLK_SEL(port),
702 PORT_CLK_SEL_WRPLL1);
703 I915_WRITE(PIPE_CLK_SEL(pipe),
704 PIPE_CLK_SEL_PORT(port));
708 if (intel_hdmi->has_audio) {
709 /* Proper support for digital audio needs a new logic and a new set
710 * of registers, so we leave it for future patch bombing.
712 DRM_DEBUG_DRIVER("HDMI audio on pipe %c not yet supported on DDI\n",
713 pipe_name(intel_crtc->pipe));
716 /* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
717 temp = I915_READ(DDI_FUNC_CTL(pipe));
718 temp &= ~PIPE_DDI_PORT_MASK;
719 temp &= ~PIPE_DDI_BPC_12;
720 temp |= PIPE_DDI_SELECT_PORT(port) |
721 PIPE_DDI_MODE_SELECT_HDMI |
722 ((intel_crtc->bpp > 24) ?
725 PIPE_DDI_FUNC_ENABLE;
727 I915_WRITE(DDI_FUNC_CTL(pipe), temp);
729 intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
730 intel_hdmi_set_spd_infoframe(encoder);
733 void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
735 struct drm_device *dev = encoder->dev;
736 struct drm_i915_private *dev_priv = dev->dev_private;
737 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
738 int port = intel_hdmi->ddi_port;
741 temp = I915_READ(DDI_BUF_CTL(port));
743 if (mode != DRM_MODE_DPMS_ON) {
744 temp &= ~DDI_BUF_CTL_ENABLE;
746 temp |= DDI_BUF_CTL_ENABLE;
749 /* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width,
750 * and swing/emphasis values are ignored so nothing special needs
751 * to be done besides enabling the port.
753 I915_WRITE(DDI_BUF_CTL(port),