diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 344 |
1 files changed, 206 insertions, 138 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 5db0b5552e39..b63d4fa204a3 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -28,87 +28,103 @@ | |||
28 | #include "i915_drv.h" | 28 | #include "i915_drv.h" |
29 | #include "intel_drv.h" | 29 | #include "intel_drv.h" |
30 | 30 | ||
31 | struct ddi_buf_trans { | ||
32 | u32 trans1; /* balance leg enable, de-emph level */ | ||
33 | u32 trans2; /* vref sel, vswing */ | ||
34 | }; | ||
35 | |||
31 | /* HDMI/DVI modes ignore everything but the last 2 items. So we share | 36 | /* 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 | 37 | * them for both DP and FDI transports, allowing those ports to |
33 | * automatically adapt to HDMI connections as well | 38 | * automatically adapt to HDMI connections as well |
34 | */ | 39 | */ |
35 | static const u32 hsw_ddi_translations_dp[] = { | 40 | static const struct ddi_buf_trans hsw_ddi_translations_dp[] = { |
36 | 0x00FFFFFF, 0x0006000E, /* DP parameters */ | 41 | { 0x00FFFFFF, 0x0006000E }, |
37 | 0x00D75FFF, 0x0005000A, | 42 | { 0x00D75FFF, 0x0005000A }, |
38 | 0x00C30FFF, 0x00040006, | 43 | { 0x00C30FFF, 0x00040006 }, |
39 | 0x80AAAFFF, 0x000B0000, | 44 | { 0x80AAAFFF, 0x000B0000 }, |
40 | 0x00FFFFFF, 0x0005000A, | 45 | { 0x00FFFFFF, 0x0005000A }, |
41 | 0x00D75FFF, 0x000C0004, | 46 | { 0x00D75FFF, 0x000C0004 }, |
42 | 0x80C30FFF, 0x000B0000, | 47 | { 0x80C30FFF, 0x000B0000 }, |
43 | 0x00FFFFFF, 0x00040006, | 48 | { 0x00FFFFFF, 0x00040006 }, |
44 | 0x80D75FFF, 0x000B0000, | 49 | { 0x80D75FFF, 0x000B0000 }, |
45 | }; | 50 | }; |
46 | 51 | ||
47 | static const u32 hsw_ddi_translations_fdi[] = { | 52 | static const struct ddi_buf_trans hsw_ddi_translations_fdi[] = { |
48 | 0x00FFFFFF, 0x0007000E, /* FDI parameters */ | 53 | { 0x00FFFFFF, 0x0007000E }, |
49 | 0x00D75FFF, 0x000F000A, | 54 | { 0x00D75FFF, 0x000F000A }, |
50 | 0x00C30FFF, 0x00060006, | 55 | { 0x00C30FFF, 0x00060006 }, |
51 | 0x00AAAFFF, 0x001E0000, | 56 | { 0x00AAAFFF, 0x001E0000 }, |
52 | 0x00FFFFFF, 0x000F000A, | 57 | { 0x00FFFFFF, 0x000F000A }, |
53 | 0x00D75FFF, 0x00160004, | 58 | { 0x00D75FFF, 0x00160004 }, |
54 | 0x00C30FFF, 0x001E0000, | 59 | { 0x00C30FFF, 0x001E0000 }, |
55 | 0x00FFFFFF, 0x00060006, | 60 | { 0x00FFFFFF, 0x00060006 }, |
56 | 0x00D75FFF, 0x001E0000, | 61 | { 0x00D75FFF, 0x001E0000 }, |
57 | }; | 62 | }; |
58 | 63 | ||
59 | static const u32 hsw_ddi_translations_hdmi[] = { | 64 | static const struct ddi_buf_trans hsw_ddi_translations_hdmi[] = { |
60 | /* Idx NT mV diff T mV diff db */ | 65 | /* Idx NT mV d T mV d db */ |
61 | 0x00FFFFFF, 0x0006000E, /* 0: 400 400 0 */ | 66 | { 0x00FFFFFF, 0x0006000E }, /* 0: 400 400 0 */ |
62 | 0x00E79FFF, 0x000E000C, /* 1: 400 500 2 */ | 67 | { 0x00E79FFF, 0x000E000C }, /* 1: 400 500 2 */ |
63 | 0x00D75FFF, 0x0005000A, /* 2: 400 600 3.5 */ | 68 | { 0x00D75FFF, 0x0005000A }, /* 2: 400 600 3.5 */ |
64 | 0x00FFFFFF, 0x0005000A, /* 3: 600 600 0 */ | 69 | { 0x00FFFFFF, 0x0005000A }, /* 3: 600 600 0 */ |
65 | 0x00E79FFF, 0x001D0007, /* 4: 600 750 2 */ | 70 | { 0x00E79FFF, 0x001D0007 }, /* 4: 600 750 2 */ |
66 | 0x00D75FFF, 0x000C0004, /* 5: 600 900 3.5 */ | 71 | { 0x00D75FFF, 0x000C0004 }, /* 5: 600 900 3.5 */ |
67 | 0x00FFFFFF, 0x00040006, /* 6: 800 800 0 */ | 72 | { 0x00FFFFFF, 0x00040006 }, /* 6: 800 800 0 */ |
68 | 0x80E79FFF, 0x00030002, /* 7: 800 1000 2 */ | 73 | { 0x80E79FFF, 0x00030002 }, /* 7: 800 1000 2 */ |
69 | 0x00FFFFFF, 0x00140005, /* 8: 850 850 0 */ | 74 | { 0x00FFFFFF, 0x00140005 }, /* 8: 850 850 0 */ |
70 | 0x00FFFFFF, 0x000C0004, /* 9: 900 900 0 */ | 75 | { 0x00FFFFFF, 0x000C0004 }, /* 9: 900 900 0 */ |
71 | 0x00FFFFFF, 0x001C0003, /* 10: 950 950 0 */ | 76 | { 0x00FFFFFF, 0x001C0003 }, /* 10: 950 950 0 */ |
72 | 0x80FFFFFF, 0x00030002, /* 11: 1000 1000 0 */ | 77 | { 0x80FFFFFF, 0x00030002 }, /* 11: 1000 1000 0 */ |
73 | }; | 78 | }; |
74 | 79 | ||
75 | static const u32 bdw_ddi_translations_edp[] = { | 80 | static const struct ddi_buf_trans bdw_ddi_translations_edp[] = { |
76 | 0x00FFFFFF, 0x00000012, /* eDP parameters */ | 81 | { 0x00FFFFFF, 0x00000012 }, |
77 | 0x00EBAFFF, 0x00020011, | 82 | { 0x00EBAFFF, 0x00020011 }, |
78 | 0x00C71FFF, 0x0006000F, | 83 | { 0x00C71FFF, 0x0006000F }, |
79 | 0x00AAAFFF, 0x000E000A, | 84 | { 0x00AAAFFF, 0x000E000A }, |
80 | 0x00FFFFFF, 0x00020011, | 85 | { 0x00FFFFFF, 0x00020011 }, |
81 | 0x00DB6FFF, 0x0005000F, | 86 | { 0x00DB6FFF, 0x0005000F }, |
82 | 0x00BEEFFF, 0x000A000C, | 87 | { 0x00BEEFFF, 0x000A000C }, |
83 | 0x00FFFFFF, 0x0005000F, | 88 | { 0x00FFFFFF, 0x0005000F }, |
84 | 0x00DB6FFF, 0x000A000C, | 89 | { 0x00DB6FFF, 0x000A000C }, |
85 | 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ | ||
86 | }; | 90 | }; |
87 | 91 | ||
88 | static const u32 bdw_ddi_translations_dp[] = { | 92 | static const struct ddi_buf_trans bdw_ddi_translations_dp[] = { |
89 | 0x00FFFFFF, 0x0007000E, /* DP parameters */ | 93 | { 0x00FFFFFF, 0x0007000E }, |
90 | 0x00D75FFF, 0x000E000A, | 94 | { 0x00D75FFF, 0x000E000A }, |
91 | 0x00BEFFFF, 0x00140006, | 95 | { 0x00BEFFFF, 0x00140006 }, |
92 | 0x80B2CFFF, 0x001B0002, | 96 | { 0x80B2CFFF, 0x001B0002 }, |
93 | 0x00FFFFFF, 0x000E000A, | 97 | { 0x00FFFFFF, 0x000E000A }, |
94 | 0x00D75FFF, 0x00180004, | 98 | { 0x00D75FFF, 0x00180004 }, |
95 | 0x80CB2FFF, 0x001B0002, | 99 | { 0x80CB2FFF, 0x001B0002 }, |
96 | 0x00F7DFFF, 0x00180004, | 100 | { 0x00F7DFFF, 0x00180004 }, |
97 | 0x80D75FFF, 0x001B0002, | 101 | { 0x80D75FFF, 0x001B0002 }, |
98 | 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ | ||
99 | }; | 102 | }; |
100 | 103 | ||
101 | static const u32 bdw_ddi_translations_fdi[] = { | 104 | static const struct ddi_buf_trans bdw_ddi_translations_fdi[] = { |
102 | 0x00FFFFFF, 0x0001000E, /* FDI parameters */ | 105 | { 0x00FFFFFF, 0x0001000E }, |
103 | 0x00D75FFF, 0x0004000A, | 106 | { 0x00D75FFF, 0x0004000A }, |
104 | 0x00C30FFF, 0x00070006, | 107 | { 0x00C30FFF, 0x00070006 }, |
105 | 0x00AAAFFF, 0x000C0000, | 108 | { 0x00AAAFFF, 0x000C0000 }, |
106 | 0x00FFFFFF, 0x0004000A, | 109 | { 0x00FFFFFF, 0x0004000A }, |
107 | 0x00D75FFF, 0x00090004, | 110 | { 0x00D75FFF, 0x00090004 }, |
108 | 0x00C30FFF, 0x000C0000, | 111 | { 0x00C30FFF, 0x000C0000 }, |
109 | 0x00FFFFFF, 0x00070006, | 112 | { 0x00FFFFFF, 0x00070006 }, |
110 | 0x00D75FFF, 0x000C0000, | 113 | { 0x00D75FFF, 0x000C0000 }, |
111 | 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ | 114 | }; |
115 | |||
116 | static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = { | ||
117 | /* Idx NT mV d T mV df db */ | ||
118 | { 0x00FFFFFF, 0x0007000E }, /* 0: 400 400 0 */ | ||
119 | { 0x00D75FFF, 0x000E000A }, /* 1: 400 600 3.5 */ | ||
120 | { 0x00BEFFFF, 0x00140006 }, /* 2: 400 800 6 */ | ||
121 | { 0x00FFFFFF, 0x0009000D }, /* 3: 450 450 0 */ | ||
122 | { 0x00FFFFFF, 0x000E000A }, /* 4: 600 600 0 */ | ||
123 | { 0x00D7FFFF, 0x00140006 }, /* 5: 600 800 2.5 */ | ||
124 | { 0x80CB2FFF, 0x001B0002 }, /* 6: 600 1000 4.5 */ | ||
125 | { 0x00FFFFFF, 0x00140006 }, /* 7: 800 800 0 */ | ||
126 | { 0x80E79FFF, 0x001B0002 }, /* 8: 800 1000 2 */ | ||
127 | { 0x80FFFFFF, 0x001B0002 }, /* 9: 1000 1000 0 */ | ||
112 | }; | 128 | }; |
113 | 129 | ||
114 | enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) | 130 | enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) |
@@ -145,26 +161,36 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) | |||
145 | { | 161 | { |
146 | struct drm_i915_private *dev_priv = dev->dev_private; | 162 | struct drm_i915_private *dev_priv = dev->dev_private; |
147 | u32 reg; | 163 | u32 reg; |
148 | int i; | 164 | int i, n_hdmi_entries, hdmi_800mV_0dB; |
149 | int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; | 165 | int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; |
150 | const u32 *ddi_translations_fdi; | 166 | const struct ddi_buf_trans *ddi_translations_fdi; |
151 | const u32 *ddi_translations_dp; | 167 | const struct ddi_buf_trans *ddi_translations_dp; |
152 | const u32 *ddi_translations_edp; | 168 | const struct ddi_buf_trans *ddi_translations_edp; |
153 | const u32 *ddi_translations; | 169 | const struct ddi_buf_trans *ddi_translations_hdmi; |
170 | const struct ddi_buf_trans *ddi_translations; | ||
154 | 171 | ||
155 | if (IS_BROADWELL(dev)) { | 172 | if (IS_BROADWELL(dev)) { |
156 | ddi_translations_fdi = bdw_ddi_translations_fdi; | 173 | ddi_translations_fdi = bdw_ddi_translations_fdi; |
157 | ddi_translations_dp = bdw_ddi_translations_dp; | 174 | ddi_translations_dp = bdw_ddi_translations_dp; |
158 | ddi_translations_edp = bdw_ddi_translations_edp; | 175 | ddi_translations_edp = bdw_ddi_translations_edp; |
176 | ddi_translations_hdmi = bdw_ddi_translations_hdmi; | ||
177 | n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); | ||
178 | hdmi_800mV_0dB = 7; | ||
159 | } else if (IS_HASWELL(dev)) { | 179 | } else if (IS_HASWELL(dev)) { |
160 | ddi_translations_fdi = hsw_ddi_translations_fdi; | 180 | ddi_translations_fdi = hsw_ddi_translations_fdi; |
161 | ddi_translations_dp = hsw_ddi_translations_dp; | 181 | ddi_translations_dp = hsw_ddi_translations_dp; |
162 | ddi_translations_edp = hsw_ddi_translations_dp; | 182 | ddi_translations_edp = hsw_ddi_translations_dp; |
183 | ddi_translations_hdmi = hsw_ddi_translations_hdmi; | ||
184 | n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi); | ||
185 | hdmi_800mV_0dB = 6; | ||
163 | } else { | 186 | } else { |
164 | WARN(1, "ddi translation table missing\n"); | 187 | WARN(1, "ddi translation table missing\n"); |
165 | ddi_translations_edp = bdw_ddi_translations_dp; | 188 | ddi_translations_edp = bdw_ddi_translations_dp; |
166 | ddi_translations_fdi = bdw_ddi_translations_fdi; | 189 | ddi_translations_fdi = bdw_ddi_translations_fdi; |
167 | ddi_translations_dp = bdw_ddi_translations_dp; | 190 | ddi_translations_dp = bdw_ddi_translations_dp; |
191 | ddi_translations_hdmi = bdw_ddi_translations_hdmi; | ||
192 | n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); | ||
193 | hdmi_800mV_0dB = 7; | ||
168 | } | 194 | } |
169 | 195 | ||
170 | switch (port) { | 196 | switch (port) { |
@@ -190,14 +216,22 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) | |||
190 | 216 | ||
191 | for (i = 0, reg = DDI_BUF_TRANS(port); | 217 | for (i = 0, reg = DDI_BUF_TRANS(port); |
192 | i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { | 218 | i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { |
193 | I915_WRITE(reg, ddi_translations[i]); | 219 | I915_WRITE(reg, ddi_translations[i].trans1); |
194 | reg += 4; | 220 | reg += 4; |
195 | } | 221 | I915_WRITE(reg, ddi_translations[i].trans2); |
196 | /* Entry 9 is for HDMI: */ | ||
197 | for (i = 0; i < 2; i++) { | ||
198 | I915_WRITE(reg, hsw_ddi_translations_hdmi[hdmi_level * 2 + i]); | ||
199 | reg += 4; | 222 | reg += 4; |
200 | } | 223 | } |
224 | |||
225 | /* Choose a good default if VBT is badly populated */ | ||
226 | if (hdmi_level == HDMI_LEVEL_SHIFT_UNKNOWN || | ||
227 | hdmi_level >= n_hdmi_entries) | ||
228 | hdmi_level = hdmi_800mV_0dB; | ||
229 | |||
230 | /* Entry 9 is for HDMI: */ | ||
231 | I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans1); | ||
232 | reg += 4; | ||
233 | I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans2); | ||
234 | reg += 4; | ||
201 | } | 235 | } |
202 | 236 | ||
203 | /* Program DDI buffers translations for DP. By default, program ports A-D in DP | 237 | /* Program DDI buffers translations for DP. By default, program ports A-D in DP |
@@ -214,18 +248,6 @@ void intel_prepare_ddi(struct drm_device *dev) | |||
214 | intel_prepare_ddi_buffers(dev, port); | 248 | intel_prepare_ddi_buffers(dev, port); |
215 | } | 249 | } |
216 | 250 | ||
217 | static const long hsw_ddi_buf_ctl_values[] = { | ||
218 | DDI_BUF_EMP_400MV_0DB_HSW, | ||
219 | DDI_BUF_EMP_400MV_3_5DB_HSW, | ||
220 | DDI_BUF_EMP_400MV_6DB_HSW, | ||
221 | DDI_BUF_EMP_400MV_9_5DB_HSW, | ||
222 | DDI_BUF_EMP_600MV_0DB_HSW, | ||
223 | DDI_BUF_EMP_600MV_3_5DB_HSW, | ||
224 | DDI_BUF_EMP_600MV_6DB_HSW, | ||
225 | DDI_BUF_EMP_800MV_0DB_HSW, | ||
226 | DDI_BUF_EMP_800MV_3_5DB_HSW | ||
227 | }; | ||
228 | |||
229 | static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, | 251 | static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, |
230 | enum port port) | 252 | enum port port) |
231 | { | 253 | { |
@@ -285,7 +307,7 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) | |||
285 | 307 | ||
286 | /* Start the training iterating through available voltages and emphasis, | 308 | /* Start the training iterating through available voltages and emphasis, |
287 | * testing each value twice. */ | 309 | * testing each value twice. */ |
288 | for (i = 0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values) * 2; i++) { | 310 | for (i = 0; i < ARRAY_SIZE(hsw_ddi_translations_fdi) * 2; i++) { |
289 | /* Configure DP_TP_CTL with auto-training */ | 311 | /* Configure DP_TP_CTL with auto-training */ |
290 | I915_WRITE(DP_TP_CTL(PORT_E), | 312 | I915_WRITE(DP_TP_CTL(PORT_E), |
291 | DP_TP_CTL_FDI_AUTOTRAIN | | 313 | DP_TP_CTL_FDI_AUTOTRAIN | |
@@ -300,7 +322,7 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) | |||
300 | I915_WRITE(DDI_BUF_CTL(PORT_E), | 322 | I915_WRITE(DDI_BUF_CTL(PORT_E), |
301 | DDI_BUF_CTL_ENABLE | | 323 | DDI_BUF_CTL_ENABLE | |
302 | ((intel_crtc->config.fdi_lanes - 1) << 1) | | 324 | ((intel_crtc->config.fdi_lanes - 1) << 1) | |
303 | hsw_ddi_buf_ctl_values[i / 2]); | 325 | DDI_BUF_TRANS_SELECT(i / 2)); |
304 | POSTING_READ(DDI_BUF_CTL(PORT_E)); | 326 | POSTING_READ(DDI_BUF_CTL(PORT_E)); |
305 | 327 | ||
306 | udelay(600); | 328 | udelay(600); |
@@ -375,7 +397,7 @@ void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder) | |||
375 | enc_to_dig_port(&encoder->base); | 397 | enc_to_dig_port(&encoder->base); |
376 | 398 | ||
377 | intel_dp->DP = intel_dig_port->saved_port_bits | | 399 | intel_dp->DP = intel_dig_port->saved_port_bits | |
378 | DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW; | 400 | DDI_BUF_CTL_ENABLE | DDI_BUF_TRANS_SELECT(0); |
379 | intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count); | 401 | intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count); |
380 | 402 | ||
381 | } | 403 | } |
@@ -402,7 +424,7 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc) | |||
402 | } | 424 | } |
403 | 425 | ||
404 | #define LC_FREQ 2700 | 426 | #define LC_FREQ 2700 |
405 | #define LC_FREQ_2K (LC_FREQ * 2000) | 427 | #define LC_FREQ_2K U64_C(LC_FREQ * 2000) |
406 | 428 | ||
407 | #define P_MIN 2 | 429 | #define P_MIN 2 |
408 | #define P_MAX 64 | 430 | #define P_MAX 64 |
@@ -414,7 +436,11 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc) | |||
414 | #define VCO_MIN 2400 | 436 | #define VCO_MIN 2400 |
415 | #define VCO_MAX 4800 | 437 | #define VCO_MAX 4800 |
416 | 438 | ||
417 | #define ABS_DIFF(a, b) ((a > b) ? (a - b) : (b - a)) | 439 | #define abs_diff(a, b) ({ \ |
440 | typeof(a) __a = (a); \ | ||
441 | typeof(b) __b = (b); \ | ||
442 | (void) (&__a == &__b); \ | ||
443 | __a > __b ? (__a - __b) : (__b - __a); }) | ||
418 | 444 | ||
419 | struct wrpll_rnp { | 445 | struct wrpll_rnp { |
420 | unsigned p, n2, r2; | 446 | unsigned p, n2, r2; |
@@ -524,9 +550,9 @@ static void wrpll_update_rnp(uint64_t freq2k, unsigned budget, | |||
524 | */ | 550 | */ |
525 | a = freq2k * budget * p * r2; | 551 | a = freq2k * budget * p * r2; |
526 | b = freq2k * budget * best->p * best->r2; | 552 | b = freq2k * budget * best->p * best->r2; |
527 | diff = ABS_DIFF((freq2k * p * r2), (LC_FREQ_2K * n2)); | 553 | diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2); |
528 | diff_best = ABS_DIFF((freq2k * best->p * best->r2), | 554 | diff_best = abs_diff(freq2k * best->p * best->r2, |
529 | (LC_FREQ_2K * best->n2)); | 555 | LC_FREQ_2K * best->n2); |
530 | c = 1000000 * diff; | 556 | c = 1000000 * diff; |
531 | d = 1000000 * diff_best; | 557 | d = 1000000 * diff_best; |
532 | 558 | ||
@@ -587,8 +613,8 @@ static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, | |||
587 | return (refclk * n * 100) / (p * r); | 613 | return (refclk * n * 100) / (p * r); |
588 | } | 614 | } |
589 | 615 | ||
590 | void intel_ddi_clock_get(struct intel_encoder *encoder, | 616 | static void hsw_ddi_clock_get(struct intel_encoder *encoder, |
591 | struct intel_crtc_config *pipe_config) | 617 | struct intel_crtc_config *pipe_config) |
592 | { | 618 | { |
593 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; | 619 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
594 | int link_clock = 0; | 620 | int link_clock = 0; |
@@ -643,9 +669,15 @@ void intel_ddi_clock_get(struct intel_encoder *encoder, | |||
643 | pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock; | 669 | pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock; |
644 | } | 670 | } |
645 | 671 | ||
672 | void intel_ddi_clock_get(struct intel_encoder *encoder, | ||
673 | struct intel_crtc_config *pipe_config) | ||
674 | { | ||
675 | hsw_ddi_clock_get(encoder, pipe_config); | ||
676 | } | ||
677 | |||
646 | static void | 678 | static void |
647 | intel_ddi_calculate_wrpll(int clock /* in Hz */, | 679 | hsw_ddi_calculate_wrpll(int clock /* in Hz */, |
648 | unsigned *r2_out, unsigned *n2_out, unsigned *p_out) | 680 | unsigned *r2_out, unsigned *n2_out, unsigned *p_out) |
649 | { | 681 | { |
650 | uint64_t freq2k; | 682 | uint64_t freq2k; |
651 | unsigned p, n2, r2; | 683 | unsigned p, n2, r2; |
@@ -708,27 +740,17 @@ intel_ddi_calculate_wrpll(int clock /* in Hz */, | |||
708 | *r2_out = best.r2; | 740 | *r2_out = best.r2; |
709 | } | 741 | } |
710 | 742 | ||
711 | /* | 743 | static bool |
712 | * Tries to find a PLL for the CRTC. If it finds, it increases the refcount and | 744 | hsw_ddi_pll_select(struct intel_crtc *intel_crtc, |
713 | * stores it in intel_crtc->ddi_pll_sel, so other mode sets won't be able to | 745 | struct intel_encoder *intel_encoder, |
714 | * steal the selected PLL. You need to call intel_ddi_pll_enable to actually | 746 | int clock) |
715 | * enable the PLL. | ||
716 | */ | ||
717 | bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) | ||
718 | { | 747 | { |
719 | struct drm_crtc *crtc = &intel_crtc->base; | 748 | if (intel_encoder->type == INTEL_OUTPUT_HDMI) { |
720 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); | ||
721 | int type = intel_encoder->type; | ||
722 | int clock = intel_crtc->config.port_clock; | ||
723 | |||
724 | intel_put_shared_dpll(intel_crtc); | ||
725 | |||
726 | if (type == INTEL_OUTPUT_HDMI) { | ||
727 | struct intel_shared_dpll *pll; | 749 | struct intel_shared_dpll *pll; |
728 | uint32_t val; | 750 | uint32_t val; |
729 | unsigned p, n2, r2; | 751 | unsigned p, n2, r2; |
730 | 752 | ||
731 | intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); | 753 | hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); |
732 | 754 | ||
733 | val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL | | 755 | val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL | |
734 | WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | | 756 | WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | |
@@ -749,6 +771,25 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) | |||
749 | return true; | 771 | return true; |
750 | } | 772 | } |
751 | 773 | ||
774 | |||
775 | /* | ||
776 | * Tries to find a *shared* PLL for the CRTC and store it in | ||
777 | * intel_crtc->ddi_pll_sel. | ||
778 | * | ||
779 | * For private DPLLs, compute_config() should do the selection for us. This | ||
780 | * function should be folded into compute_config() eventually. | ||
781 | */ | ||
782 | bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) | ||
783 | { | ||
784 | struct drm_crtc *crtc = &intel_crtc->base; | ||
785 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); | ||
786 | int clock = intel_crtc->config.port_clock; | ||
787 | |||
788 | intel_put_shared_dpll(intel_crtc); | ||
789 | |||
790 | return hsw_ddi_pll_select(intel_crtc, intel_encoder, clock); | ||
791 | } | ||
792 | |||
752 | void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) | 793 | void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) |
753 | { | 794 | { |
754 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; | 795 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
@@ -1183,31 +1224,52 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder) | |||
1183 | } | 1224 | } |
1184 | } | 1225 | } |
1185 | 1226 | ||
1186 | int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) | 1227 | static int bdw_get_cdclk_freq(struct drm_i915_private *dev_priv) |
1228 | { | ||
1229 | uint32_t lcpll = I915_READ(LCPLL_CTL); | ||
1230 | uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; | ||
1231 | |||
1232 | if (lcpll & LCPLL_CD_SOURCE_FCLK) | ||
1233 | return 800000; | ||
1234 | else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) | ||
1235 | return 450000; | ||
1236 | else if (freq == LCPLL_CLK_FREQ_450) | ||
1237 | return 450000; | ||
1238 | else if (freq == LCPLL_CLK_FREQ_54O_BDW) | ||
1239 | return 540000; | ||
1240 | else if (freq == LCPLL_CLK_FREQ_337_5_BDW) | ||
1241 | return 337500; | ||
1242 | else | ||
1243 | return 675000; | ||
1244 | } | ||
1245 | |||
1246 | static int hsw_get_cdclk_freq(struct drm_i915_private *dev_priv) | ||
1187 | { | 1247 | { |
1188 | struct drm_device *dev = dev_priv->dev; | 1248 | struct drm_device *dev = dev_priv->dev; |
1189 | uint32_t lcpll = I915_READ(LCPLL_CTL); | 1249 | uint32_t lcpll = I915_READ(LCPLL_CTL); |
1190 | uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; | 1250 | uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; |
1191 | 1251 | ||
1192 | if (lcpll & LCPLL_CD_SOURCE_FCLK) { | 1252 | if (lcpll & LCPLL_CD_SOURCE_FCLK) |
1193 | return 800000; | 1253 | return 800000; |
1194 | } else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) { | 1254 | else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) |
1195 | return 450000; | 1255 | return 450000; |
1196 | } else if (freq == LCPLL_CLK_FREQ_450) { | 1256 | else if (freq == LCPLL_CLK_FREQ_450) |
1197 | return 450000; | 1257 | return 450000; |
1198 | } else if (IS_HASWELL(dev)) { | 1258 | else if (IS_ULT(dev)) |
1199 | if (IS_ULT(dev)) | 1259 | return 337500; |
1200 | return 337500; | 1260 | else |
1201 | else | 1261 | return 540000; |
1202 | return 540000; | 1262 | } |
1203 | } else { | 1263 | |
1204 | if (freq == LCPLL_CLK_FREQ_54O_BDW) | 1264 | int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) |
1205 | return 540000; | 1265 | { |
1206 | else if (freq == LCPLL_CLK_FREQ_337_5_BDW) | 1266 | struct drm_device *dev = dev_priv->dev; |
1207 | return 337500; | 1267 | |
1208 | else | 1268 | if (IS_BROADWELL(dev)) |
1209 | return 675000; | 1269 | return bdw_get_cdclk_freq(dev_priv); |
1210 | } | 1270 | |
1271 | /* Haswell */ | ||
1272 | return hsw_get_cdclk_freq(dev_priv); | ||
1211 | } | 1273 | } |
1212 | 1274 | ||
1213 | static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv, | 1275 | static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv, |
@@ -1248,10 +1310,8 @@ static const char * const hsw_ddi_pll_names[] = { | |||
1248 | "WRPLL 2", | 1310 | "WRPLL 2", |
1249 | }; | 1311 | }; |
1250 | 1312 | ||
1251 | void intel_ddi_pll_init(struct drm_device *dev) | 1313 | static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv) |
1252 | { | 1314 | { |
1253 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1254 | uint32_t val = I915_READ(LCPLL_CTL); | ||
1255 | int i; | 1315 | int i; |
1256 | 1316 | ||
1257 | dev_priv->num_shared_dpll = 2; | 1317 | dev_priv->num_shared_dpll = 2; |
@@ -1264,6 +1324,14 @@ void intel_ddi_pll_init(struct drm_device *dev) | |||
1264 | dev_priv->shared_dplls[i].get_hw_state = | 1324 | dev_priv->shared_dplls[i].get_hw_state = |
1265 | hsw_ddi_pll_get_hw_state; | 1325 | hsw_ddi_pll_get_hw_state; |
1266 | } | 1326 | } |
1327 | } | ||
1328 | |||
1329 | void intel_ddi_pll_init(struct drm_device *dev) | ||
1330 | { | ||
1331 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1332 | uint32_t val = I915_READ(LCPLL_CTL); | ||
1333 | |||
1334 | hsw_shared_dplls_init(dev_priv); | ||
1267 | 1335 | ||
1268 | /* The LCPLL register should be turned on by the BIOS. For now let's | 1336 | /* The LCPLL register should be turned on by the BIOS. For now let's |
1269 | * just check its state and print errors in case something is wrong. | 1337 | * just check its state and print errors in case something is wrong. |
@@ -1444,7 +1512,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, | |||
1444 | dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; | 1512 | dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; |
1445 | } | 1513 | } |
1446 | 1514 | ||
1447 | intel_ddi_clock_get(encoder, pipe_config); | 1515 | hsw_ddi_clock_get(encoder, pipe_config); |
1448 | } | 1516 | } |
1449 | 1517 | ||
1450 | static void intel_ddi_destroy(struct drm_encoder *encoder) | 1518 | static void intel_ddi_destroy(struct drm_encoder *encoder) |