blob: d7ebac6619a3f68be2bb60e48e95d4bb8f326f88 [file] [log] [blame]
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001/*
2 * Copyright © 2006-2016 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include "intel_drv.h"
25
26struct intel_shared_dpll *
27intel_crtc_to_shared_dpll(struct intel_crtc *crtc)
28{
29 struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
30
31 if (crtc->config->shared_dpll < 0)
32 return NULL;
33
34 return &dev_priv->shared_dplls[crtc->config->shared_dpll];
35}
36
37/* For ILK+ */
38void assert_shared_dpll(struct drm_i915_private *dev_priv,
39 struct intel_shared_dpll *pll,
40 bool state)
41{
42 bool cur_state;
43 struct intel_dpll_hw_state hw_state;
44
45 if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
46 return;
47
48 cur_state = pll->get_hw_state(dev_priv, pll, &hw_state);
49 I915_STATE_WARN(cur_state != state,
50 "%s assertion failure (expected %s, current %s)\n",
51 pll->name, onoff(state), onoff(cur_state));
52}
53
54void intel_prepare_shared_dpll(struct intel_crtc *crtc)
55{
56 struct drm_device *dev = crtc->base.dev;
57 struct drm_i915_private *dev_priv = dev->dev_private;
58 struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
59
60 if (WARN_ON(pll == NULL))
61 return;
62
63 WARN_ON(!pll->config.crtc_mask);
64 if (pll->active == 0) {
65 DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
66 WARN_ON(pll->on);
67 assert_shared_dpll_disabled(dev_priv, pll);
68
69 pll->mode_set(dev_priv, pll);
70 }
71}
72
73/**
74 * intel_enable_shared_dpll - enable PCH PLL
75 * @dev_priv: i915 private structure
76 * @pipe: pipe PLL to enable
77 *
78 * The PCH PLL needs to be enabled before the PCH transcoder, since it
79 * drives the transcoder clock.
80 */
81void intel_enable_shared_dpll(struct intel_crtc *crtc)
82{
83 struct drm_device *dev = crtc->base.dev;
84 struct drm_i915_private *dev_priv = dev->dev_private;
85 struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
86
87 if (WARN_ON(pll == NULL))
88 return;
89
90 if (WARN_ON(pll->config.crtc_mask == 0))
91 return;
92
93 DRM_DEBUG_KMS("enable %s (active %d, on? %d) for crtc %d\n",
94 pll->name, pll->active, pll->on,
95 crtc->base.base.id);
96
97 if (pll->active++) {
98 WARN_ON(!pll->on);
99 assert_shared_dpll_enabled(dev_priv, pll);
100 return;
101 }
102 WARN_ON(pll->on);
103
104 intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
105
106 DRM_DEBUG_KMS("enabling %s\n", pll->name);
107 pll->enable(dev_priv, pll);
108 pll->on = true;
109}
110
111void intel_disable_shared_dpll(struct intel_crtc *crtc)
112{
113 struct drm_device *dev = crtc->base.dev;
114 struct drm_i915_private *dev_priv = dev->dev_private;
115 struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
116
117 /* PCH only available on ILK+ */
118 if (INTEL_INFO(dev)->gen < 5)
119 return;
120
121 if (pll == NULL)
122 return;
123
124 if (WARN_ON(!(pll->config.crtc_mask & (1 << drm_crtc_index(&crtc->base)))))
125 return;
126
127 DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n",
128 pll->name, pll->active, pll->on,
129 crtc->base.base.id);
130
131 if (WARN_ON(pll->active == 0)) {
132 assert_shared_dpll_disabled(dev_priv, pll);
133 return;
134 }
135
136 assert_shared_dpll_enabled(dev_priv, pll);
137 WARN_ON(!pll->on);
138 if (--pll->active)
139 return;
140
141 DRM_DEBUG_KMS("disabling %s\n", pll->name);
142 pll->disable(dev_priv, pll);
143 pll->on = false;
144
145 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
146}
147
148struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
149 struct intel_crtc_state *crtc_state)
150{
151 struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
152 struct intel_shared_dpll *pll;
153 struct intel_shared_dpll_config *shared_dpll;
154 enum intel_dpll_id i;
155 int max = dev_priv->num_shared_dpll;
156
157 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
158
159 if (HAS_PCH_IBX(dev_priv->dev)) {
160 /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
161 i = (enum intel_dpll_id) crtc->pipe;
162 pll = &dev_priv->shared_dplls[i];
163
164 DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
165 crtc->base.base.id, pll->name);
166
167 WARN_ON(shared_dpll[i].crtc_mask);
168
169 goto found;
170 }
171
172 if (IS_BROXTON(dev_priv->dev)) {
173 /* PLL is attached to port in bxt */
174 struct intel_encoder *encoder;
175 struct intel_digital_port *intel_dig_port;
176
177 encoder = intel_ddi_get_crtc_new_encoder(crtc_state);
178 if (WARN_ON(!encoder))
179 return NULL;
180
181 intel_dig_port = enc_to_dig_port(&encoder->base);
182 /* 1:1 mapping between ports and PLLs */
183 i = (enum intel_dpll_id)intel_dig_port->port;
184 pll = &dev_priv->shared_dplls[i];
185 DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
186 crtc->base.base.id, pll->name);
187 WARN_ON(shared_dpll[i].crtc_mask);
188
189 goto found;
190 } else if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv))
191 /* Do not consider SPLL */
192 max = 2;
193
194 for (i = 0; i < max; i++) {
195 pll = &dev_priv->shared_dplls[i];
196
197 /* Only want to check enabled timings first */
198 if (shared_dpll[i].crtc_mask == 0)
199 continue;
200
201 if (memcmp(&crtc_state->dpll_hw_state,
202 &shared_dpll[i].hw_state,
203 sizeof(crtc_state->dpll_hw_state)) == 0) {
204 DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n",
205 crtc->base.base.id, pll->name,
206 shared_dpll[i].crtc_mask,
207 pll->active);
208 goto found;
209 }
210 }
211
212 /* Ok no matching timings, maybe there's a free one? */
213 for (i = 0; i < dev_priv->num_shared_dpll; i++) {
214 pll = &dev_priv->shared_dplls[i];
215 if (shared_dpll[i].crtc_mask == 0) {
216 DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
217 crtc->base.base.id, pll->name);
218 goto found;
219 }
220 }
221
222 return NULL;
223
224found:
225 if (shared_dpll[i].crtc_mask == 0)
226 shared_dpll[i].hw_state =
227 crtc_state->dpll_hw_state;
228
229 crtc_state->shared_dpll = i;
230 DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
231 pipe_name(crtc->pipe));
232
233 shared_dpll[i].crtc_mask |= 1 << crtc->pipe;
234
235 return pll;
236}
237
238void intel_shared_dpll_commit(struct drm_atomic_state *state)
239{
240 struct drm_i915_private *dev_priv = to_i915(state->dev);
241 struct intel_shared_dpll_config *shared_dpll;
242 struct intel_shared_dpll *pll;
243 enum intel_dpll_id i;
244
245 if (!to_intel_atomic_state(state)->dpll_set)
246 return;
247
248 shared_dpll = to_intel_atomic_state(state)->shared_dpll;
249 for (i = 0; i < dev_priv->num_shared_dpll; i++) {
250 pll = &dev_priv->shared_dplls[i];
251 pll->config = shared_dpll[i];
252 }
253}
254
255static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
256 struct intel_shared_dpll *pll,
257 struct intel_dpll_hw_state *hw_state)
258{
259 uint32_t val;
260
261 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
262 return false;
263
264 val = I915_READ(PCH_DPLL(pll->id));
265 hw_state->dpll = val;
266 hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
267 hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
268
269 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
270
271 return val & DPLL_VCO_ENABLE;
272}
273
274static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
275 struct intel_shared_dpll *pll)
276{
277 I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0);
278 I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1);
279}
280
281static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
282{
283 u32 val;
284 bool enabled;
285
286 I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev)));
287
288 val = I915_READ(PCH_DREF_CONTROL);
289 enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
290 DREF_SUPERSPREAD_SOURCE_MASK));
291 I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
292}
293
294static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
295 struct intel_shared_dpll *pll)
296{
297 /* PCH refclock must be enabled first */
298 ibx_assert_pch_refclk_enabled(dev_priv);
299
300 I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
301
302 /* Wait for the clocks to stabilize. */
303 POSTING_READ(PCH_DPLL(pll->id));
304 udelay(150);
305
306 /* The pixel multiplier can only be updated once the
307 * DPLL is enabled and the clocks are stable.
308 *
309 * So write it again.
310 */
311 I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
312 POSTING_READ(PCH_DPLL(pll->id));
313 udelay(200);
314}
315
316static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
317 struct intel_shared_dpll *pll)
318{
319 struct drm_device *dev = dev_priv->dev;
320 struct intel_crtc *crtc;
321
322 /* Make sure no transcoder isn't still depending on us. */
323 for_each_intel_crtc(dev, crtc) {
324 if (intel_crtc_to_shared_dpll(crtc) == pll)
325 assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
326 }
327
328 I915_WRITE(PCH_DPLL(pll->id), 0);
329 POSTING_READ(PCH_DPLL(pll->id));
330 udelay(200);
331}
332
333static char *ibx_pch_dpll_names[] = {
334 "PCH DPLL A",
335 "PCH DPLL B",
336};
337
338static void ibx_pch_dpll_init(struct drm_device *dev)
339{
340 struct drm_i915_private *dev_priv = dev->dev_private;
341 int i;
342
343 dev_priv->num_shared_dpll = 2;
344
345 for (i = 0; i < dev_priv->num_shared_dpll; i++) {
346 dev_priv->shared_dplls[i].id = i;
347 dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i];
348 dev_priv->shared_dplls[i].mode_set = ibx_pch_dpll_mode_set;
349 dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable;
350 dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable;
351 dev_priv->shared_dplls[i].get_hw_state =
352 ibx_pch_dpll_get_hw_state;
353 }
354}
355
356void intel_shared_dpll_init(struct drm_device *dev)
357{
358 struct drm_i915_private *dev_priv = dev->dev_private;
359
360 if (HAS_DDI(dev))
361 intel_ddi_pll_init(dev);
362 else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
363 ibx_pch_dpll_init(dev);
364 else
365 dev_priv->num_shared_dpll = 0;
366
367 BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
368}