blob: 0227b1652906cc0ad345863f2ead6c8bce6025dc [file] [log] [blame]
Jesse Barnes79e53942008-11-07 14:24:08 -08001/*
2 * Copyright © 2006-2007 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 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 */
26
27#include <linux/i2c.h>
Shaohua Li7662c8b2009-06-26 11:23:55 +080028#include <linux/kernel.h>
Jesse Barnes79e53942008-11-07 14:24:08 -080029#include "drmP.h"
30#include "intel_drv.h"
31#include "i915_drm.h"
32#include "i915_drv.h"
Keith Packarda4fc5ed2009-04-07 16:16:42 -070033#include "intel_dp.h"
Jesse Barnes79e53942008-11-07 14:24:08 -080034
35#include "drm_crtc_helper.h"
36
Zhenyu Wang32f9d652009-07-24 01:00:32 +080037#define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
38
Jesse Barnes79e53942008-11-07 14:24:08 -080039bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
Shaohua Li7662c8b2009-06-26 11:23:55 +080040static void intel_update_watermarks(struct drm_device *dev);
Jesse Barnes652c3932009-08-17 13:31:43 -070041static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule);
Jesse Barnes79e53942008-11-07 14:24:08 -080042
43typedef struct {
44 /* given values */
45 int n;
46 int m1, m2;
47 int p1, p2;
48 /* derived values */
49 int dot;
50 int vco;
51 int m;
52 int p;
53} intel_clock_t;
54
55typedef struct {
56 int min, max;
57} intel_range_t;
58
59typedef struct {
60 int dot_limit;
61 int p2_slow, p2_fast;
62} intel_p2_t;
63
64#define INTEL_P2_NUM 2
Ma Lingd4906092009-03-18 20:13:27 +080065typedef struct intel_limit intel_limit_t;
66struct intel_limit {
Jesse Barnes79e53942008-11-07 14:24:08 -080067 intel_range_t dot, vco, n, m, m1, m2, p, p1;
68 intel_p2_t p2;
Ma Lingd4906092009-03-18 20:13:27 +080069 bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
70 int, int, intel_clock_t *);
Jesse Barnes652c3932009-08-17 13:31:43 -070071 bool (* find_reduced_pll)(const intel_limit_t *, struct drm_crtc *,
72 int, int, intel_clock_t *);
Ma Lingd4906092009-03-18 20:13:27 +080073};
Jesse Barnes79e53942008-11-07 14:24:08 -080074
75#define I8XX_DOT_MIN 25000
76#define I8XX_DOT_MAX 350000
77#define I8XX_VCO_MIN 930000
78#define I8XX_VCO_MAX 1400000
79#define I8XX_N_MIN 3
80#define I8XX_N_MAX 16
81#define I8XX_M_MIN 96
82#define I8XX_M_MAX 140
83#define I8XX_M1_MIN 18
84#define I8XX_M1_MAX 26
85#define I8XX_M2_MIN 6
86#define I8XX_M2_MAX 16
87#define I8XX_P_MIN 4
88#define I8XX_P_MAX 128
89#define I8XX_P1_MIN 2
90#define I8XX_P1_MAX 33
91#define I8XX_P1_LVDS_MIN 1
92#define I8XX_P1_LVDS_MAX 6
93#define I8XX_P2_SLOW 4
94#define I8XX_P2_FAST 2
95#define I8XX_P2_LVDS_SLOW 14
ling.ma@intel.com0c2e3952009-07-17 11:44:30 +080096#define I8XX_P2_LVDS_FAST 7
Jesse Barnes79e53942008-11-07 14:24:08 -080097#define I8XX_P2_SLOW_LIMIT 165000
98
99#define I9XX_DOT_MIN 20000
100#define I9XX_DOT_MAX 400000
101#define I9XX_VCO_MIN 1400000
102#define I9XX_VCO_MAX 2800000
Shaohua Li21778322009-02-23 15:19:16 +0800103#define IGD_VCO_MIN 1700000
104#define IGD_VCO_MAX 3500000
Kristian Høgsbergf3cade52009-02-13 20:56:50 -0500105#define I9XX_N_MIN 1
106#define I9XX_N_MAX 6
Shaohua Li21778322009-02-23 15:19:16 +0800107/* IGD's Ncounter is a ring counter */
108#define IGD_N_MIN 3
109#define IGD_N_MAX 6
Jesse Barnes79e53942008-11-07 14:24:08 -0800110#define I9XX_M_MIN 70
111#define I9XX_M_MAX 120
Shaohua Li21778322009-02-23 15:19:16 +0800112#define IGD_M_MIN 2
113#define IGD_M_MAX 256
Jesse Barnes79e53942008-11-07 14:24:08 -0800114#define I9XX_M1_MIN 10
Kristian Høgsbergf3cade52009-02-13 20:56:50 -0500115#define I9XX_M1_MAX 22
Jesse Barnes79e53942008-11-07 14:24:08 -0800116#define I9XX_M2_MIN 5
117#define I9XX_M2_MAX 9
Shaohua Li21778322009-02-23 15:19:16 +0800118/* IGD M1 is reserved, and must be 0 */
119#define IGD_M1_MIN 0
120#define IGD_M1_MAX 0
121#define IGD_M2_MIN 0
122#define IGD_M2_MAX 254
Jesse Barnes79e53942008-11-07 14:24:08 -0800123#define I9XX_P_SDVO_DAC_MIN 5
124#define I9XX_P_SDVO_DAC_MAX 80
125#define I9XX_P_LVDS_MIN 7
126#define I9XX_P_LVDS_MAX 98
Shaohua Li21778322009-02-23 15:19:16 +0800127#define IGD_P_LVDS_MIN 7
128#define IGD_P_LVDS_MAX 112
Jesse Barnes79e53942008-11-07 14:24:08 -0800129#define I9XX_P1_MIN 1
130#define I9XX_P1_MAX 8
131#define I9XX_P2_SDVO_DAC_SLOW 10
132#define I9XX_P2_SDVO_DAC_FAST 5
133#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000
134#define I9XX_P2_LVDS_SLOW 14
135#define I9XX_P2_LVDS_FAST 7
136#define I9XX_P2_LVDS_SLOW_LIMIT 112000
137
Ma Ling044c7c42009-03-18 20:13:23 +0800138/*The parameter is for SDVO on G4x platform*/
139#define G4X_DOT_SDVO_MIN 25000
140#define G4X_DOT_SDVO_MAX 270000
141#define G4X_VCO_MIN 1750000
142#define G4X_VCO_MAX 3500000
143#define G4X_N_SDVO_MIN 1
144#define G4X_N_SDVO_MAX 4
145#define G4X_M_SDVO_MIN 104
146#define G4X_M_SDVO_MAX 138
147#define G4X_M1_SDVO_MIN 17
148#define G4X_M1_SDVO_MAX 23
149#define G4X_M2_SDVO_MIN 5
150#define G4X_M2_SDVO_MAX 11
151#define G4X_P_SDVO_MIN 10
152#define G4X_P_SDVO_MAX 30
153#define G4X_P1_SDVO_MIN 1
154#define G4X_P1_SDVO_MAX 3
155#define G4X_P2_SDVO_SLOW 10
156#define G4X_P2_SDVO_FAST 10
157#define G4X_P2_SDVO_LIMIT 270000
158
159/*The parameter is for HDMI_DAC on G4x platform*/
160#define G4X_DOT_HDMI_DAC_MIN 22000
161#define G4X_DOT_HDMI_DAC_MAX 400000
162#define G4X_N_HDMI_DAC_MIN 1
163#define G4X_N_HDMI_DAC_MAX 4
164#define G4X_M_HDMI_DAC_MIN 104
165#define G4X_M_HDMI_DAC_MAX 138
166#define G4X_M1_HDMI_DAC_MIN 16
167#define G4X_M1_HDMI_DAC_MAX 23
168#define G4X_M2_HDMI_DAC_MIN 5
169#define G4X_M2_HDMI_DAC_MAX 11
170#define G4X_P_HDMI_DAC_MIN 5
171#define G4X_P_HDMI_DAC_MAX 80
172#define G4X_P1_HDMI_DAC_MIN 1
173#define G4X_P1_HDMI_DAC_MAX 8
174#define G4X_P2_HDMI_DAC_SLOW 10
175#define G4X_P2_HDMI_DAC_FAST 5
176#define G4X_P2_HDMI_DAC_LIMIT 165000
177
178/*The parameter is for SINGLE_CHANNEL_LVDS on G4x platform*/
179#define G4X_DOT_SINGLE_CHANNEL_LVDS_MIN 20000
180#define G4X_DOT_SINGLE_CHANNEL_LVDS_MAX 115000
181#define G4X_N_SINGLE_CHANNEL_LVDS_MIN 1
182#define G4X_N_SINGLE_CHANNEL_LVDS_MAX 3
183#define G4X_M_SINGLE_CHANNEL_LVDS_MIN 104
184#define G4X_M_SINGLE_CHANNEL_LVDS_MAX 138
185#define G4X_M1_SINGLE_CHANNEL_LVDS_MIN 17
186#define G4X_M1_SINGLE_CHANNEL_LVDS_MAX 23
187#define G4X_M2_SINGLE_CHANNEL_LVDS_MIN 5
188#define G4X_M2_SINGLE_CHANNEL_LVDS_MAX 11
189#define G4X_P_SINGLE_CHANNEL_LVDS_MIN 28
190#define G4X_P_SINGLE_CHANNEL_LVDS_MAX 112
191#define G4X_P1_SINGLE_CHANNEL_LVDS_MIN 2
192#define G4X_P1_SINGLE_CHANNEL_LVDS_MAX 8
193#define G4X_P2_SINGLE_CHANNEL_LVDS_SLOW 14
194#define G4X_P2_SINGLE_CHANNEL_LVDS_FAST 14
195#define G4X_P2_SINGLE_CHANNEL_LVDS_LIMIT 0
196
197/*The parameter is for DUAL_CHANNEL_LVDS on G4x platform*/
198#define G4X_DOT_DUAL_CHANNEL_LVDS_MIN 80000
199#define G4X_DOT_DUAL_CHANNEL_LVDS_MAX 224000
200#define G4X_N_DUAL_CHANNEL_LVDS_MIN 1
201#define G4X_N_DUAL_CHANNEL_LVDS_MAX 3
202#define G4X_M_DUAL_CHANNEL_LVDS_MIN 104
203#define G4X_M_DUAL_CHANNEL_LVDS_MAX 138
204#define G4X_M1_DUAL_CHANNEL_LVDS_MIN 17
205#define G4X_M1_DUAL_CHANNEL_LVDS_MAX 23
206#define G4X_M2_DUAL_CHANNEL_LVDS_MIN 5
207#define G4X_M2_DUAL_CHANNEL_LVDS_MAX 11
208#define G4X_P_DUAL_CHANNEL_LVDS_MIN 14
209#define G4X_P_DUAL_CHANNEL_LVDS_MAX 42
210#define G4X_P1_DUAL_CHANNEL_LVDS_MIN 2
211#define G4X_P1_DUAL_CHANNEL_LVDS_MAX 6
212#define G4X_P2_DUAL_CHANNEL_LVDS_SLOW 7
213#define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7
214#define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0
215
Keith Packarda4fc5ed2009-04-07 16:16:42 -0700216/*The parameter is for DISPLAY PORT on G4x platform*/
217#define G4X_DOT_DISPLAY_PORT_MIN 161670
218#define G4X_DOT_DISPLAY_PORT_MAX 227000
219#define G4X_N_DISPLAY_PORT_MIN 1
220#define G4X_N_DISPLAY_PORT_MAX 2
221#define G4X_M_DISPLAY_PORT_MIN 97
222#define G4X_M_DISPLAY_PORT_MAX 108
223#define G4X_M1_DISPLAY_PORT_MIN 0x10
224#define G4X_M1_DISPLAY_PORT_MAX 0x12
225#define G4X_M2_DISPLAY_PORT_MIN 0x05
226#define G4X_M2_DISPLAY_PORT_MAX 0x06
227#define G4X_P_DISPLAY_PORT_MIN 10
228#define G4X_P_DISPLAY_PORT_MAX 20
229#define G4X_P1_DISPLAY_PORT_MIN 1
230#define G4X_P1_DISPLAY_PORT_MAX 2
231#define G4X_P2_DISPLAY_PORT_SLOW 10
232#define G4X_P2_DISPLAY_PORT_FAST 10
233#define G4X_P2_DISPLAY_PORT_LIMIT 0
234
Zhenyu Wang2c072452009-06-05 15:38:42 +0800235/* IGDNG */
236/* as we calculate clock using (register_value + 2) for
237 N/M1/M2, so here the range value for them is (actual_value-2).
238 */
239#define IGDNG_DOT_MIN 25000
240#define IGDNG_DOT_MAX 350000
241#define IGDNG_VCO_MIN 1760000
242#define IGDNG_VCO_MAX 3510000
243#define IGDNG_N_MIN 1
244#define IGDNG_N_MAX 5
245#define IGDNG_M_MIN 79
246#define IGDNG_M_MAX 118
247#define IGDNG_M1_MIN 12
248#define IGDNG_M1_MAX 23
249#define IGDNG_M2_MIN 5
250#define IGDNG_M2_MAX 9
251#define IGDNG_P_SDVO_DAC_MIN 5
252#define IGDNG_P_SDVO_DAC_MAX 80
253#define IGDNG_P_LVDS_MIN 28
254#define IGDNG_P_LVDS_MAX 112
255#define IGDNG_P1_MIN 1
256#define IGDNG_P1_MAX 8
257#define IGDNG_P2_SDVO_DAC_SLOW 10
258#define IGDNG_P2_SDVO_DAC_FAST 5
259#define IGDNG_P2_LVDS_SLOW 14 /* single channel */
260#define IGDNG_P2_LVDS_FAST 7 /* double channel */
261#define IGDNG_P2_DOT_LIMIT 225000 /* 225Mhz */
262
Ma Lingd4906092009-03-18 20:13:27 +0800263static bool
264intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
265 int target, int refclk, intel_clock_t *best_clock);
266static bool
Jesse Barnes652c3932009-08-17 13:31:43 -0700267intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
268 int target, int refclk, intel_clock_t *best_clock);
269static bool
Ma Lingd4906092009-03-18 20:13:27 +0800270intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
271 int target, int refclk, intel_clock_t *best_clock);
Zhenyu Wang2c072452009-06-05 15:38:42 +0800272static bool
273intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
274 int target, int refclk, intel_clock_t *best_clock);
Jesse Barnes79e53942008-11-07 14:24:08 -0800275
Keith Packarda4fc5ed2009-04-07 16:16:42 -0700276static bool
277intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
278 int target, int refclk, intel_clock_t *best_clock);
Zhenyu Wang5eb08b62009-07-24 01:00:31 +0800279static bool
280intel_find_pll_igdng_dp(const intel_limit_t *, struct drm_crtc *crtc,
281 int target, int refclk, intel_clock_t *best_clock);
Keith Packarda4fc5ed2009-04-07 16:16:42 -0700282
Keith Packarde4b36692009-06-05 19:22:17 -0700283static const intel_limit_t intel_limits_i8xx_dvo = {
Jesse Barnes79e53942008-11-07 14:24:08 -0800284 .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX },
285 .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX },
286 .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX },
287 .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX },
288 .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX },
289 .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX },
290 .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX },
291 .p1 = { .min = I8XX_P1_MIN, .max = I8XX_P1_MAX },
292 .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
293 .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST },
Ma Lingd4906092009-03-18 20:13:27 +0800294 .find_pll = intel_find_best_PLL,
Jesse Barnes652c3932009-08-17 13:31:43 -0700295 .find_reduced_pll = intel_find_best_reduced_PLL,
Keith Packarde4b36692009-06-05 19:22:17 -0700296};
297
298static const intel_limit_t intel_limits_i8xx_lvds = {
Jesse Barnes79e53942008-11-07 14:24:08 -0800299 .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX },
300 .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX },
301 .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX },
302 .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX },
303 .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX },
304 .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX },
305 .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX },
306 .p1 = { .min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX },
307 .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
308 .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST },
Ma Lingd4906092009-03-18 20:13:27 +0800309 .find_pll = intel_find_best_PLL,
Jesse Barnes652c3932009-08-17 13:31:43 -0700310 .find_reduced_pll = intel_find_best_reduced_PLL,
Keith Packarde4b36692009-06-05 19:22:17 -0700311};
312
313static const intel_limit_t intel_limits_i9xx_sdvo = {
Jesse Barnes79e53942008-11-07 14:24:08 -0800314 .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
315 .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX },
316 .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX },
317 .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX },
318 .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX },
319 .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX },
320 .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX },
321 .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX },
322 .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
323 .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
Ma Lingd4906092009-03-18 20:13:27 +0800324 .find_pll = intel_find_best_PLL,
Jesse Barnes652c3932009-08-17 13:31:43 -0700325 .find_reduced_pll = intel_find_best_reduced_PLL,
Keith Packarde4b36692009-06-05 19:22:17 -0700326};
327
328static const intel_limit_t intel_limits_i9xx_lvds = {
Jesse Barnes79e53942008-11-07 14:24:08 -0800329 .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
330 .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX },
331 .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX },
332 .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX },
333 .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX },
334 .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX },
335 .p = { .min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX },
336 .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX },
337 /* The single-channel range is 25-112Mhz, and dual-channel
338 * is 80-224Mhz. Prefer single channel as much as possible.
339 */
340 .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
341 .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST },
Ma Lingd4906092009-03-18 20:13:27 +0800342 .find_pll = intel_find_best_PLL,
Jesse Barnes652c3932009-08-17 13:31:43 -0700343 .find_reduced_pll = intel_find_best_reduced_PLL,
Keith Packarde4b36692009-06-05 19:22:17 -0700344};
345
Ma Ling044c7c42009-03-18 20:13:23 +0800346 /* below parameter and function is for G4X Chipset Family*/
Keith Packarde4b36692009-06-05 19:22:17 -0700347static const intel_limit_t intel_limits_g4x_sdvo = {
Ma Ling044c7c42009-03-18 20:13:23 +0800348 .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX },
349 .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX},
350 .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX },
351 .m = { .min = G4X_M_SDVO_MIN, .max = G4X_M_SDVO_MAX },
352 .m1 = { .min = G4X_M1_SDVO_MIN, .max = G4X_M1_SDVO_MAX },
353 .m2 = { .min = G4X_M2_SDVO_MIN, .max = G4X_M2_SDVO_MAX },
354 .p = { .min = G4X_P_SDVO_MIN, .max = G4X_P_SDVO_MAX },
355 .p1 = { .min = G4X_P1_SDVO_MIN, .max = G4X_P1_SDVO_MAX},
356 .p2 = { .dot_limit = G4X_P2_SDVO_LIMIT,
357 .p2_slow = G4X_P2_SDVO_SLOW,
358 .p2_fast = G4X_P2_SDVO_FAST
359 },
Ma Lingd4906092009-03-18 20:13:27 +0800360 .find_pll = intel_g4x_find_best_PLL,
Jesse Barnes652c3932009-08-17 13:31:43 -0700361 .find_reduced_pll = intel_g4x_find_best_PLL,
Keith Packarde4b36692009-06-05 19:22:17 -0700362};
363
364static const intel_limit_t intel_limits_g4x_hdmi = {
Ma Ling044c7c42009-03-18 20:13:23 +0800365 .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX },
366 .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX},
367 .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX },
368 .m = { .min = G4X_M_HDMI_DAC_MIN, .max = G4X_M_HDMI_DAC_MAX },
369 .m1 = { .min = G4X_M1_HDMI_DAC_MIN, .max = G4X_M1_HDMI_DAC_MAX },
370 .m2 = { .min = G4X_M2_HDMI_DAC_MIN, .max = G4X_M2_HDMI_DAC_MAX },
371 .p = { .min = G4X_P_HDMI_DAC_MIN, .max = G4X_P_HDMI_DAC_MAX },
372 .p1 = { .min = G4X_P1_HDMI_DAC_MIN, .max = G4X_P1_HDMI_DAC_MAX},
373 .p2 = { .dot_limit = G4X_P2_HDMI_DAC_LIMIT,
374 .p2_slow = G4X_P2_HDMI_DAC_SLOW,
375 .p2_fast = G4X_P2_HDMI_DAC_FAST
376 },
Ma Lingd4906092009-03-18 20:13:27 +0800377 .find_pll = intel_g4x_find_best_PLL,
Jesse Barnes652c3932009-08-17 13:31:43 -0700378 .find_reduced_pll = intel_g4x_find_best_PLL,
Keith Packarde4b36692009-06-05 19:22:17 -0700379};
380
381static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
Ma Ling044c7c42009-03-18 20:13:23 +0800382 .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN,
383 .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX },
384 .vco = { .min = G4X_VCO_MIN,
385 .max = G4X_VCO_MAX },
386 .n = { .min = G4X_N_SINGLE_CHANNEL_LVDS_MIN,
387 .max = G4X_N_SINGLE_CHANNEL_LVDS_MAX },
388 .m = { .min = G4X_M_SINGLE_CHANNEL_LVDS_MIN,
389 .max = G4X_M_SINGLE_CHANNEL_LVDS_MAX },
390 .m1 = { .min = G4X_M1_SINGLE_CHANNEL_LVDS_MIN,
391 .max = G4X_M1_SINGLE_CHANNEL_LVDS_MAX },
392 .m2 = { .min = G4X_M2_SINGLE_CHANNEL_LVDS_MIN,
393 .max = G4X_M2_SINGLE_CHANNEL_LVDS_MAX },
394 .p = { .min = G4X_P_SINGLE_CHANNEL_LVDS_MIN,
395 .max = G4X_P_SINGLE_CHANNEL_LVDS_MAX },
396 .p1 = { .min = G4X_P1_SINGLE_CHANNEL_LVDS_MIN,
397 .max = G4X_P1_SINGLE_CHANNEL_LVDS_MAX },
398 .p2 = { .dot_limit = G4X_P2_SINGLE_CHANNEL_LVDS_LIMIT,
399 .p2_slow = G4X_P2_SINGLE_CHANNEL_LVDS_SLOW,
400 .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST
401 },
Ma Lingd4906092009-03-18 20:13:27 +0800402 .find_pll = intel_g4x_find_best_PLL,
Jesse Barnes652c3932009-08-17 13:31:43 -0700403 .find_reduced_pll = intel_g4x_find_best_PLL,
Keith Packarde4b36692009-06-05 19:22:17 -0700404};
405
406static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
Ma Ling044c7c42009-03-18 20:13:23 +0800407 .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN,
408 .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX },
409 .vco = { .min = G4X_VCO_MIN,
410 .max = G4X_VCO_MAX },
411 .n = { .min = G4X_N_DUAL_CHANNEL_LVDS_MIN,
412 .max = G4X_N_DUAL_CHANNEL_LVDS_MAX },
413 .m = { .min = G4X_M_DUAL_CHANNEL_LVDS_MIN,
414 .max = G4X_M_DUAL_CHANNEL_LVDS_MAX },
415 .m1 = { .min = G4X_M1_DUAL_CHANNEL_LVDS_MIN,
416 .max = G4X_M1_DUAL_CHANNEL_LVDS_MAX },
417 .m2 = { .min = G4X_M2_DUAL_CHANNEL_LVDS_MIN,
418 .max = G4X_M2_DUAL_CHANNEL_LVDS_MAX },
419 .p = { .min = G4X_P_DUAL_CHANNEL_LVDS_MIN,
420 .max = G4X_P_DUAL_CHANNEL_LVDS_MAX },
421 .p1 = { .min = G4X_P1_DUAL_CHANNEL_LVDS_MIN,
422 .max = G4X_P1_DUAL_CHANNEL_LVDS_MAX },
423 .p2 = { .dot_limit = G4X_P2_DUAL_CHANNEL_LVDS_LIMIT,
424 .p2_slow = G4X_P2_DUAL_CHANNEL_LVDS_SLOW,
425 .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST
426 },
Ma Lingd4906092009-03-18 20:13:27 +0800427 .find_pll = intel_g4x_find_best_PLL,
Jesse Barnes652c3932009-08-17 13:31:43 -0700428 .find_reduced_pll = intel_g4x_find_best_PLL,
Keith Packarde4b36692009-06-05 19:22:17 -0700429};
430
431static const intel_limit_t intel_limits_g4x_display_port = {
Keith Packarda4fc5ed2009-04-07 16:16:42 -0700432 .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN,
433 .max = G4X_DOT_DISPLAY_PORT_MAX },
434 .vco = { .min = G4X_VCO_MIN,
435 .max = G4X_VCO_MAX},
436 .n = { .min = G4X_N_DISPLAY_PORT_MIN,
437 .max = G4X_N_DISPLAY_PORT_MAX },
438 .m = { .min = G4X_M_DISPLAY_PORT_MIN,
439 .max = G4X_M_DISPLAY_PORT_MAX },
440 .m1 = { .min = G4X_M1_DISPLAY_PORT_MIN,
441 .max = G4X_M1_DISPLAY_PORT_MAX },
442 .m2 = { .min = G4X_M2_DISPLAY_PORT_MIN,
443 .max = G4X_M2_DISPLAY_PORT_MAX },
444 .p = { .min = G4X_P_DISPLAY_PORT_MIN,
445 .max = G4X_P_DISPLAY_PORT_MAX },
446 .p1 = { .min = G4X_P1_DISPLAY_PORT_MIN,
447 .max = G4X_P1_DISPLAY_PORT_MAX},
448 .p2 = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT,
449 .p2_slow = G4X_P2_DISPLAY_PORT_SLOW,
450 .p2_fast = G4X_P2_DISPLAY_PORT_FAST },
451 .find_pll = intel_find_pll_g4x_dp,
Keith Packarde4b36692009-06-05 19:22:17 -0700452};
453
454static const intel_limit_t intel_limits_igd_sdvo = {
Shaohua Li21778322009-02-23 15:19:16 +0800455 .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
456 .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX },
457 .n = { .min = IGD_N_MIN, .max = IGD_N_MAX },
458 .m = { .min = IGD_M_MIN, .max = IGD_M_MAX },
459 .m1 = { .min = IGD_M1_MIN, .max = IGD_M1_MAX },
460 .m2 = { .min = IGD_M2_MIN, .max = IGD_M2_MAX },
461 .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX },
462 .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX },
463 .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
464 .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
Shaohua Li61157072009-04-03 15:24:43 +0800465 .find_pll = intel_find_best_PLL,
Jesse Barnes652c3932009-08-17 13:31:43 -0700466 .find_reduced_pll = intel_find_best_reduced_PLL,
Keith Packarde4b36692009-06-05 19:22:17 -0700467};
468
469static const intel_limit_t intel_limits_igd_lvds = {
Shaohua Li21778322009-02-23 15:19:16 +0800470 .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
471 .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX },
472 .n = { .min = IGD_N_MIN, .max = IGD_N_MAX },
473 .m = { .min = IGD_M_MIN, .max = IGD_M_MAX },
474 .m1 = { .min = IGD_M1_MIN, .max = IGD_M1_MAX },
475 .m2 = { .min = IGD_M2_MIN, .max = IGD_M2_MAX },
476 .p = { .min = IGD_P_LVDS_MIN, .max = IGD_P_LVDS_MAX },
477 .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX },
478 /* IGD only supports single-channel mode. */
479 .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
480 .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW },
Shaohua Li61157072009-04-03 15:24:43 +0800481 .find_pll = intel_find_best_PLL,
Jesse Barnes652c3932009-08-17 13:31:43 -0700482 .find_reduced_pll = intel_find_best_reduced_PLL,
Keith Packarde4b36692009-06-05 19:22:17 -0700483};
484
485static const intel_limit_t intel_limits_igdng_sdvo = {
Zhenyu Wang2c072452009-06-05 15:38:42 +0800486 .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX },
487 .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX },
488 .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX },
489 .m = { .min = IGDNG_M_MIN, .max = IGDNG_M_MAX },
490 .m1 = { .min = IGDNG_M1_MIN, .max = IGDNG_M1_MAX },
491 .m2 = { .min = IGDNG_M2_MIN, .max = IGDNG_M2_MAX },
492 .p = { .min = IGDNG_P_SDVO_DAC_MIN, .max = IGDNG_P_SDVO_DAC_MAX },
493 .p1 = { .min = IGDNG_P1_MIN, .max = IGDNG_P1_MAX },
494 .p2 = { .dot_limit = IGDNG_P2_DOT_LIMIT,
495 .p2_slow = IGDNG_P2_SDVO_DAC_SLOW,
496 .p2_fast = IGDNG_P2_SDVO_DAC_FAST },
497 .find_pll = intel_igdng_find_best_PLL,
Keith Packarde4b36692009-06-05 19:22:17 -0700498};
499
500static const intel_limit_t intel_limits_igdng_lvds = {
Zhenyu Wang2c072452009-06-05 15:38:42 +0800501 .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX },
502 .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX },
503 .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX },
504 .m = { .min = IGDNG_M_MIN, .max = IGDNG_M_MAX },
505 .m1 = { .min = IGDNG_M1_MIN, .max = IGDNG_M1_MAX },
506 .m2 = { .min = IGDNG_M2_MIN, .max = IGDNG_M2_MAX },
507 .p = { .min = IGDNG_P_LVDS_MIN, .max = IGDNG_P_LVDS_MAX },
508 .p1 = { .min = IGDNG_P1_MIN, .max = IGDNG_P1_MAX },
509 .p2 = { .dot_limit = IGDNG_P2_DOT_LIMIT,
510 .p2_slow = IGDNG_P2_LVDS_SLOW,
511 .p2_fast = IGDNG_P2_LVDS_FAST },
512 .find_pll = intel_igdng_find_best_PLL,
Jesse Barnes79e53942008-11-07 14:24:08 -0800513};
514
Zhenyu Wang2c072452009-06-05 15:38:42 +0800515static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc)
516{
517 const intel_limit_t *limit;
518 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
Keith Packarde4b36692009-06-05 19:22:17 -0700519 limit = &intel_limits_igdng_lvds;
Zhenyu Wang2c072452009-06-05 15:38:42 +0800520 else
Keith Packarde4b36692009-06-05 19:22:17 -0700521 limit = &intel_limits_igdng_sdvo;
Zhenyu Wang2c072452009-06-05 15:38:42 +0800522
523 return limit;
524}
525
Ma Ling044c7c42009-03-18 20:13:23 +0800526static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
527{
528 struct drm_device *dev = crtc->dev;
529 struct drm_i915_private *dev_priv = dev->dev_private;
530 const intel_limit_t *limit;
531
532 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
533 if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
534 LVDS_CLKB_POWER_UP)
535 /* LVDS with dual channel */
Keith Packarde4b36692009-06-05 19:22:17 -0700536 limit = &intel_limits_g4x_dual_channel_lvds;
Ma Ling044c7c42009-03-18 20:13:23 +0800537 else
538 /* LVDS with dual channel */
Keith Packarde4b36692009-06-05 19:22:17 -0700539 limit = &intel_limits_g4x_single_channel_lvds;
Ma Ling044c7c42009-03-18 20:13:23 +0800540 } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) ||
541 intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
Keith Packarde4b36692009-06-05 19:22:17 -0700542 limit = &intel_limits_g4x_hdmi;
Ma Ling044c7c42009-03-18 20:13:23 +0800543 } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
Keith Packarde4b36692009-06-05 19:22:17 -0700544 limit = &intel_limits_g4x_sdvo;
Keith Packarda4fc5ed2009-04-07 16:16:42 -0700545 } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) {
Keith Packarde4b36692009-06-05 19:22:17 -0700546 limit = &intel_limits_g4x_display_port;
Ma Ling044c7c42009-03-18 20:13:23 +0800547 } else /* The option is for other outputs */
Keith Packarde4b36692009-06-05 19:22:17 -0700548 limit = &intel_limits_i9xx_sdvo;
Ma Ling044c7c42009-03-18 20:13:23 +0800549
550 return limit;
551}
552
Jesse Barnes79e53942008-11-07 14:24:08 -0800553static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
554{
555 struct drm_device *dev = crtc->dev;
556 const intel_limit_t *limit;
557
Zhenyu Wang2c072452009-06-05 15:38:42 +0800558 if (IS_IGDNG(dev))
559 limit = intel_igdng_limit(crtc);
560 else if (IS_G4X(dev)) {
Ma Ling044c7c42009-03-18 20:13:23 +0800561 limit = intel_g4x_limit(crtc);
Shaohua Li21778322009-02-23 15:19:16 +0800562 } else if (IS_I9XX(dev) && !IS_IGD(dev)) {
Jesse Barnes79e53942008-11-07 14:24:08 -0800563 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
Keith Packarde4b36692009-06-05 19:22:17 -0700564 limit = &intel_limits_i9xx_lvds;
Jesse Barnes79e53942008-11-07 14:24:08 -0800565 else
Keith Packarde4b36692009-06-05 19:22:17 -0700566 limit = &intel_limits_i9xx_sdvo;
Shaohua Li21778322009-02-23 15:19:16 +0800567 } else if (IS_IGD(dev)) {
568 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
Keith Packarde4b36692009-06-05 19:22:17 -0700569 limit = &intel_limits_igd_lvds;
Shaohua Li21778322009-02-23 15:19:16 +0800570 else
Keith Packarde4b36692009-06-05 19:22:17 -0700571 limit = &intel_limits_igd_sdvo;
Jesse Barnes79e53942008-11-07 14:24:08 -0800572 } else {
573 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
Keith Packarde4b36692009-06-05 19:22:17 -0700574 limit = &intel_limits_i8xx_lvds;
Jesse Barnes79e53942008-11-07 14:24:08 -0800575 else
Keith Packarde4b36692009-06-05 19:22:17 -0700576 limit = &intel_limits_i8xx_dvo;
Jesse Barnes79e53942008-11-07 14:24:08 -0800577 }
578 return limit;
579}
580
Shaohua Li21778322009-02-23 15:19:16 +0800581/* m1 is reserved as 0 in IGD, n is a ring counter */
582static void igd_clock(int refclk, intel_clock_t *clock)
Jesse Barnes79e53942008-11-07 14:24:08 -0800583{
Shaohua Li21778322009-02-23 15:19:16 +0800584 clock->m = clock->m2 + 2;
585 clock->p = clock->p1 * clock->p2;
586 clock->vco = refclk * clock->m / clock->n;
587 clock->dot = clock->vco / clock->p;
588}
589
590static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock)
591{
592 if (IS_IGD(dev)) {
593 igd_clock(refclk, clock);
594 return;
595 }
Jesse Barnes79e53942008-11-07 14:24:08 -0800596 clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
597 clock->p = clock->p1 * clock->p2;
598 clock->vco = refclk * clock->m / (clock->n + 2);
599 clock->dot = clock->vco / clock->p;
600}
601
Jesse Barnes79e53942008-11-07 14:24:08 -0800602/**
603 * Returns whether any output on the specified pipe is of the specified type
604 */
605bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
606{
607 struct drm_device *dev = crtc->dev;
608 struct drm_mode_config *mode_config = &dev->mode_config;
609 struct drm_connector *l_entry;
610
611 list_for_each_entry(l_entry, &mode_config->connector_list, head) {
612 if (l_entry->encoder &&
613 l_entry->encoder->crtc == crtc) {
614 struct intel_output *intel_output = to_intel_output(l_entry);
615 if (intel_output->type == type)
616 return true;
617 }
618 }
619 return false;
620}
621
Zhenyu Wang32f9d652009-07-24 01:00:32 +0800622struct drm_connector *
623intel_pipe_get_output (struct drm_crtc *crtc)
624{
625 struct drm_device *dev = crtc->dev;
626 struct drm_mode_config *mode_config = &dev->mode_config;
627 struct drm_connector *l_entry, *ret = NULL;
628
629 list_for_each_entry(l_entry, &mode_config->connector_list, head) {
630 if (l_entry->encoder &&
631 l_entry->encoder->crtc == crtc) {
632 ret = l_entry;
633 break;
634 }
635 }
636 return ret;
637}
638
Jesse Barnes7c04d1d2009-02-23 15:36:40 -0800639#define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0)
Jesse Barnes79e53942008-11-07 14:24:08 -0800640/**
641 * Returns whether the given set of divisors are valid for a given refclk with
642 * the given connectors.
643 */
644
645static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock)
646{
647 const intel_limit_t *limit = intel_limit (crtc);
Shaohua Li21778322009-02-23 15:19:16 +0800648 struct drm_device *dev = crtc->dev;
Jesse Barnes79e53942008-11-07 14:24:08 -0800649
650 if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
651 INTELPllInvalid ("p1 out of range\n");
652 if (clock->p < limit->p.min || limit->p.max < clock->p)
653 INTELPllInvalid ("p out of range\n");
654 if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
655 INTELPllInvalid ("m2 out of range\n");
656 if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
657 INTELPllInvalid ("m1 out of range\n");
Shaohua Li21778322009-02-23 15:19:16 +0800658 if (clock->m1 <= clock->m2 && !IS_IGD(dev))
Jesse Barnes79e53942008-11-07 14:24:08 -0800659 INTELPllInvalid ("m1 <= m2\n");
660 if (clock->m < limit->m.min || limit->m.max < clock->m)
661 INTELPllInvalid ("m out of range\n");
662 if (clock->n < limit->n.min || limit->n.max < clock->n)
663 INTELPllInvalid ("n out of range\n");
664 if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
665 INTELPllInvalid ("vco out of range\n");
666 /* XXX: We may need to be checking "Dot clock" depending on the multiplier,
667 * connector, etc., rather than just a single range.
668 */
669 if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
670 INTELPllInvalid ("dot out of range\n");
671
672 return true;
673}
674
Ma Lingd4906092009-03-18 20:13:27 +0800675static bool
676intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
677 int target, int refclk, intel_clock_t *best_clock)
678
Jesse Barnes79e53942008-11-07 14:24:08 -0800679{
680 struct drm_device *dev = crtc->dev;
681 struct drm_i915_private *dev_priv = dev->dev_private;
682 intel_clock_t clock;
Jesse Barnes79e53942008-11-07 14:24:08 -0800683 int err = target;
684
Bruno Prémontbc5e5712009-08-08 13:01:17 +0200685 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
Florian Mickler832cc282009-07-13 18:40:32 +0800686 (I915_READ(LVDS)) != 0) {
Jesse Barnes79e53942008-11-07 14:24:08 -0800687 /*
688 * For LVDS, if the panel is on, just rely on its current
689 * settings for dual-channel. We haven't figured out how to
690 * reliably set up different single/dual channel state, if we
691 * even can.
692 */
693 if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
694 LVDS_CLKB_POWER_UP)
695 clock.p2 = limit->p2.p2_fast;
696 else
697 clock.p2 = limit->p2.p2_slow;
698 } else {
699 if (target < limit->p2.dot_limit)
700 clock.p2 = limit->p2.p2_slow;
701 else
702 clock.p2 = limit->p2.p2_fast;
703 }
704
705 memset (best_clock, 0, sizeof (*best_clock));
706
Jesse Barnes652c3932009-08-17 13:31:43 -0700707 for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
708 for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
709 clock.m1++) {
710 for (clock.m2 = limit->m2.min;
711 clock.m2 <= limit->m2.max; clock.m2++) {
712 /* m1 is always 0 in IGD */
713 if (clock.m2 >= clock.m1 && !IS_IGD(dev))
714 break;
715 for (clock.n = limit->n.min;
716 clock.n <= limit->n.max; clock.n++) {
Jesse Barnes79e53942008-11-07 14:24:08 -0800717 int this_err;
718
Shaohua Li21778322009-02-23 15:19:16 +0800719 intel_clock(dev, refclk, &clock);
Jesse Barnes79e53942008-11-07 14:24:08 -0800720
721 if (!intel_PLL_is_valid(crtc, &clock))
722 continue;
723
724 this_err = abs(clock.dot - target);
725 if (this_err < err) {
726 *best_clock = clock;
727 err = this_err;
728 }
729 }
730 }
731 }
732 }
733
734 return (err != target);
735}
736
Jesse Barnes652c3932009-08-17 13:31:43 -0700737
738static bool
739intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
740 int target, int refclk, intel_clock_t *best_clock)
741
742{
743 struct drm_device *dev = crtc->dev;
744 intel_clock_t clock;
745 int err = target;
746 bool found = false;
747
748 memcpy(&clock, best_clock, sizeof(intel_clock_t));
749
750 for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
751 for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) {
752 /* m1 is always 0 in IGD */
753 if (clock.m2 >= clock.m1 && !IS_IGD(dev))
754 break;
755 for (clock.n = limit->n.min; clock.n <= limit->n.max;
756 clock.n++) {
757 int this_err;
758
759 intel_clock(dev, refclk, &clock);
760
761 if (!intel_PLL_is_valid(crtc, &clock))
762 continue;
763
764 this_err = abs(clock.dot - target);
765 if (this_err < err) {
766 *best_clock = clock;
767 err = this_err;
768 found = true;
769 }
770 }
771 }
772 }
773
774 return found;
775}
776
Ma Lingd4906092009-03-18 20:13:27 +0800777static bool
778intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
779 int target, int refclk, intel_clock_t *best_clock)
780{
781 struct drm_device *dev = crtc->dev;
782 struct drm_i915_private *dev_priv = dev->dev_private;
783 intel_clock_t clock;
784 int max_n;
785 bool found;
786 /* approximately equals target * 0.00488 */
787 int err_most = (target >> 8) + (target >> 10);
788 found = false;
789
790 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
791 if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
792 LVDS_CLKB_POWER_UP)
793 clock.p2 = limit->p2.p2_fast;
794 else
795 clock.p2 = limit->p2.p2_slow;
796 } else {
797 if (target < limit->p2.dot_limit)
798 clock.p2 = limit->p2.p2_slow;
799 else
800 clock.p2 = limit->p2.p2_fast;
801 }
802
803 memset(best_clock, 0, sizeof(*best_clock));
804 max_n = limit->n.max;
805 /* based on hardware requriment prefer smaller n to precision */
806 for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
Jesse Barnes652c3932009-08-17 13:31:43 -0700807 /* based on hardware requirment prefere larger m1,m2 */
Ma Lingd4906092009-03-18 20:13:27 +0800808 for (clock.m1 = limit->m1.max;
809 clock.m1 >= limit->m1.min; clock.m1--) {
810 for (clock.m2 = limit->m2.max;
811 clock.m2 >= limit->m2.min; clock.m2--) {
812 for (clock.p1 = limit->p1.max;
813 clock.p1 >= limit->p1.min; clock.p1--) {
814 int this_err;
815
Shaohua Li21778322009-02-23 15:19:16 +0800816 intel_clock(dev, refclk, &clock);
Ma Lingd4906092009-03-18 20:13:27 +0800817 if (!intel_PLL_is_valid(crtc, &clock))
818 continue;
819 this_err = abs(clock.dot - target) ;
820 if (this_err < err_most) {
821 *best_clock = clock;
822 err_most = this_err;
823 max_n = clock.n;
824 found = true;
825 }
826 }
827 }
828 }
829 }
Zhenyu Wang2c072452009-06-05 15:38:42 +0800830 return found;
831}
Ma Lingd4906092009-03-18 20:13:27 +0800832
Zhenyu Wang2c072452009-06-05 15:38:42 +0800833static bool
Zhenyu Wang5eb08b62009-07-24 01:00:31 +0800834intel_find_pll_igdng_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
835 int target, int refclk, intel_clock_t *best_clock)
836{
837 struct drm_device *dev = crtc->dev;
838 intel_clock_t clock;
839 if (target < 200000) {
840 clock.n = 1;
841 clock.p1 = 2;
842 clock.p2 = 10;
843 clock.m1 = 12;
844 clock.m2 = 9;
845 } else {
846 clock.n = 2;
847 clock.p1 = 1;
848 clock.p2 = 10;
849 clock.m1 = 14;
850 clock.m2 = 8;
851 }
852 intel_clock(dev, refclk, &clock);
853 memcpy(best_clock, &clock, sizeof(intel_clock_t));
854 return true;
855}
856
857static bool
Zhenyu Wang2c072452009-06-05 15:38:42 +0800858intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
859 int target, int refclk, intel_clock_t *best_clock)
860{
861 struct drm_device *dev = crtc->dev;
862 struct drm_i915_private *dev_priv = dev->dev_private;
863 intel_clock_t clock;
864 int max_n;
865 bool found;
866 int err_most = 47;
867 found = false;
868
Zhenyu Wang32f9d652009-07-24 01:00:32 +0800869 /* eDP has only 2 clock choice, no n/m/p setting */
870 if (HAS_eDP)
871 return true;
872
Zhenyu Wang5eb08b62009-07-24 01:00:31 +0800873 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
874 return intel_find_pll_igdng_dp(limit, crtc, target,
875 refclk, best_clock);
876
Zhenyu Wang2c072452009-06-05 15:38:42 +0800877 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
878 if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
879 LVDS_CLKB_POWER_UP)
880 clock.p2 = limit->p2.p2_fast;
881 else
882 clock.p2 = limit->p2.p2_slow;
883 } else {
884 if (target < limit->p2.dot_limit)
885 clock.p2 = limit->p2.p2_slow;
886 else
887 clock.p2 = limit->p2.p2_fast;
888 }
889
890 memset(best_clock, 0, sizeof(*best_clock));
891 max_n = limit->n.max;
Jesse Barnes652c3932009-08-17 13:31:43 -0700892 for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
893 /* based on hardware requriment prefer smaller n to precision */
894 for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
895 /* based on hardware requirment prefere larger m1,m2 */
896 for (clock.m1 = limit->m1.max;
897 clock.m1 >= limit->m1.min; clock.m1--) {
898 for (clock.m2 = limit->m2.max;
899 clock.m2 >= limit->m2.min; clock.m2--) {
Zhenyu Wang2c072452009-06-05 15:38:42 +0800900 int this_err;
901
902 intel_clock(dev, refclk, &clock);
903 if (!intel_PLL_is_valid(crtc, &clock))
904 continue;
905 this_err = abs((10000 - (target*10000/clock.dot)));
906 if (this_err < err_most) {
907 *best_clock = clock;
908 err_most = this_err;
909 max_n = clock.n;
910 found = true;
911 /* found on first matching */
912 goto out;
913 }
914 }
915 }
916 }
917 }
918out:
Ma Lingd4906092009-03-18 20:13:27 +0800919 return found;
920}
921
Keith Packarda4fc5ed2009-04-07 16:16:42 -0700922/* DisplayPort has only two frequencies, 162MHz and 270MHz */
923static bool
924intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
925 int target, int refclk, intel_clock_t *best_clock)
926{
927 intel_clock_t clock;
928 if (target < 200000) {
Keith Packarda4fc5ed2009-04-07 16:16:42 -0700929 clock.p1 = 2;
930 clock.p2 = 10;
Keith Packardb3d25492009-06-24 23:09:15 -0700931 clock.n = 2;
932 clock.m1 = 23;
933 clock.m2 = 8;
Keith Packarda4fc5ed2009-04-07 16:16:42 -0700934 } else {
Keith Packarda4fc5ed2009-04-07 16:16:42 -0700935 clock.p1 = 1;
936 clock.p2 = 10;
Keith Packardb3d25492009-06-24 23:09:15 -0700937 clock.n = 1;
938 clock.m1 = 14;
939 clock.m2 = 2;
Keith Packarda4fc5ed2009-04-07 16:16:42 -0700940 }
Keith Packardb3d25492009-06-24 23:09:15 -0700941 clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2);
942 clock.p = (clock.p1 * clock.p2);
943 clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p;
Keith Packarda4fc5ed2009-04-07 16:16:42 -0700944 memcpy(best_clock, &clock, sizeof(intel_clock_t));
945 return true;
946}
947
Jesse Barnes79e53942008-11-07 14:24:08 -0800948void
949intel_wait_for_vblank(struct drm_device *dev)
950{
951 /* Wait for 20ms, i.e. one cycle at 50hz. */
Arjan van de Ven580982d2009-03-23 13:36:25 -0700952 mdelay(20);
Jesse Barnes79e53942008-11-07 14:24:08 -0800953}
954
Chris Wilson5c3b82e2009-02-11 13:25:09 +0000955static int
Kristian Høgsberg3c4fdcf2008-12-17 22:14:46 -0500956intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
957 struct drm_framebuffer *old_fb)
Jesse Barnes79e53942008-11-07 14:24:08 -0800958{
959 struct drm_device *dev = crtc->dev;
960 struct drm_i915_private *dev_priv = dev->dev_private;
961 struct drm_i915_master_private *master_priv;
962 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
963 struct intel_framebuffer *intel_fb;
964 struct drm_i915_gem_object *obj_priv;
965 struct drm_gem_object *obj;
966 int pipe = intel_crtc->pipe;
967 unsigned long Start, Offset;
968 int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR);
969 int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
970 int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
Jesse Barnesf5448472009-04-14 14:17:47 -0700971 int dsptileoff = (pipe == 0 ? DSPATILEOFF : DSPBTILEOFF);
Jesse Barnes79e53942008-11-07 14:24:08 -0800972 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
Kristian Høgsberg3c4fdcf2008-12-17 22:14:46 -0500973 u32 dspcntr, alignment;
Chris Wilson5c3b82e2009-02-11 13:25:09 +0000974 int ret;
Jesse Barnes79e53942008-11-07 14:24:08 -0800975
976 /* no fb bound */
977 if (!crtc->fb) {
978 DRM_DEBUG("No FB bound\n");
Chris Wilson5c3b82e2009-02-11 13:25:09 +0000979 return 0;
980 }
981
982 switch (pipe) {
983 case 0:
984 case 1:
985 break;
986 default:
987 DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
988 return -EINVAL;
Jesse Barnes79e53942008-11-07 14:24:08 -0800989 }
990
991 intel_fb = to_intel_framebuffer(crtc->fb);
Jesse Barnes79e53942008-11-07 14:24:08 -0800992 obj = intel_fb->obj;
993 obj_priv = obj->driver_private;
994
Kristian Høgsberg3c4fdcf2008-12-17 22:14:46 -0500995 switch (obj_priv->tiling_mode) {
996 case I915_TILING_NONE:
997 alignment = 64 * 1024;
998 break;
999 case I915_TILING_X:
Chris Wilson2ebed172009-02-11 14:26:30 +00001000 /* pin() will align the object as required by fence */
1001 alignment = 0;
Kristian Høgsberg3c4fdcf2008-12-17 22:14:46 -05001002 break;
1003 case I915_TILING_Y:
1004 /* FIXME: Is this true? */
1005 DRM_ERROR("Y tiled not allowed for scan out buffers\n");
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001006 return -EINVAL;
Kristian Høgsberg3c4fdcf2008-12-17 22:14:46 -05001007 default:
1008 BUG();
1009 }
1010
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001011 mutex_lock(&dev->struct_mutex);
Chris Wilson8c4b8c32009-06-17 22:08:52 +01001012 ret = i915_gem_object_pin(obj, alignment);
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001013 if (ret != 0) {
1014 mutex_unlock(&dev->struct_mutex);
1015 return ret;
1016 }
Kristian Høgsberg3c4fdcf2008-12-17 22:14:46 -05001017
Chris Wilson8c4b8c32009-06-17 22:08:52 +01001018 ret = i915_gem_object_set_to_gtt_domain(obj, 1);
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001019 if (ret != 0) {
Chris Wilson8c4b8c32009-06-17 22:08:52 +01001020 i915_gem_object_unpin(obj);
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001021 mutex_unlock(&dev->struct_mutex);
1022 return ret;
1023 }
Jesse Barnes79e53942008-11-07 14:24:08 -08001024
Chris Wilson8c4b8c32009-06-17 22:08:52 +01001025 /* Pre-i965 needs to install a fence for tiled scan-out */
1026 if (!IS_I965G(dev) &&
1027 obj_priv->fence_reg == I915_FENCE_REG_NONE &&
1028 obj_priv->tiling_mode != I915_TILING_NONE) {
1029 ret = i915_gem_object_get_fence_reg(obj);
1030 if (ret != 0) {
1031 i915_gem_object_unpin(obj);
1032 mutex_unlock(&dev->struct_mutex);
1033 return ret;
1034 }
1035 }
1036
Jesse Barnes79e53942008-11-07 14:24:08 -08001037 dspcntr = I915_READ(dspcntr_reg);
Jesse Barnes712531b2009-01-09 13:56:14 -08001038 /* Mask out pixel format bits in case we change it */
1039 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
Jesse Barnes79e53942008-11-07 14:24:08 -08001040 switch (crtc->fb->bits_per_pixel) {
1041 case 8:
1042 dspcntr |= DISPPLANE_8BPP;
1043 break;
1044 case 16:
1045 if (crtc->fb->depth == 15)
1046 dspcntr |= DISPPLANE_15_16BPP;
1047 else
1048 dspcntr |= DISPPLANE_16BPP;
1049 break;
1050 case 24:
1051 case 32:
1052 dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
1053 break;
1054 default:
1055 DRM_ERROR("Unknown color depth\n");
Chris Wilson8c4b8c32009-06-17 22:08:52 +01001056 i915_gem_object_unpin(obj);
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001057 mutex_unlock(&dev->struct_mutex);
1058 return -EINVAL;
Jesse Barnes79e53942008-11-07 14:24:08 -08001059 }
Jesse Barnesf5448472009-04-14 14:17:47 -07001060 if (IS_I965G(dev)) {
1061 if (obj_priv->tiling_mode != I915_TILING_NONE)
1062 dspcntr |= DISPPLANE_TILED;
1063 else
1064 dspcntr &= ~DISPPLANE_TILED;
1065 }
1066
Zhenyu Wang553bd142009-09-02 10:57:52 +08001067 if (IS_IGDNG(dev))
1068 /* must disable */
1069 dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
1070
Jesse Barnes79e53942008-11-07 14:24:08 -08001071 I915_WRITE(dspcntr_reg, dspcntr);
1072
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001073 Start = obj_priv->gtt_offset;
1074 Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
1075
Jesse Barnes79e53942008-11-07 14:24:08 -08001076 DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001077 I915_WRITE(dspstride, crtc->fb->pitch);
Jesse Barnes79e53942008-11-07 14:24:08 -08001078 if (IS_I965G(dev)) {
1079 I915_WRITE(dspbase, Offset);
1080 I915_READ(dspbase);
1081 I915_WRITE(dspsurf, Start);
1082 I915_READ(dspsurf);
Jesse Barnesf5448472009-04-14 14:17:47 -07001083 I915_WRITE(dsptileoff, (y << 16) | x);
Jesse Barnes79e53942008-11-07 14:24:08 -08001084 } else {
1085 I915_WRITE(dspbase, Start + Offset);
1086 I915_READ(dspbase);
1087 }
1088
Kristian Høgsberg3c4fdcf2008-12-17 22:14:46 -05001089 intel_wait_for_vblank(dev);
1090
1091 if (old_fb) {
1092 intel_fb = to_intel_framebuffer(old_fb);
Jesse Barnes652c3932009-08-17 13:31:43 -07001093 obj_priv = intel_fb->obj->driver_private;
Kristian Høgsberg3c4fdcf2008-12-17 22:14:46 -05001094 i915_gem_object_unpin(intel_fb->obj);
1095 }
Jesse Barnes652c3932009-08-17 13:31:43 -07001096 intel_increase_pllclock(crtc, true);
1097
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001098 mutex_unlock(&dev->struct_mutex);
Jesse Barnes79e53942008-11-07 14:24:08 -08001099
1100 if (!dev->primary->master)
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001101 return 0;
Jesse Barnes79e53942008-11-07 14:24:08 -08001102
1103 master_priv = dev->primary->master->driver_priv;
1104 if (!master_priv->sarea_priv)
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001105 return 0;
Jesse Barnes79e53942008-11-07 14:24:08 -08001106
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001107 if (pipe) {
Jesse Barnes79e53942008-11-07 14:24:08 -08001108 master_priv->sarea_priv->pipeB_x = x;
1109 master_priv->sarea_priv->pipeB_y = y;
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001110 } else {
1111 master_priv->sarea_priv->pipeA_x = x;
1112 master_priv->sarea_priv->pipeA_y = y;
Jesse Barnes79e53942008-11-07 14:24:08 -08001113 }
Chris Wilson5c3b82e2009-02-11 13:25:09 +00001114
1115 return 0;
Jesse Barnes79e53942008-11-07 14:24:08 -08001116}
1117
Zhenyu Wang24f119c2009-07-24 01:00:28 +08001118/* Disable the VGA plane that we never use */
1119static void i915_disable_vga (struct drm_device *dev)
1120{
1121 struct drm_i915_private *dev_priv = dev->dev_private;
1122 u8 sr1;
1123 u32 vga_reg;
1124
1125 if (IS_IGDNG(dev))
1126 vga_reg = CPU_VGACNTRL;
1127 else
1128 vga_reg = VGACNTRL;
1129
1130 if (I915_READ(vga_reg) & VGA_DISP_DISABLE)
1131 return;
1132
1133 I915_WRITE8(VGA_SR_INDEX, 1);
1134 sr1 = I915_READ8(VGA_SR_DATA);
1135 I915_WRITE8(VGA_SR_DATA, sr1 | (1 << 5));
1136 udelay(100);
1137
1138 I915_WRITE(vga_reg, VGA_DISP_DISABLE);
1139}
1140
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001141static void igdng_disable_pll_edp (struct drm_crtc *crtc)
1142{
1143 struct drm_device *dev = crtc->dev;
1144 struct drm_i915_private *dev_priv = dev->dev_private;
1145 u32 dpa_ctl;
1146
1147 DRM_DEBUG("\n");
1148 dpa_ctl = I915_READ(DP_A);
1149 dpa_ctl &= ~DP_PLL_ENABLE;
1150 I915_WRITE(DP_A, dpa_ctl);
1151}
1152
1153static void igdng_enable_pll_edp (struct drm_crtc *crtc)
1154{
1155 struct drm_device *dev = crtc->dev;
1156 struct drm_i915_private *dev_priv = dev->dev_private;
1157 u32 dpa_ctl;
1158
1159 dpa_ctl = I915_READ(DP_A);
1160 dpa_ctl |= DP_PLL_ENABLE;
1161 I915_WRITE(DP_A, dpa_ctl);
1162 udelay(200);
1163}
1164
1165
1166static void igdng_set_pll_edp (struct drm_crtc *crtc, int clock)
1167{
1168 struct drm_device *dev = crtc->dev;
1169 struct drm_i915_private *dev_priv = dev->dev_private;
1170 u32 dpa_ctl;
1171
1172 DRM_DEBUG("eDP PLL enable for clock %d\n", clock);
1173 dpa_ctl = I915_READ(DP_A);
1174 dpa_ctl &= ~DP_PLL_FREQ_MASK;
1175
1176 if (clock < 200000) {
1177 u32 temp;
1178 dpa_ctl |= DP_PLL_FREQ_160MHZ;
1179 /* workaround for 160Mhz:
1180 1) program 0x4600c bits 15:0 = 0x8124
1181 2) program 0x46010 bit 0 = 1
1182 3) program 0x46034 bit 24 = 1
1183 4) program 0x64000 bit 14 = 1
1184 */
1185 temp = I915_READ(0x4600c);
1186 temp &= 0xffff0000;
1187 I915_WRITE(0x4600c, temp | 0x8124);
1188
1189 temp = I915_READ(0x46010);
1190 I915_WRITE(0x46010, temp | 1);
1191
1192 temp = I915_READ(0x46034);
1193 I915_WRITE(0x46034, temp | (1 << 24));
1194 } else {
1195 dpa_ctl |= DP_PLL_FREQ_270MHZ;
1196 }
1197 I915_WRITE(DP_A, dpa_ctl);
1198
1199 udelay(500);
1200}
1201
Zhenyu Wang2c072452009-06-05 15:38:42 +08001202static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
Jesse Barnes79e53942008-11-07 14:24:08 -08001203{
1204 struct drm_device *dev = crtc->dev;
Zhenyu Wang2c072452009-06-05 15:38:42 +08001205 struct drm_i915_private *dev_priv = dev->dev_private;
1206 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1207 int pipe = intel_crtc->pipe;
Shaohua Li7662c8b2009-06-26 11:23:55 +08001208 int plane = intel_crtc->plane;
Zhenyu Wang2c072452009-06-05 15:38:42 +08001209 int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
1210 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
1211 int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
1212 int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR;
1213 int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
1214 int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
1215 int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
1216 int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
1217 int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
1218 int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
Zhenyu Wang249c0e62009-07-24 01:00:29 +08001219 int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ;
Zhenyu Wang2c072452009-06-05 15:38:42 +08001220 int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
1221 int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
1222 int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
1223 int cpu_vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
1224 int cpu_vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
1225 int cpu_vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
1226 int trans_htot_reg = (pipe == 0) ? TRANS_HTOTAL_A : TRANS_HTOTAL_B;
1227 int trans_hblank_reg = (pipe == 0) ? TRANS_HBLANK_A : TRANS_HBLANK_B;
1228 int trans_hsync_reg = (pipe == 0) ? TRANS_HSYNC_A : TRANS_HSYNC_B;
1229 int trans_vtot_reg = (pipe == 0) ? TRANS_VTOTAL_A : TRANS_VTOTAL_B;
1230 int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B;
1231 int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
1232 u32 temp;
Zhenyu Wang249c0e62009-07-24 01:00:29 +08001233 int tries = 5, j, n;
Zhenyu Wang2c072452009-06-05 15:38:42 +08001234
1235 /* XXX: When our outputs are all unaware of DPMS modes other than off
1236 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
1237 */
1238 switch (mode) {
1239 case DRM_MODE_DPMS_ON:
1240 case DRM_MODE_DPMS_STANDBY:
1241 case DRM_MODE_DPMS_SUSPEND:
1242 DRM_DEBUG("crtc %d dpms on\n", pipe);
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001243 if (HAS_eDP) {
1244 /* enable eDP PLL */
1245 igdng_enable_pll_edp(crtc);
1246 } else {
1247 /* enable PCH DPLL */
1248 temp = I915_READ(pch_dpll_reg);
1249 if ((temp & DPLL_VCO_ENABLE) == 0) {
1250 I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
1251 I915_READ(pch_dpll_reg);
1252 }
Zhenyu Wang2c072452009-06-05 15:38:42 +08001253
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001254 /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
1255 temp = I915_READ(fdi_rx_reg);
1256 I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
1257 FDI_SEL_PCDCLK |
1258 FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
1259 I915_READ(fdi_rx_reg);
1260 udelay(200);
Zhenyu Wang2c072452009-06-05 15:38:42 +08001261
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001262 /* Enable CPU FDI TX PLL, always on for IGDNG */
1263 temp = I915_READ(fdi_tx_reg);
1264 if ((temp & FDI_TX_PLL_ENABLE) == 0) {
1265 I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
1266 I915_READ(fdi_tx_reg);
1267 udelay(100);
1268 }
Zhenyu Wang2c072452009-06-05 15:38:42 +08001269 }
1270
1271 /* Enable CPU pipe */
1272 temp = I915_READ(pipeconf_reg);
1273 if ((temp & PIPEACONF_ENABLE) == 0) {
1274 I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
1275 I915_READ(pipeconf_reg);
1276 udelay(100);
1277 }
1278
1279 /* configure and enable CPU plane */
1280 temp = I915_READ(dspcntr_reg);
1281 if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
1282 I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
1283 /* Flush the plane changes */
1284 I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
1285 }
1286
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001287 if (!HAS_eDP) {
1288 /* enable CPU FDI TX and PCH FDI RX */
1289 temp = I915_READ(fdi_tx_reg);
1290 temp |= FDI_TX_ENABLE;
1291 temp |= FDI_DP_PORT_WIDTH_X4; /* default */
1292 temp &= ~FDI_LINK_TRAIN_NONE;
1293 temp |= FDI_LINK_TRAIN_PATTERN_1;
1294 I915_WRITE(fdi_tx_reg, temp);
1295 I915_READ(fdi_tx_reg);
Zhenyu Wang2c072452009-06-05 15:38:42 +08001296
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001297 temp = I915_READ(fdi_rx_reg);
1298 temp &= ~FDI_LINK_TRAIN_NONE;
1299 temp |= FDI_LINK_TRAIN_PATTERN_1;
1300 I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE);
1301 I915_READ(fdi_rx_reg);
Zhenyu Wang2c072452009-06-05 15:38:42 +08001302
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001303 udelay(150);
Zhenyu Wang2c072452009-06-05 15:38:42 +08001304
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001305 /* Train FDI. */
1306 /* umask FDI RX Interrupt symbol_lock and bit_lock bit
1307 for train result */
1308 temp = I915_READ(fdi_rx_imr_reg);
1309 temp &= ~FDI_RX_SYMBOL_LOCK;
1310 temp &= ~FDI_RX_BIT_LOCK;
1311 I915_WRITE(fdi_rx_imr_reg, temp);
1312 I915_READ(fdi_rx_imr_reg);
1313 udelay(150);
Zhenyu Wang2c072452009-06-05 15:38:42 +08001314
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001315 temp = I915_READ(fdi_rx_iir_reg);
1316 DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
Zhenyu Wang2c072452009-06-05 15:38:42 +08001317
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001318 if ((temp & FDI_RX_BIT_LOCK) == 0) {
1319 for (j = 0; j < tries; j++) {
1320 temp = I915_READ(fdi_rx_iir_reg);
1321 DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
1322 if (temp & FDI_RX_BIT_LOCK)
1323 break;
1324 udelay(200);
1325 }
1326 if (j != tries)
1327 I915_WRITE(fdi_rx_iir_reg,
1328 temp | FDI_RX_BIT_LOCK);
1329 else
1330 DRM_DEBUG("train 1 fail\n");
1331 } else {
Zhenyu Wang2c072452009-06-05 15:38:42 +08001332 I915_WRITE(fdi_rx_iir_reg,
1333 temp | FDI_RX_BIT_LOCK);
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001334 DRM_DEBUG("train 1 ok 2!\n");
Zhenyu Wang2c072452009-06-05 15:38:42 +08001335 }
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001336 temp = I915_READ(fdi_tx_reg);
1337 temp &= ~FDI_LINK_TRAIN_NONE;
1338 temp |= FDI_LINK_TRAIN_PATTERN_2;
1339 I915_WRITE(fdi_tx_reg, temp);
1340
1341 temp = I915_READ(fdi_rx_reg);
1342 temp &= ~FDI_LINK_TRAIN_NONE;
1343 temp |= FDI_LINK_TRAIN_PATTERN_2;
1344 I915_WRITE(fdi_rx_reg, temp);
1345
1346 udelay(150);
1347
1348 temp = I915_READ(fdi_rx_iir_reg);
1349 DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
1350
1351 if ((temp & FDI_RX_SYMBOL_LOCK) == 0) {
1352 for (j = 0; j < tries; j++) {
1353 temp = I915_READ(fdi_rx_iir_reg);
1354 DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
1355 if (temp & FDI_RX_SYMBOL_LOCK)
1356 break;
1357 udelay(200);
1358 }
1359 if (j != tries) {
1360 I915_WRITE(fdi_rx_iir_reg,
1361 temp | FDI_RX_SYMBOL_LOCK);
1362 DRM_DEBUG("train 2 ok 1!\n");
1363 } else
1364 DRM_DEBUG("train 2 fail\n");
1365 } else {
Zhenyu Wang2c072452009-06-05 15:38:42 +08001366 I915_WRITE(fdi_rx_iir_reg,
1367 temp | FDI_RX_SYMBOL_LOCK);
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001368 DRM_DEBUG("train 2 ok 2!\n");
1369 }
1370 DRM_DEBUG("train done\n");
1371
1372 /* set transcoder timing */
1373 I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg));
1374 I915_WRITE(trans_hblank_reg, I915_READ(cpu_hblank_reg));
1375 I915_WRITE(trans_hsync_reg, I915_READ(cpu_hsync_reg));
1376
1377 I915_WRITE(trans_vtot_reg, I915_READ(cpu_vtot_reg));
1378 I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg));
1379 I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg));
1380
1381 /* enable PCH transcoder */
1382 temp = I915_READ(transconf_reg);
1383 I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
1384 I915_READ(transconf_reg);
1385
1386 while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0)
1387 ;
1388
1389 /* enable normal */
1390
1391 temp = I915_READ(fdi_tx_reg);
1392 temp &= ~FDI_LINK_TRAIN_NONE;
1393 I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
1394 FDI_TX_ENHANCE_FRAME_ENABLE);
1395 I915_READ(fdi_tx_reg);
1396
1397 temp = I915_READ(fdi_rx_reg);
1398 temp &= ~FDI_LINK_TRAIN_NONE;
1399 I915_WRITE(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE |
1400 FDI_RX_ENHANCE_FRAME_ENABLE);
1401 I915_READ(fdi_rx_reg);
1402
1403 /* wait one idle pattern time */
1404 udelay(100);
1405
Zhenyu Wang2c072452009-06-05 15:38:42 +08001406 }
Zhenyu Wang2c072452009-06-05 15:38:42 +08001407
1408 intel_crtc_load_lut(crtc);
1409
1410 break;
1411 case DRM_MODE_DPMS_OFF:
1412 DRM_DEBUG("crtc %d dpms off\n", pipe);
1413
Zhenyu Wang24f119c2009-07-24 01:00:28 +08001414 i915_disable_vga(dev);
Zhenyu Wang2c072452009-06-05 15:38:42 +08001415
1416 /* Disable display plane */
1417 temp = I915_READ(dspcntr_reg);
1418 if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
1419 I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
1420 /* Flush the plane changes */
1421 I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
1422 I915_READ(dspbase_reg);
1423 }
1424
1425 /* disable cpu pipe, disable after all planes disabled */
1426 temp = I915_READ(pipeconf_reg);
1427 if ((temp & PIPEACONF_ENABLE) != 0) {
1428 I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
1429 I915_READ(pipeconf_reg);
Zhenyu Wang249c0e62009-07-24 01:00:29 +08001430 n = 0;
Zhenyu Wang2c072452009-06-05 15:38:42 +08001431 /* wait for cpu pipe off, pipe state */
Zhenyu Wang249c0e62009-07-24 01:00:29 +08001432 while ((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) != 0) {
1433 n++;
1434 if (n < 60) {
1435 udelay(500);
1436 continue;
1437 } else {
1438 DRM_DEBUG("pipe %d off delay\n", pipe);
1439 break;
1440 }
1441 }
Zhenyu Wang2c072452009-06-05 15:38:42 +08001442 } else
1443 DRM_DEBUG("crtc %d is disabled\n", pipe);
1444
Zhenyu Wang32f9d652009-07-24 01:00:32 +08001445 if (HAS_eDP) {
1446 igdng_disable_pll_edp(crtc);
1447 }
1448
Zhenyu Wang2c072452009-06-05 15:38:42 +08001449 /* disable CPU FDI tx and PCH FDI rx */
1450 temp = I915_READ(fdi_tx_reg);
1451 I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_ENABLE);
1452 I915_READ(fdi_tx_reg);
1453
1454 temp = I915_READ(fdi_rx_reg);
1455 I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE);
1456 I915_READ(fdi_rx_reg);
1457
Zhenyu Wang249c0e62009-07-24 01:00:29 +08001458 udelay(100);
1459
Zhenyu Wang2c072452009-06-05 15:38:42 +08001460 /* still set train pattern 1 */
1461 temp = I915_READ(fdi_tx_reg);
1462 temp &= ~FDI_LINK_TRAIN_NONE;
1463 temp |= FDI_LINK_TRAIN_PATTERN_1;
1464 I915_WRITE(fdi_tx_reg, temp);
1465
1466 temp = I915_READ(fdi_rx_reg);
1467 temp &= ~FDI_LINK_TRAIN_NONE;
1468 temp |= FDI_LINK_TRAIN_PATTERN_1;
1469 I915_WRITE(fdi_rx_reg, temp);
1470
Zhenyu Wang249c0e62009-07-24 01:00:29 +08001471 udelay(100);
1472
Zhenyu Wang2c072452009-06-05 15:38:42 +08001473 /* disable PCH transcoder */
1474 temp = I915_READ(transconf_reg);
1475 if ((temp & TRANS_ENABLE) != 0) {
1476 I915_WRITE(transconf_reg, temp & ~TRANS_ENABLE);
1477 I915_READ(transconf_reg);
Zhenyu Wang249c0e62009-07-24 01:00:29 +08001478 n = 0;
Zhenyu Wang2c072452009-06-05 15:38:42 +08001479 /* wait for PCH transcoder off, transcoder state */
Zhenyu Wang249c0e62009-07-24 01:00:29 +08001480 while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) != 0) {
1481 n++;
1482 if (n < 60) {
1483 udelay(500);
1484 continue;
1485 } else {
1486 DRM_DEBUG("transcoder %d off delay\n", pipe);
1487 break;
1488 }
1489 }
Zhenyu Wang2c072452009-06-05 15:38:42 +08001490 }
1491
1492 /* disable PCH DPLL */
1493 temp = I915_READ(pch_dpll_reg);
1494 if ((temp & DPLL_VCO_ENABLE) != 0) {
1495 I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
1496 I915_READ(pch_dpll_reg);
1497 }
1498
1499 temp = I915_READ(fdi_rx_reg);
1500 if ((temp & FDI_RX_PLL_ENABLE) != 0) {
1501 temp &= ~FDI_SEL_PCDCLK;
1502 temp &= ~FDI_RX_PLL_ENABLE;
1503 I915_WRITE(fdi_rx_reg, temp);
1504 I915_READ(fdi_rx_reg);
1505 }
1506
Zhenyu Wang249c0e62009-07-24 01:00:29 +08001507 /* Disable CPU FDI TX PLL */
1508 temp = I915_READ(fdi_tx_reg);
1509 if ((temp & FDI_TX_PLL_ENABLE) != 0) {
1510 I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE);
1511 I915_READ(fdi_tx_reg);
1512 udelay(100);
1513 }
1514
1515 /* Disable PF */
1516 temp = I915_READ(pf_ctl_reg);
1517 if ((temp & PF_ENABLE) != 0) {
1518 I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
1519 I915_READ(pf_ctl_reg);
1520 }
1521 I915_WRITE(pf_win_size, 0);
1522
Zhenyu Wang2c072452009-06-05 15:38:42 +08001523 /* Wait for the clocks to turn off. */
1524 udelay(150);
1525 break;
1526 }
1527}
1528
1529static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
1530{
1531 struct drm_device *dev = crtc->dev;
Jesse Barnes79e53942008-11-07 14:24:08 -08001532 struct drm_i915_private *dev_priv = dev->dev_private;
1533 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1534 int pipe = intel_crtc->pipe;
1535 int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
1536 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
1537 int dspbase_reg = (pipe == 0) ? DSPAADDR : DSPBADDR;
1538 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
1539 u32 temp;
Jesse Barnes79e53942008-11-07 14:24:08 -08001540
1541 /* XXX: When our outputs are all unaware of DPMS modes other than off
1542 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
1543 */
1544 switch (mode) {
1545 case DRM_MODE_DPMS_ON:
1546 case DRM_MODE_DPMS_STANDBY:
1547 case DRM_MODE_DPMS_SUSPEND:
1548 /* Enable the DPLL */
1549 temp = I915_READ(dpll_reg);
1550 if ((temp & DPLL_VCO_ENABLE) == 0) {
1551 I915_WRITE(dpll_reg, temp);
1552 I915_READ(dpll_reg);
1553 /* Wait for the clocks to stabilize. */
1554 udelay(150);
1555 I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
1556 I915_READ(dpll_reg);
1557 /* Wait for the clocks to stabilize. */
1558 udelay(150);
1559 I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
1560 I915_READ(dpll_reg);
1561 /* Wait for the clocks to stabilize. */
1562 udelay(150);
1563 }
1564
1565 /* Enable the pipe */
1566 temp = I915_READ(pipeconf_reg);
1567 if ((temp & PIPEACONF_ENABLE) == 0)
1568 I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
1569
1570 /* Enable the plane */
1571 temp = I915_READ(dspcntr_reg);
1572 if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
1573 I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
1574 /* Flush the plane changes */
1575 I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
1576 }
1577
1578 intel_crtc_load_lut(crtc);
1579
1580 /* Give the overlay scaler a chance to enable if it's on this pipe */
1581 //intel_crtc_dpms_video(crtc, true); TODO
Shaohua Li7662c8b2009-06-26 11:23:55 +08001582 intel_update_watermarks(dev);
Jesse Barnes79e53942008-11-07 14:24:08 -08001583 break;
1584 case DRM_MODE_DPMS_OFF:
Shaohua Li7662c8b2009-06-26 11:23:55 +08001585 intel_update_watermarks(dev);
Jesse Barnes79e53942008-11-07 14:24:08 -08001586 /* Give the overlay scaler a chance to disable if it's on this pipe */
1587 //intel_crtc_dpms_video(crtc, FALSE); TODO
1588
1589 /* Disable the VGA plane that we never use */
Zhenyu Wang24f119c2009-07-24 01:00:28 +08001590 i915_disable_vga(dev);
Jesse Barnes79e53942008-11-07 14:24:08 -08001591
1592 /* Disable display plane */
1593 temp = I915_READ(dspcntr_reg);
1594 if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
1595 I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
1596 /* Flush the plane changes */
1597 I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
1598 I915_READ(dspbase_reg);
1599 }
1600
1601 if (!IS_I9XX(dev)) {
1602 /* Wait for vblank for the disable to take effect */
1603 intel_wait_for_vblank(dev);
1604 }
1605
1606 /* Next, disable display pipes */
1607 temp = I915_READ(pipeconf_reg);
1608 if ((temp & PIPEACONF_ENABLE) != 0) {
1609 I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
1610 I915_READ(pipeconf_reg);
1611 }
1612
1613 /* Wait for vblank for the disable to take effect. */
1614 intel_wait_for_vblank(dev);
1615
1616 temp = I915_READ(dpll_reg);
1617 if ((temp & DPLL_VCO_ENABLE) != 0) {
1618 I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
1619 I915_READ(dpll_reg);
1620 }
1621
1622 /* Wait for the clocks to turn off. */
1623 udelay(150);
1624 break;
1625 }
Zhenyu Wang2c072452009-06-05 15:38:42 +08001626}
1627
1628/**
1629 * Sets the power management mode of the pipe and plane.
1630 *
1631 * This code should probably grow support for turning the cursor off and back
1632 * on appropriately at the same time as we're turning the pipe off/on.
1633 */
1634static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
1635{
1636 struct drm_device *dev = crtc->dev;
1637 struct drm_i915_master_private *master_priv;
1638 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1639 int pipe = intel_crtc->pipe;
1640 bool enabled;
1641
1642 if (IS_IGDNG(dev))
1643 igdng_crtc_dpms(crtc, mode);
1644 else
1645 i9xx_crtc_dpms(crtc, mode);
Jesse Barnes79e53942008-11-07 14:24:08 -08001646
Daniel Vetter65655d42009-08-11 16:05:31 +02001647 intel_crtc->dpms_mode = mode;
1648
Jesse Barnes79e53942008-11-07 14:24:08 -08001649 if (!dev->primary->master)
1650 return;
1651
1652 master_priv = dev->primary->master->driver_priv;
1653 if (!master_priv->sarea_priv)
1654 return;
1655
1656 enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
1657
1658 switch (pipe) {
1659 case 0:
1660 master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0;
1661 master_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0;
1662 break;
1663 case 1:
1664 master_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0;
1665 master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0;
1666 break;
1667 default:
1668 DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
1669 break;
1670 }
Jesse Barnes79e53942008-11-07 14:24:08 -08001671}
1672
1673static void intel_crtc_prepare (struct drm_crtc *crtc)
1674{
1675 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
1676 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
1677}
1678
1679static void intel_crtc_commit (struct drm_crtc *crtc)
1680{
1681 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
1682 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
1683}
1684
1685void intel_encoder_prepare (struct drm_encoder *encoder)
1686{
1687 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
1688 /* lvds has its own version of prepare see intel_lvds_prepare */
1689 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
1690}
1691
1692void intel_encoder_commit (struct drm_encoder *encoder)
1693{
1694 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
1695 /* lvds has its own version of commit see intel_lvds_commit */
1696 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
1697}
1698
1699static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
1700 struct drm_display_mode *mode,
1701 struct drm_display_mode *adjusted_mode)
1702{
Zhenyu Wang2c072452009-06-05 15:38:42 +08001703 struct drm_device *dev = crtc->dev;
1704 if (IS_IGDNG(dev)) {
1705 /* FDI link clock is fixed at 2.7G */
1706 if (mode->clock * 3 > 27000 * 4)
1707 return MODE_CLOCK_HIGH;
1708 }
Jesse Barnes79e53942008-11-07 14:24:08 -08001709 return true;
1710}
1711
1712
1713/** Returns the core display clock speed for i830 - i945 */
1714static int intel_get_core_clock_speed(struct drm_device *dev)
1715{
1716
1717 /* Core clock values taken from the published datasheets.
1718 * The 830 may go up to 166 Mhz, which we should check.
1719 */
1720 if (IS_I945G(dev))
1721 return 400000;
1722 else if (IS_I915G(dev))
1723 return 333000;
Shaohua Li21778322009-02-23 15:19:16 +08001724 else if (IS_I945GM(dev) || IS_845G(dev) || IS_IGDGM(dev))
Jesse Barnes79e53942008-11-07 14:24:08 -08001725 return 200000;
1726 else if (IS_I915GM(dev)) {
1727 u16 gcfgc = 0;
1728
1729 pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
1730
1731 if (gcfgc & GC_LOW_FREQUENCY_ENABLE)
1732 return 133000;
1733 else {
1734 switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
1735 case GC_DISPLAY_CLOCK_333_MHZ:
1736 return 333000;
1737 default:
1738 case GC_DISPLAY_CLOCK_190_200_MHZ:
1739 return 190000;
1740 }
1741 }
1742 } else if (IS_I865G(dev))
1743 return 266000;
1744 else if (IS_I855(dev)) {
1745 u16 hpllcc = 0;
1746 /* Assume that the hardware is in the high speed state. This
1747 * should be the default.
1748 */
1749 switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
1750 case GC_CLOCK_133_200:
1751 case GC_CLOCK_100_200:
1752 return 200000;
1753 case GC_CLOCK_166_250:
1754 return 250000;
1755 case GC_CLOCK_100_133:
1756 return 133000;
1757 }
1758 } else /* 852, 830 */
1759 return 133000;
1760
1761 return 0; /* Silence gcc warning */
1762}
1763
Jesse Barnes79e53942008-11-07 14:24:08 -08001764/**
1765 * Return the pipe currently connected to the panel fitter,
1766 * or -1 if the panel fitter is not present or not in use
1767 */
1768static int intel_panel_fitter_pipe (struct drm_device *dev)
1769{
1770 struct drm_i915_private *dev_priv = dev->dev_private;
1771 u32 pfit_control;
1772
1773 /* i830 doesn't have a panel fitter */
1774 if (IS_I830(dev))
1775 return -1;
1776
1777 pfit_control = I915_READ(PFIT_CONTROL);
1778
1779 /* See if the panel fitter is in use */
1780 if ((pfit_control & PFIT_ENABLE) == 0)
1781 return -1;
1782
1783 /* 965 can place panel fitter on either pipe */
1784 if (IS_I965G(dev))
1785 return (pfit_control >> 29) & 0x3;
1786
1787 /* older chips can only use pipe 1 */
1788 return 1;
1789}
1790
Zhenyu Wang2c072452009-06-05 15:38:42 +08001791struct fdi_m_n {
1792 u32 tu;
1793 u32 gmch_m;
1794 u32 gmch_n;
1795 u32 link_m;
1796 u32 link_n;
1797};
1798
1799static void
1800fdi_reduce_ratio(u32 *num, u32 *den)
1801{
1802 while (*num > 0xffffff || *den > 0xffffff) {
1803 *num >>= 1;
1804 *den >>= 1;
1805 }
1806}
1807
1808#define DATA_N 0x800000
1809#define LINK_N 0x80000
1810
1811static void
1812igdng_compute_m_n(int bytes_per_pixel, int nlanes,
1813 int pixel_clock, int link_clock,
1814 struct fdi_m_n *m_n)
1815{
1816 u64 temp;
1817
1818 m_n->tu = 64; /* default size */
1819
1820 temp = (u64) DATA_N * pixel_clock;
1821 temp = div_u64(temp, link_clock);
Andy Whitcroft956dba32009-07-01 15:20:59 +01001822 m_n->gmch_m = div_u64(temp * bytes_per_pixel, nlanes);
Zhenyu Wang2c072452009-06-05 15:38:42 +08001823 m_n->gmch_n = DATA_N;
1824 fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
1825
1826 temp = (u64) LINK_N * pixel_clock;
1827 m_n->link_m = div_u64(temp, link_clock);
1828 m_n->link_n = LINK_N;
1829 fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
1830}
1831
1832
Shaohua Li7662c8b2009-06-26 11:23:55 +08001833struct intel_watermark_params {
1834 unsigned long fifo_size;
1835 unsigned long max_wm;
1836 unsigned long default_wm;
1837 unsigned long guard_size;
1838 unsigned long cacheline_size;
1839};
1840
1841/* IGD has different values for various configs */
1842static struct intel_watermark_params igd_display_wm = {
1843 IGD_DISPLAY_FIFO,
1844 IGD_MAX_WM,
1845 IGD_DFT_WM,
1846 IGD_GUARD_WM,
1847 IGD_FIFO_LINE_SIZE
1848};
1849static struct intel_watermark_params igd_display_hplloff_wm = {
1850 IGD_DISPLAY_FIFO,
1851 IGD_MAX_WM,
1852 IGD_DFT_HPLLOFF_WM,
1853 IGD_GUARD_WM,
1854 IGD_FIFO_LINE_SIZE
1855};
1856static struct intel_watermark_params igd_cursor_wm = {
1857 IGD_CURSOR_FIFO,
1858 IGD_CURSOR_MAX_WM,
1859 IGD_CURSOR_DFT_WM,
1860 IGD_CURSOR_GUARD_WM,
1861 IGD_FIFO_LINE_SIZE,
1862};
1863static struct intel_watermark_params igd_cursor_hplloff_wm = {
1864 IGD_CURSOR_FIFO,
1865 IGD_CURSOR_MAX_WM,
1866 IGD_CURSOR_DFT_WM,
1867 IGD_CURSOR_GUARD_WM,
1868 IGD_FIFO_LINE_SIZE
1869};
1870static struct intel_watermark_params i945_wm_info = {
Shaohua Li7662c8b2009-06-26 11:23:55 +08001871 I945_FIFO_SIZE,
1872 I915_MAX_WM,
1873 1,
Jesse Barnesdff33cf2009-07-14 10:15:56 -07001874 2,
1875 I915_FIFO_LINE_SIZE
1876};
1877static struct intel_watermark_params i915_wm_info = {
1878 I915_FIFO_SIZE,
1879 I915_MAX_WM,
1880 1,
1881 2,
Shaohua Li7662c8b2009-06-26 11:23:55 +08001882 I915_FIFO_LINE_SIZE
1883};
1884static struct intel_watermark_params i855_wm_info = {
1885 I855GM_FIFO_SIZE,
1886 I915_MAX_WM,
1887 1,
Jesse Barnesdff33cf2009-07-14 10:15:56 -07001888 2,
Shaohua Li7662c8b2009-06-26 11:23:55 +08001889 I830_FIFO_LINE_SIZE
1890};
1891static struct intel_watermark_params i830_wm_info = {
1892 I830_FIFO_SIZE,
1893 I915_MAX_WM,
1894 1,
Jesse Barnesdff33cf2009-07-14 10:15:56 -07001895 2,
Shaohua Li7662c8b2009-06-26 11:23:55 +08001896 I830_FIFO_LINE_SIZE
1897};
1898
Jesse Barnesdff33cf2009-07-14 10:15:56 -07001899/**
1900 * intel_calculate_wm - calculate watermark level
1901 * @clock_in_khz: pixel clock
1902 * @wm: chip FIFO params
1903 * @pixel_size: display pixel size
1904 * @latency_ns: memory latency for the platform
1905 *
1906 * Calculate the watermark level (the level at which the display plane will
1907 * start fetching from memory again). Each chip has a different display
1908 * FIFO size and allocation, so the caller needs to figure that out and pass
1909 * in the correct intel_watermark_params structure.
1910 *
1911 * As the pixel clock runs, the FIFO will be drained at a rate that depends
1912 * on the pixel size. When it reaches the watermark level, it'll start
1913 * fetching FIFO line sized based chunks from memory until the FIFO fills
1914 * past the watermark point. If the FIFO drains completely, a FIFO underrun
1915 * will occur, and a display engine hang could result.
1916 */
Shaohua Li7662c8b2009-06-26 11:23:55 +08001917static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
1918 struct intel_watermark_params *wm,
1919 int pixel_size,
1920 unsigned long latency_ns)
1921{
Jesse Barnes390c4dd2009-07-16 13:01:01 -07001922 long entries_required, wm_size;
Shaohua Li7662c8b2009-06-26 11:23:55 +08001923
Jesse Barnesdff33cf2009-07-14 10:15:56 -07001924 entries_required = (clock_in_khz * pixel_size * latency_ns) / 1000000;
1925 entries_required /= wm->cacheline_size;
1926
1927 DRM_DEBUG("FIFO entries required for mode: %d\n", entries_required);
1928
1929 wm_size = wm->fifo_size - (entries_required + wm->guard_size);
1930
1931 DRM_DEBUG("FIFO watermark level: %d\n", wm_size);
Shaohua Li7662c8b2009-06-26 11:23:55 +08001932
Jesse Barnes390c4dd2009-07-16 13:01:01 -07001933 /* Don't promote wm_size to unsigned... */
1934 if (wm_size > (long)wm->max_wm)
Shaohua Li7662c8b2009-06-26 11:23:55 +08001935 wm_size = wm->max_wm;
Jesse Barnes390c4dd2009-07-16 13:01:01 -07001936 if (wm_size <= 0)
Shaohua Li7662c8b2009-06-26 11:23:55 +08001937 wm_size = wm->default_wm;
1938 return wm_size;
1939}
1940
1941struct cxsr_latency {
1942 int is_desktop;
1943 unsigned long fsb_freq;
1944 unsigned long mem_freq;
1945 unsigned long display_sr;
1946 unsigned long display_hpll_disable;
1947 unsigned long cursor_sr;
1948 unsigned long cursor_hpll_disable;
1949};
1950
1951static struct cxsr_latency cxsr_latency_table[] = {
1952 {1, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */
1953 {1, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */
1954 {1, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */
1955
1956 {1, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */
1957 {1, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */
1958 {1, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */
1959
1960 {1, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */
1961 {1, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */
1962 {1, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */
1963
1964 {0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */
1965 {0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */
1966 {0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */
1967
1968 {0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */
1969 {0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */
1970 {0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */
1971
1972 {0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */
1973 {0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */
1974 {0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */
1975};
1976
1977static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb,
1978 int mem)
1979{
1980 int i;
1981 struct cxsr_latency *latency;
1982
1983 if (fsb == 0 || mem == 0)
1984 return NULL;
1985
1986 for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) {
1987 latency = &cxsr_latency_table[i];
1988 if (is_desktop == latency->is_desktop &&
1989 fsb == latency->fsb_freq && mem == latency->mem_freq)
1990 break;
1991 }
1992 if (i >= ARRAY_SIZE(cxsr_latency_table)) {
1993 DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n");
1994 return NULL;
1995 }
1996 return latency;
1997}
1998
1999static void igd_disable_cxsr(struct drm_device *dev)
2000{
2001 struct drm_i915_private *dev_priv = dev->dev_private;
2002 u32 reg;
2003
2004 /* deactivate cxsr */
2005 reg = I915_READ(DSPFW3);
2006 reg &= ~(IGD_SELF_REFRESH_EN);
2007 I915_WRITE(DSPFW3, reg);
2008 DRM_INFO("Big FIFO is disabled\n");
2009}
2010
2011static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock,
2012 int pixel_size)
2013{
2014 struct drm_i915_private *dev_priv = dev->dev_private;
2015 u32 reg;
2016 unsigned long wm;
2017 struct cxsr_latency *latency;
2018
2019 latency = intel_get_cxsr_latency(IS_IGDG(dev), dev_priv->fsb_freq,
2020 dev_priv->mem_freq);
2021 if (!latency) {
2022 DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n");
2023 igd_disable_cxsr(dev);
2024 return;
2025 }
2026
2027 /* Display SR */
2028 wm = intel_calculate_wm(clock, &igd_display_wm, pixel_size,
2029 latency->display_sr);
2030 reg = I915_READ(DSPFW1);
2031 reg &= 0x7fffff;
2032 reg |= wm << 23;
2033 I915_WRITE(DSPFW1, reg);
2034 DRM_DEBUG("DSPFW1 register is %x\n", reg);
2035
2036 /* cursor SR */
2037 wm = intel_calculate_wm(clock, &igd_cursor_wm, pixel_size,
2038 latency->cursor_sr);
2039 reg = I915_READ(DSPFW3);
2040 reg &= ~(0x3f << 24);
2041 reg |= (wm & 0x3f) << 24;
2042 I915_WRITE(DSPFW3, reg);
2043
2044 /* Display HPLL off SR */
2045 wm = intel_calculate_wm(clock, &igd_display_hplloff_wm,
2046 latency->display_hpll_disable, I915_FIFO_LINE_SIZE);
2047 reg = I915_READ(DSPFW3);
2048 reg &= 0xfffffe00;
2049 reg |= wm & 0x1ff;
2050 I915_WRITE(DSPFW3, reg);
2051
2052 /* cursor HPLL off SR */
2053 wm = intel_calculate_wm(clock, &igd_cursor_hplloff_wm, pixel_size,
2054 latency->cursor_hpll_disable);
2055 reg = I915_READ(DSPFW3);
2056 reg &= ~(0x3f << 16);
2057 reg |= (wm & 0x3f) << 16;
2058 I915_WRITE(DSPFW3, reg);
2059 DRM_DEBUG("DSPFW3 register is %x\n", reg);
2060
2061 /* activate cxsr */
2062 reg = I915_READ(DSPFW3);
2063 reg |= IGD_SELF_REFRESH_EN;
2064 I915_WRITE(DSPFW3, reg);
2065
2066 DRM_INFO("Big FIFO is enabled\n");
2067
2068 return;
2069}
2070
Jesse Barnesbcc24fb2009-08-31 10:24:31 -07002071/*
2072 * Latency for FIFO fetches is dependent on several factors:
2073 * - memory configuration (speed, channels)
2074 * - chipset
2075 * - current MCH state
2076 * It can be fairly high in some situations, so here we assume a fairly
2077 * pessimal value. It's a tradeoff between extra memory fetches (if we
2078 * set this value too high, the FIFO will fetch frequently to stay full)
2079 * and power consumption (set it too low to save power and we might see
2080 * FIFO underruns and display "flicker").
2081 *
2082 * A value of 5us seems to be a good balance; safe for very low end
2083 * platforms but not overly aggressive on lower latency configs.
2084 */
2085const static int latency_ns = 5000;
Shaohua Li7662c8b2009-06-26 11:23:55 +08002086
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002087static int intel_get_fifo_size(struct drm_device *dev, int plane)
2088{
2089 struct drm_i915_private *dev_priv = dev->dev_private;
2090 uint32_t dsparb = I915_READ(DSPARB);
2091 int size;
2092
2093 if (IS_I9XX(dev)) {
2094 if (plane == 0)
2095 size = dsparb & 0x7f;
2096 else
2097 size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) -
2098 (dsparb & 0x7f);
2099 } else if (IS_I85X(dev)) {
2100 if (plane == 0)
2101 size = dsparb & 0x1ff;
2102 else
2103 size = ((dsparb >> DSPARB_BEND_SHIFT) & 0x1ff) -
2104 (dsparb & 0x1ff);
2105 size >>= 1; /* Convert to cachelines */
Jesse Barnesf3601322009-07-22 12:54:59 -07002106 } else if (IS_845G(dev)) {
2107 size = dsparb & 0x7f;
2108 size >>= 2; /* Convert to cachelines */
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002109 } else {
2110 size = dsparb & 0x7f;
2111 size >>= 1; /* Convert to cachelines */
2112 }
2113
2114 DRM_DEBUG("FIFO size - (0x%08x) %s: %d\n", dsparb, plane ? "B" : "A",
2115 size);
2116
2117 return size;
2118}
Shaohua Li7662c8b2009-06-26 11:23:55 +08002119
Jesse Barnes652c3932009-08-17 13:31:43 -07002120static void g4x_update_wm(struct drm_device *dev)
2121{
2122 struct drm_i915_private *dev_priv = dev->dev_private;
2123 u32 fw_blc_self = I915_READ(FW_BLC_SELF);
2124
2125 if (i915_powersave)
2126 fw_blc_self |= FW_BLC_SELF_EN;
2127 else
2128 fw_blc_self &= ~FW_BLC_SELF_EN;
2129 I915_WRITE(FW_BLC_SELF, fw_blc_self);
2130}
2131
Shaohua Li7662c8b2009-06-26 11:23:55 +08002132static void i965_update_wm(struct drm_device *dev)
2133{
2134 struct drm_i915_private *dev_priv = dev->dev_private;
2135
2136 DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n");
2137
2138 /* 965 has limitations... */
2139 I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0));
2140 I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
2141}
2142
2143static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
2144 int planeb_clock, int sr_hdisplay, int pixel_size)
2145{
2146 struct drm_i915_private *dev_priv = dev->dev_private;
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002147 uint32_t fwater_lo;
2148 uint32_t fwater_hi;
2149 int total_size, cacheline_size, cwm, srwm = 1;
2150 int planea_wm, planeb_wm;
2151 struct intel_watermark_params planea_params, planeb_params;
Shaohua Li7662c8b2009-06-26 11:23:55 +08002152 unsigned long line_time_us;
2153 int sr_clock, sr_entries = 0;
2154
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002155 /* Create copies of the base settings for each pipe */
Shaohua Li7662c8b2009-06-26 11:23:55 +08002156 if (IS_I965GM(dev) || IS_I945GM(dev))
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002157 planea_params = planeb_params = i945_wm_info;
Shaohua Li7662c8b2009-06-26 11:23:55 +08002158 else if (IS_I9XX(dev))
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002159 planea_params = planeb_params = i915_wm_info;
Shaohua Li7662c8b2009-06-26 11:23:55 +08002160 else
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002161 planea_params = planeb_params = i855_wm_info;
Shaohua Li7662c8b2009-06-26 11:23:55 +08002162
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002163 /* Grab a couple of global values before we overwrite them */
2164 total_size = planea_params.fifo_size;
2165 cacheline_size = planea_params.cacheline_size;
Shaohua Li7662c8b2009-06-26 11:23:55 +08002166
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002167 /* Update per-plane FIFO sizes */
2168 planea_params.fifo_size = intel_get_fifo_size(dev, 0);
2169 planeb_params.fifo_size = intel_get_fifo_size(dev, 1);
Shaohua Li7662c8b2009-06-26 11:23:55 +08002170
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002171 planea_wm = intel_calculate_wm(planea_clock, &planea_params,
2172 pixel_size, latency_ns);
2173 planeb_wm = intel_calculate_wm(planeb_clock, &planeb_params,
2174 pixel_size, latency_ns);
2175 DRM_DEBUG("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
Shaohua Li7662c8b2009-06-26 11:23:55 +08002176
2177 /*
2178 * Overlay gets an aggressive default since video jitter is bad.
2179 */
2180 cwm = 2;
2181
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002182 /* Calc sr entries for one plane configs */
Jesse Barnes652c3932009-08-17 13:31:43 -07002183 if (HAS_FW_BLC(dev) && sr_hdisplay &&
2184 (!planea_clock || !planeb_clock)) {
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002185 /* self-refresh has much higher latency */
2186 const static int sr_latency_ns = 6000;
2187
Shaohua Li7662c8b2009-06-26 11:23:55 +08002188 sr_clock = planea_clock ? planea_clock : planeb_clock;
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002189 line_time_us = ((sr_hdisplay * 1000) / sr_clock);
2190
2191 /* Use ns/us then divide to preserve precision */
2192 sr_entries = (((sr_latency_ns / line_time_us) + 1) *
2193 pixel_size * sr_hdisplay) / 1000;
2194 sr_entries = roundup(sr_entries / cacheline_size, 1);
2195 DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
2196 srwm = total_size - sr_entries;
2197 if (srwm < 0)
2198 srwm = 1;
Jesse Barnes652c3932009-08-17 13:31:43 -07002199 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f));
Shaohua Li7662c8b2009-06-26 11:23:55 +08002200 }
2201
2202 DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002203 planea_wm, planeb_wm, cwm, srwm);
Shaohua Li7662c8b2009-06-26 11:23:55 +08002204
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002205 fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f);
2206 fwater_hi = (cwm & 0x1f);
2207
2208 /* Set request length to 8 cachelines per fetch */
2209 fwater_lo = fwater_lo | (1 << 24) | (1 << 8);
2210 fwater_hi = fwater_hi | (1 << 8);
Shaohua Li7662c8b2009-06-26 11:23:55 +08002211
2212 I915_WRITE(FW_BLC, fwater_lo);
2213 I915_WRITE(FW_BLC2, fwater_hi);
Shaohua Li7662c8b2009-06-26 11:23:55 +08002214}
2215
2216static void i830_update_wm(struct drm_device *dev, int planea_clock,
2217 int pixel_size)
2218{
2219 struct drm_i915_private *dev_priv = dev->dev_private;
Jesse Barnesf3601322009-07-22 12:54:59 -07002220 uint32_t fwater_lo = I915_READ(FW_BLC) & ~0xfff;
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002221 int planea_wm;
Shaohua Li7662c8b2009-06-26 11:23:55 +08002222
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002223 i830_wm_info.fifo_size = intel_get_fifo_size(dev, 0);
Shaohua Li7662c8b2009-06-26 11:23:55 +08002224
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002225 planea_wm = intel_calculate_wm(planea_clock, &i830_wm_info,
2226 pixel_size, latency_ns);
Jesse Barnesf3601322009-07-22 12:54:59 -07002227 fwater_lo |= (3<<8) | planea_wm;
2228
2229 DRM_DEBUG("Setting FIFO watermarks - A: %d\n", planea_wm);
Shaohua Li7662c8b2009-06-26 11:23:55 +08002230
2231 I915_WRITE(FW_BLC, fwater_lo);
2232}
2233
2234/**
2235 * intel_update_watermarks - update FIFO watermark values based on current modes
2236 *
2237 * Calculate watermark values for the various WM regs based on current mode
2238 * and plane configuration.
2239 *
2240 * There are several cases to deal with here:
2241 * - normal (i.e. non-self-refresh)
2242 * - self-refresh (SR) mode
2243 * - lines are large relative to FIFO size (buffer can hold up to 2)
2244 * - lines are small relative to FIFO size (buffer can hold more than 2
2245 * lines), so need to account for TLB latency
2246 *
2247 * The normal calculation is:
2248 * watermark = dotclock * bytes per pixel * latency
2249 * where latency is platform & configuration dependent (we assume pessimal
2250 * values here).
2251 *
2252 * The SR calculation is:
2253 * watermark = (trunc(latency/line time)+1) * surface width *
2254 * bytes per pixel
2255 * where
2256 * line time = htotal / dotclock
2257 * and latency is assumed to be high, as above.
2258 *
2259 * The final value programmed to the register should always be rounded up,
2260 * and include an extra 2 entries to account for clock crossings.
2261 *
2262 * We don't use the sprite, so we can ignore that. And on Crestline we have
2263 * to set the non-SR watermarks to 8.
2264 */
2265static void intel_update_watermarks(struct drm_device *dev)
2266{
2267 struct drm_crtc *crtc;
2268 struct intel_crtc *intel_crtc;
2269 int sr_hdisplay = 0;
2270 unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
2271 int enabled = 0, pixel_size = 0;
2272
Shaohua Li7662c8b2009-06-26 11:23:55 +08002273 /* Get the clock config from both planes */
2274 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
2275 intel_crtc = to_intel_crtc(crtc);
2276 if (crtc->enabled) {
2277 enabled++;
2278 if (intel_crtc->plane == 0) {
2279 DRM_DEBUG("plane A (pipe %d) clock: %d\n",
2280 intel_crtc->pipe, crtc->mode.clock);
2281 planea_clock = crtc->mode.clock;
2282 } else {
2283 DRM_DEBUG("plane B (pipe %d) clock: %d\n",
2284 intel_crtc->pipe, crtc->mode.clock);
2285 planeb_clock = crtc->mode.clock;
2286 }
2287 sr_hdisplay = crtc->mode.hdisplay;
2288 sr_clock = crtc->mode.clock;
2289 if (crtc->fb)
2290 pixel_size = crtc->fb->bits_per_pixel / 8;
2291 else
2292 pixel_size = 4; /* by default */
2293 }
2294 }
2295
2296 if (enabled <= 0)
2297 return;
2298
Jesse Barnesdff33cf2009-07-14 10:15:56 -07002299 /* Single plane configs can enable self refresh */
Shaohua Li7662c8b2009-06-26 11:23:55 +08002300 if (enabled == 1 && IS_IGD(dev))
2301 igd_enable_cxsr(dev, sr_clock, pixel_size);
2302 else if (IS_IGD(dev))
2303 igd_disable_cxsr(dev);
2304
Jesse Barnes652c3932009-08-17 13:31:43 -07002305 if (IS_G4X(dev))
2306 g4x_update_wm(dev);
2307 else if (IS_I965G(dev))
Shaohua Li7662c8b2009-06-26 11:23:55 +08002308 i965_update_wm(dev);
2309 else if (IS_I9XX(dev) || IS_MOBILE(dev))
2310 i9xx_update_wm(dev, planea_clock, planeb_clock, sr_hdisplay,
2311 pixel_size);
2312 else
2313 i830_update_wm(dev, planea_clock, pixel_size);
2314}
2315
Chris Wilson5c3b82e2009-02-11 13:25:09 +00002316static int intel_crtc_mode_set(struct drm_crtc *crtc,
2317 struct drm_display_mode *mode,
2318 struct drm_display_mode *adjusted_mode,
2319 int x, int y,
2320 struct drm_framebuffer *old_fb)
Jesse Barnes79e53942008-11-07 14:24:08 -08002321{
2322 struct drm_device *dev = crtc->dev;
2323 struct drm_i915_private *dev_priv = dev->dev_private;
2324 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2325 int pipe = intel_crtc->pipe;
2326 int fp_reg = (pipe == 0) ? FPA0 : FPB0;
2327 int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
2328 int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
2329 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
2330 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
2331 int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
2332 int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
2333 int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
2334 int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
2335 int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
2336 int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
2337 int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
2338 int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
2339 int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
Kristian Høgsberg43565a02009-02-13 20:56:52 -05002340 int refclk, num_outputs = 0;
Jesse Barnes652c3932009-08-17 13:31:43 -07002341 intel_clock_t clock, reduced_clock;
2342 u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf;
2343 bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
Keith Packarda4fc5ed2009-04-07 16:16:42 -07002344 bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
Zhenyu Wang32f9d652009-07-24 01:00:32 +08002345 bool is_edp = false;
Jesse Barnes79e53942008-11-07 14:24:08 -08002346 struct drm_mode_config *mode_config = &dev->mode_config;
2347 struct drm_connector *connector;
Ma Lingd4906092009-03-18 20:13:27 +08002348 const intel_limit_t *limit;
Chris Wilson5c3b82e2009-02-11 13:25:09 +00002349 int ret;
Zhenyu Wang2c072452009-06-05 15:38:42 +08002350 struct fdi_m_n m_n = {0};
2351 int data_m1_reg = (pipe == 0) ? PIPEA_DATA_M1 : PIPEB_DATA_M1;
2352 int data_n1_reg = (pipe == 0) ? PIPEA_DATA_N1 : PIPEB_DATA_N1;
2353 int link_m1_reg = (pipe == 0) ? PIPEA_LINK_M1 : PIPEB_LINK_M1;
2354 int link_n1_reg = (pipe == 0) ? PIPEA_LINK_N1 : PIPEB_LINK_N1;
2355 int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0;
2356 int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
2357 int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
Zhenyu Wang541998a2009-06-05 15:38:44 +08002358 int lvds_reg = LVDS;
Zhenyu Wang2c072452009-06-05 15:38:42 +08002359 u32 temp;
2360 int sdvo_pixel_multiply;
Zhenyu Wang5eb08b62009-07-24 01:00:31 +08002361 int target_clock;
Jesse Barnes79e53942008-11-07 14:24:08 -08002362
2363 drm_vblank_pre_modeset(dev, pipe);
2364
2365 list_for_each_entry(connector, &mode_config->connector_list, head) {
2366 struct intel_output *intel_output = to_intel_output(connector);
2367
2368 if (!connector->encoder || connector->encoder->crtc != crtc)
2369 continue;
2370
2371 switch (intel_output->type) {
2372 case INTEL_OUTPUT_LVDS:
2373 is_lvds = true;
2374 break;
2375 case INTEL_OUTPUT_SDVO:
Eric Anholt7d573822009-01-02 13:33:00 -08002376 case INTEL_OUTPUT_HDMI:
Jesse Barnes79e53942008-11-07 14:24:08 -08002377 is_sdvo = true;
Jesse Barnese2f0ba92009-02-02 15:11:52 -08002378 if (intel_output->needs_tv_clock)
2379 is_tv = true;
Jesse Barnes79e53942008-11-07 14:24:08 -08002380 break;
2381 case INTEL_OUTPUT_DVO:
2382 is_dvo = true;
2383 break;
2384 case INTEL_OUTPUT_TVOUT:
2385 is_tv = true;
2386 break;
2387 case INTEL_OUTPUT_ANALOG:
2388 is_crt = true;
2389 break;
Keith Packarda4fc5ed2009-04-07 16:16:42 -07002390 case INTEL_OUTPUT_DISPLAYPORT:
2391 is_dp = true;
2392 break;
Zhenyu Wang32f9d652009-07-24 01:00:32 +08002393 case INTEL_OUTPUT_EDP:
2394 is_edp = true;
2395 break;
Jesse Barnes79e53942008-11-07 14:24:08 -08002396 }
Kristian Høgsberg43565a02009-02-13 20:56:52 -05002397
2398 num_outputs++;
Jesse Barnes79e53942008-11-07 14:24:08 -08002399 }
2400
Kristian Høgsberg43565a02009-02-13 20:56:52 -05002401 if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2) {
2402 refclk = dev_priv->lvds_ssc_freq * 1000;
2403 DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000);
2404 } else if (IS_I9XX(dev)) {
Jesse Barnes79e53942008-11-07 14:24:08 -08002405 refclk = 96000;
Zhenyu Wang2c072452009-06-05 15:38:42 +08002406 if (IS_IGDNG(dev))
2407 refclk = 120000; /* 120Mhz refclk */
Jesse Barnes79e53942008-11-07 14:24:08 -08002408 } else {
2409 refclk = 48000;
2410 }
Keith Packarda4fc5ed2009-04-07 16:16:42 -07002411
Jesse Barnes79e53942008-11-07 14:24:08 -08002412
Ma Lingd4906092009-03-18 20:13:27 +08002413 /*
2414 * Returns a set of divisors for the desired target clock with the given
2415 * refclk, or FALSE. The returned values represent the clock equation:
2416 * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
2417 */
2418 limit = intel_limit(crtc);
2419 ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock);
Jesse Barnes79e53942008-11-07 14:24:08 -08002420 if (!ok) {
2421 DRM_ERROR("Couldn't find PLL settings for mode!\n");
Chris Wilson1f803ee2009-06-06 09:45:59 +01002422 drm_vblank_post_modeset(dev, pipe);
Chris Wilson5c3b82e2009-02-11 13:25:09 +00002423 return -EINVAL;
Jesse Barnes79e53942008-11-07 14:24:08 -08002424 }
2425
Jesse Barnes652c3932009-08-17 13:31:43 -07002426 if (limit->find_reduced_pll && dev_priv->lvds_downclock_avail) {
2427 memcpy(&reduced_clock, &clock, sizeof(intel_clock_t));
2428 has_reduced_clock = limit->find_reduced_pll(limit, crtc,
2429 (adjusted_mode->clock*3/4),
2430 refclk,
2431 &reduced_clock);
2432 }
2433
Zhenyu Wang7026d4a2009-03-24 14:02:43 +08002434 /* SDVO TV has fixed PLL values depend on its clock range,
2435 this mirrors vbios setting. */
2436 if (is_sdvo && is_tv) {
2437 if (adjusted_mode->clock >= 100000
2438 && adjusted_mode->clock < 140500) {
2439 clock.p1 = 2;
2440 clock.p2 = 10;
2441 clock.n = 3;
2442 clock.m1 = 16;
2443 clock.m2 = 8;
2444 } else if (adjusted_mode->clock >= 140500
2445 && adjusted_mode->clock <= 200000) {
2446 clock.p1 = 1;
2447 clock.p2 = 10;
2448 clock.n = 6;
2449 clock.m1 = 12;
2450 clock.m2 = 8;
2451 }
2452 }
2453
Zhenyu Wang2c072452009-06-05 15:38:42 +08002454 /* FDI link */
Zhenyu Wang5eb08b62009-07-24 01:00:31 +08002455 if (IS_IGDNG(dev)) {
Zhenyu Wang32f9d652009-07-24 01:00:32 +08002456 int lane, link_bw;
2457 /* eDP doesn't require FDI link, so just set DP M/N
2458 according to current link config */
2459 if (is_edp) {
2460 struct drm_connector *edp;
Zhenyu Wang5eb08b62009-07-24 01:00:31 +08002461 target_clock = mode->clock;
Zhenyu Wang32f9d652009-07-24 01:00:32 +08002462 edp = intel_pipe_get_output(crtc);
2463 intel_edp_link_config(to_intel_output(edp),
2464 &lane, &link_bw);
2465 } else {
2466 /* DP over FDI requires target mode clock
2467 instead of link clock */
2468 if (is_dp)
2469 target_clock = mode->clock;
2470 else
2471 target_clock = adjusted_mode->clock;
2472 lane = 4;
2473 link_bw = 270000;
2474 }
2475 igdng_compute_m_n(3, lane, target_clock,
2476 link_bw, &m_n);
Zhenyu Wang5eb08b62009-07-24 01:00:31 +08002477 }
Zhenyu Wang2c072452009-06-05 15:38:42 +08002478
Jesse Barnes652c3932009-08-17 13:31:43 -07002479 if (IS_IGD(dev)) {
Shaohua Li21778322009-02-23 15:19:16 +08002480 fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
Jesse Barnes652c3932009-08-17 13:31:43 -07002481 if (has_reduced_clock)
2482 fp2 = (1 << reduced_clock.n) << 16 |
2483 reduced_clock.m1 << 8 | reduced_clock.m2;
2484 } else {
Shaohua Li21778322009-02-23 15:19:16 +08002485 fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
Jesse Barnes652c3932009-08-17 13:31:43 -07002486 if (has_reduced_clock)
2487 fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
2488 reduced_clock.m2;
2489 }
Jesse Barnes79e53942008-11-07 14:24:08 -08002490
Zhenyu Wang2c072452009-06-05 15:38:42 +08002491 if (!IS_IGDNG(dev))
2492 dpll = DPLL_VGA_MODE_DIS;
2493
Jesse Barnes79e53942008-11-07 14:24:08 -08002494 if (IS_I9XX(dev)) {
2495 if (is_lvds)
2496 dpll |= DPLLB_MODE_LVDS;
2497 else
2498 dpll |= DPLLB_MODE_DAC_SERIAL;
2499 if (is_sdvo) {
2500 dpll |= DPLL_DVO_HIGH_SPEED;
Zhenyu Wang2c072452009-06-05 15:38:42 +08002501 sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
Sean Young942642a2009-08-06 17:35:50 +08002502 if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
Jesse Barnes79e53942008-11-07 14:24:08 -08002503 dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
Zhenyu Wang2c072452009-06-05 15:38:42 +08002504 else if (IS_IGDNG(dev))
2505 dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
Jesse Barnes79e53942008-11-07 14:24:08 -08002506 }
Keith Packarda4fc5ed2009-04-07 16:16:42 -07002507 if (is_dp)
2508 dpll |= DPLL_DVO_HIGH_SPEED;
Jesse Barnes79e53942008-11-07 14:24:08 -08002509
2510 /* compute bitmask from p1 value */
Shaohua Li21778322009-02-23 15:19:16 +08002511 if (IS_IGD(dev))
2512 dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_IGD;
Zhenyu Wang2c072452009-06-05 15:38:42 +08002513 else {
Shaohua Li21778322009-02-23 15:19:16 +08002514 dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
Zhenyu Wang2c072452009-06-05 15:38:42 +08002515 /* also FPA1 */
2516 if (IS_IGDNG(dev))
2517 dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
Jesse Barnes652c3932009-08-17 13:31:43 -07002518 if (IS_G4X(dev) && has_reduced_clock)
2519 dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
Zhenyu Wang2c072452009-06-05 15:38:42 +08002520 }
Jesse Barnes79e53942008-11-07 14:24:08 -08002521 switch (clock.p2) {
2522 case 5:
2523 dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
2524 break;
2525 case 7:
2526 dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
2527 break;
2528 case 10:
2529 dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
2530 break;
2531 case 14:
2532 dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
2533 break;
2534 }
Zhenyu Wang2c072452009-06-05 15:38:42 +08002535 if (IS_I965G(dev) && !IS_IGDNG(dev))
Jesse Barnes79e53942008-11-07 14:24:08 -08002536 dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
2537 } else {
2538 if (is_lvds) {
2539 dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
2540 } else {
2541 if (clock.p1 == 2)
2542 dpll |= PLL_P1_DIVIDE_BY_TWO;
2543 else
2544 dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT;
2545 if (clock.p2 == 4)
2546 dpll |= PLL_P2_DIVIDE_BY_4;
2547 }
2548 }
2549
Kristian Høgsberg43565a02009-02-13 20:56:52 -05002550 if (is_sdvo && is_tv)
2551 dpll |= PLL_REF_INPUT_TVCLKINBC;
2552 else if (is_tv)
Jesse Barnes79e53942008-11-07 14:24:08 -08002553 /* XXX: just matching BIOS for now */
Kristian Høgsberg43565a02009-02-13 20:56:52 -05002554 /* dpll |= PLL_REF_INPUT_TVCLKINBC; */
Jesse Barnes79e53942008-11-07 14:24:08 -08002555 dpll |= 3;
Kristian Høgsberg43565a02009-02-13 20:56:52 -05002556 else if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2)
2557 dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
Jesse Barnes79e53942008-11-07 14:24:08 -08002558 else
2559 dpll |= PLL_REF_INPUT_DREFCLK;
2560
2561 /* setup pipeconf */
2562 pipeconf = I915_READ(pipeconf_reg);
2563
2564 /* Set up the display plane register */
2565 dspcntr = DISPPLANE_GAMMA_ENABLE;
2566
Zhenyu Wang2c072452009-06-05 15:38:42 +08002567 /* IGDNG's plane is forced to pipe, bit 24 is to
2568 enable color space conversion */
2569 if (!IS_IGDNG(dev)) {
2570 if (pipe == 0)
2571 dspcntr |= DISPPLANE_SEL_PIPE_A;
2572 else
2573 dspcntr |= DISPPLANE_SEL_PIPE_B;
2574 }
Jesse Barnes79e53942008-11-07 14:24:08 -08002575
2576 if (pipe == 0 && !IS_I965G(dev)) {
2577 /* Enable pixel doubling when the dot clock is > 90% of the (display)
2578 * core speed.
2579 *
2580 * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
2581 * pipe == 0 check?
2582 */
2583 if (mode->clock > intel_get_core_clock_speed(dev) * 9 / 10)
2584 pipeconf |= PIPEACONF_DOUBLE_WIDE;
2585 else
2586 pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
2587 }
2588
2589 dspcntr |= DISPLAY_PLANE_ENABLE;
2590 pipeconf |= PIPEACONF_ENABLE;
2591 dpll |= DPLL_VCO_ENABLE;
2592
2593
2594 /* Disable the panel fitter if it was on our pipe */
Zhenyu Wang2c072452009-06-05 15:38:42 +08002595 if (!IS_IGDNG(dev) && intel_panel_fitter_pipe(dev) == pipe)
Jesse Barnes79e53942008-11-07 14:24:08 -08002596 I915_WRITE(PFIT_CONTROL, 0);
2597
2598 DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
2599 drm_mode_debug_printmodeline(mode);
2600
Zhenyu Wang2c072452009-06-05 15:38:42 +08002601 /* assign to IGDNG registers */
2602 if (IS_IGDNG(dev)) {
2603 fp_reg = pch_fp_reg;
2604 dpll_reg = pch_dpll_reg;
2605 }
Jesse Barnes79e53942008-11-07 14:24:08 -08002606
Zhenyu Wang32f9d652009-07-24 01:00:32 +08002607 if (is_edp) {
2608 igdng_disable_pll_edp(crtc);
2609 } else if ((dpll & DPLL_VCO_ENABLE)) {
Jesse Barnes79e53942008-11-07 14:24:08 -08002610 I915_WRITE(fp_reg, fp);
2611 I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
2612 I915_READ(dpll_reg);
2613 udelay(150);
2614 }
2615
2616 /* The LVDS pin pair needs to be on before the DPLLs are enabled.
2617 * This is an exception to the general rule that mode_set doesn't turn
2618 * things on.
2619 */
2620 if (is_lvds) {
Zhenyu Wang541998a2009-06-05 15:38:44 +08002621 u32 lvds;
Jesse Barnes79e53942008-11-07 14:24:08 -08002622
Zhenyu Wang541998a2009-06-05 15:38:44 +08002623 if (IS_IGDNG(dev))
2624 lvds_reg = PCH_LVDS;
2625
2626 lvds = I915_READ(lvds_reg);
Jesse Barnes79e53942008-11-07 14:24:08 -08002627 lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
2628 /* Set the B0-B3 data pairs corresponding to whether we're going to
2629 * set the DPLLs for dual-channel mode or not.
2630 */
2631 if (clock.p2 == 7)
2632 lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
2633 else
2634 lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
2635
2636 /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
2637 * appropriately here, but we need to look more thoroughly into how
2638 * panels behave in the two modes.
2639 */
2640
Zhenyu Wang541998a2009-06-05 15:38:44 +08002641 I915_WRITE(lvds_reg, lvds);
2642 I915_READ(lvds_reg);
Jesse Barnes79e53942008-11-07 14:24:08 -08002643 }
Keith Packarda4fc5ed2009-04-07 16:16:42 -07002644 if (is_dp)
2645 intel_dp_set_m_n(crtc, mode, adjusted_mode);
Jesse Barnes79e53942008-11-07 14:24:08 -08002646
Zhenyu Wang32f9d652009-07-24 01:00:32 +08002647 if (!is_edp) {
2648 I915_WRITE(fp_reg, fp);
Jesse Barnes79e53942008-11-07 14:24:08 -08002649 I915_WRITE(dpll_reg, dpll);
Zhenyu Wang32f9d652009-07-24 01:00:32 +08002650 I915_READ(dpll_reg);
2651 /* Wait for the clocks to stabilize. */
2652 udelay(150);
2653
2654 if (IS_I965G(dev) && !IS_IGDNG(dev)) {
2655 sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
2656 I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
2657 ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
2658 } else {
2659 /* write it again -- the BIOS does, after all */
2660 I915_WRITE(dpll_reg, dpll);
2661 }
2662 I915_READ(dpll_reg);
2663 /* Wait for the clocks to stabilize. */
2664 udelay(150);
Jesse Barnes79e53942008-11-07 14:24:08 -08002665 }
Jesse Barnes79e53942008-11-07 14:24:08 -08002666
Jesse Barnes652c3932009-08-17 13:31:43 -07002667 if (is_lvds && has_reduced_clock && i915_powersave) {
2668 I915_WRITE(fp_reg + 4, fp2);
2669 intel_crtc->lowfreq_avail = true;
2670 if (HAS_PIPE_CXSR(dev)) {
2671 DRM_DEBUG("enabling CxSR downclocking\n");
2672 pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
2673 }
2674 } else {
2675 I915_WRITE(fp_reg + 4, fp);
2676 intel_crtc->lowfreq_avail = false;
2677 if (HAS_PIPE_CXSR(dev)) {
2678 DRM_DEBUG("disabling CxSR downclocking\n");
2679 pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
2680 }
2681 }
2682
Jesse Barnes79e53942008-11-07 14:24:08 -08002683 I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
2684 ((adjusted_mode->crtc_htotal - 1) << 16));
2685 I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
2686 ((adjusted_mode->crtc_hblank_end - 1) << 16));
2687 I915_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
2688 ((adjusted_mode->crtc_hsync_end - 1) << 16));
2689 I915_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
2690 ((adjusted_mode->crtc_vtotal - 1) << 16));
2691 I915_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
2692 ((adjusted_mode->crtc_vblank_end - 1) << 16));
2693 I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
2694 ((adjusted_mode->crtc_vsync_end - 1) << 16));
2695 /* pipesrc and dspsize control the size that is scaled from, which should
2696 * always be the user's requested size.
2697 */
Zhenyu Wang2c072452009-06-05 15:38:42 +08002698 if (!IS_IGDNG(dev)) {
2699 I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) |
2700 (mode->hdisplay - 1));
2701 I915_WRITE(dsppos_reg, 0);
2702 }
Jesse Barnes79e53942008-11-07 14:24:08 -08002703 I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
Zhenyu Wang2c072452009-06-05 15:38:42 +08002704
2705 if (IS_IGDNG(dev)) {
2706 I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m);
2707 I915_WRITE(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n);
2708 I915_WRITE(link_m1_reg, m_n.link_m);
2709 I915_WRITE(link_n1_reg, m_n.link_n);
2710
Zhenyu Wang32f9d652009-07-24 01:00:32 +08002711 if (is_edp) {
2712 igdng_set_pll_edp(crtc, adjusted_mode->clock);
2713 } else {
2714 /* enable FDI RX PLL too */
2715 temp = I915_READ(fdi_rx_reg);
2716 I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
2717 udelay(200);
2718 }
Zhenyu Wang2c072452009-06-05 15:38:42 +08002719 }
2720
Jesse Barnes79e53942008-11-07 14:24:08 -08002721 I915_WRITE(pipeconf_reg, pipeconf);
2722 I915_READ(pipeconf_reg);
2723
2724 intel_wait_for_vblank(dev);
2725
Zhenyu Wang553bd142009-09-02 10:57:52 +08002726 if (IS_IGDNG(dev)) {
2727 /* enable address swizzle for tiling buffer */
2728 temp = I915_READ(DISP_ARB_CTL);
2729 I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING);
2730 }
2731
Jesse Barnes79e53942008-11-07 14:24:08 -08002732 I915_WRITE(dspcntr_reg, dspcntr);
2733
2734 /* Flush the plane changes */
Chris Wilson5c3b82e2009-02-11 13:25:09 +00002735 ret = intel_pipe_set_base(crtc, x, y, old_fb);
Shaohua Li7662c8b2009-06-26 11:23:55 +08002736
2737 intel_update_watermarks(dev);
2738
Jesse Barnes79e53942008-11-07 14:24:08 -08002739 drm_vblank_post_modeset(dev, pipe);
Chris Wilson5c3b82e2009-02-11 13:25:09 +00002740
Chris Wilson1f803ee2009-06-06 09:45:59 +01002741 return ret;
Jesse Barnes79e53942008-11-07 14:24:08 -08002742}
2743
2744/** Loads the palette/gamma unit for the CRTC with the prepared values */
2745void intel_crtc_load_lut(struct drm_crtc *crtc)
2746{
2747 struct drm_device *dev = crtc->dev;
2748 struct drm_i915_private *dev_priv = dev->dev_private;
2749 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2750 int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B;
2751 int i;
2752
2753 /* The clocks have to be on to load the palette. */
2754 if (!crtc->enabled)
2755 return;
2756
Zhenyu Wang2c072452009-06-05 15:38:42 +08002757 /* use legacy palette for IGDNG */
2758 if (IS_IGDNG(dev))
2759 palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A :
2760 LGC_PALETTE_B;
2761
Jesse Barnes79e53942008-11-07 14:24:08 -08002762 for (i = 0; i < 256; i++) {
2763 I915_WRITE(palreg + 4 * i,
2764 (intel_crtc->lut_r[i] << 16) |
2765 (intel_crtc->lut_g[i] << 8) |
2766 intel_crtc->lut_b[i]);
2767 }
2768}
2769
2770static int intel_crtc_cursor_set(struct drm_crtc *crtc,
2771 struct drm_file *file_priv,
2772 uint32_t handle,
2773 uint32_t width, uint32_t height)
2774{
2775 struct drm_device *dev = crtc->dev;
2776 struct drm_i915_private *dev_priv = dev->dev_private;
2777 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2778 struct drm_gem_object *bo;
2779 struct drm_i915_gem_object *obj_priv;
2780 int pipe = intel_crtc->pipe;
2781 uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
2782 uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
Jesse Barnes14b60392009-05-20 16:47:08 -04002783 uint32_t temp = I915_READ(control);
Jesse Barnes79e53942008-11-07 14:24:08 -08002784 size_t addr;
Kristian Høgsberg3f8bc372008-12-17 22:14:59 -05002785 int ret;
Jesse Barnes79e53942008-11-07 14:24:08 -08002786
2787 DRM_DEBUG("\n");
2788
2789 /* if we want to turn off the cursor ignore width and height */
2790 if (!handle) {
2791 DRM_DEBUG("cursor off\n");
Jesse Barnes14b60392009-05-20 16:47:08 -04002792 if (IS_MOBILE(dev) || IS_I9XX(dev)) {
2793 temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
2794 temp |= CURSOR_MODE_DISABLE;
2795 } else {
2796 temp &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
2797 }
Kristian Høgsberg3f8bc372008-12-17 22:14:59 -05002798 addr = 0;
2799 bo = NULL;
Pierre Willenbrock50044172009-02-23 10:12:15 +10002800 mutex_lock(&dev->struct_mutex);
Kristian Høgsberg3f8bc372008-12-17 22:14:59 -05002801 goto finish;
Jesse Barnes79e53942008-11-07 14:24:08 -08002802 }
2803
2804 /* Currently we only support 64x64 cursors */
2805 if (width != 64 || height != 64) {
2806 DRM_ERROR("we currently only support 64x64 cursors\n");
2807 return -EINVAL;
2808 }
2809
2810 bo = drm_gem_object_lookup(dev, file_priv, handle);
2811 if (!bo)
2812 return -ENOENT;
2813
2814 obj_priv = bo->driver_private;
2815
2816 if (bo->size < width * height * 4) {
2817 DRM_ERROR("buffer is to small\n");
Dave Airlie34b8686e2009-01-15 14:03:07 +10002818 ret = -ENOMEM;
2819 goto fail;
Jesse Barnes79e53942008-11-07 14:24:08 -08002820 }
2821
Dave Airlie71acb5e2008-12-30 20:31:46 +10002822 /* we only need to pin inside GTT if cursor is non-phy */
Kristian Høgsberg7f9872e2009-02-13 20:56:49 -05002823 mutex_lock(&dev->struct_mutex);
Dave Airlie71acb5e2008-12-30 20:31:46 +10002824 if (!dev_priv->cursor_needs_physical) {
2825 ret = i915_gem_object_pin(bo, PAGE_SIZE);
2826 if (ret) {
2827 DRM_ERROR("failed to pin cursor bo\n");
Kristian Høgsberg7f9872e2009-02-13 20:56:49 -05002828 goto fail_locked;
Dave Airlie71acb5e2008-12-30 20:31:46 +10002829 }
Jesse Barnes79e53942008-11-07 14:24:08 -08002830 addr = obj_priv->gtt_offset;
Dave Airlie71acb5e2008-12-30 20:31:46 +10002831 } else {
2832 ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
2833 if (ret) {
2834 DRM_ERROR("failed to attach phys object\n");
Kristian Høgsberg7f9872e2009-02-13 20:56:49 -05002835 goto fail_locked;
Dave Airlie71acb5e2008-12-30 20:31:46 +10002836 }
2837 addr = obj_priv->phys_obj->handle->busaddr;
Kristian Høgsberg3f8bc372008-12-17 22:14:59 -05002838 }
2839
Jesse Barnes14b60392009-05-20 16:47:08 -04002840 if (!IS_I9XX(dev))
2841 I915_WRITE(CURSIZE, (height << 12) | width);
2842
2843 /* Hooray for CUR*CNTR differences */
2844 if (IS_MOBILE(dev) || IS_I9XX(dev)) {
2845 temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
2846 temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
2847 temp |= (pipe << 28); /* Connect to correct pipe */
2848 } else {
2849 temp &= ~(CURSOR_FORMAT_MASK);
2850 temp |= CURSOR_ENABLE;
2851 temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
2852 }
Jesse Barnes79e53942008-11-07 14:24:08 -08002853
Kristian Høgsberg3f8bc372008-12-17 22:14:59 -05002854 finish:
Jesse Barnes79e53942008-11-07 14:24:08 -08002855 I915_WRITE(control, temp);
2856 I915_WRITE(base, addr);
2857
Kristian Høgsberg3f8bc372008-12-17 22:14:59 -05002858 if (intel_crtc->cursor_bo) {
Dave Airlie71acb5e2008-12-30 20:31:46 +10002859 if (dev_priv->cursor_needs_physical) {
2860 if (intel_crtc->cursor_bo != bo)
2861 i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
2862 } else
2863 i915_gem_object_unpin(intel_crtc->cursor_bo);
Kristian Høgsberg3f8bc372008-12-17 22:14:59 -05002864 drm_gem_object_unreference(intel_crtc->cursor_bo);
2865 }
Kristian Høgsberg7f9872e2009-02-13 20:56:49 -05002866 mutex_unlock(&dev->struct_mutex);
Kristian Høgsberg3f8bc372008-12-17 22:14:59 -05002867
2868 intel_crtc->cursor_addr = addr;
2869 intel_crtc->cursor_bo = bo;
2870
Jesse Barnes79e53942008-11-07 14:24:08 -08002871 return 0;
Dave Airlie34b8686e2009-01-15 14:03:07 +10002872fail:
2873 mutex_lock(&dev->struct_mutex);
Kristian Høgsberg7f9872e2009-02-13 20:56:49 -05002874fail_locked:
Dave Airlie34b8686e2009-01-15 14:03:07 +10002875 drm_gem_object_unreference(bo);
2876 mutex_unlock(&dev->struct_mutex);
2877 return ret;
Jesse Barnes79e53942008-11-07 14:24:08 -08002878}
2879
2880static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
2881{
2882 struct drm_device *dev = crtc->dev;
2883 struct drm_i915_private *dev_priv = dev->dev_private;
2884 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
Jesse Barnes652c3932009-08-17 13:31:43 -07002885 struct intel_framebuffer *intel_fb;
Jesse Barnes79e53942008-11-07 14:24:08 -08002886 int pipe = intel_crtc->pipe;
2887 uint32_t temp = 0;
2888 uint32_t adder;
2889
Jesse Barnes652c3932009-08-17 13:31:43 -07002890 if (crtc->fb) {
2891 intel_fb = to_intel_framebuffer(crtc->fb);
2892 intel_mark_busy(dev, intel_fb->obj);
2893 }
2894
Jesse Barnes79e53942008-11-07 14:24:08 -08002895 if (x < 0) {
Keith Packard2245fda2009-05-30 20:42:29 -07002896 temp |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
Jesse Barnes79e53942008-11-07 14:24:08 -08002897 x = -x;
2898 }
2899 if (y < 0) {
Keith Packard2245fda2009-05-30 20:42:29 -07002900 temp |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
Jesse Barnes79e53942008-11-07 14:24:08 -08002901 y = -y;
2902 }
2903
Keith Packard2245fda2009-05-30 20:42:29 -07002904 temp |= x << CURSOR_X_SHIFT;
2905 temp |= y << CURSOR_Y_SHIFT;
Jesse Barnes79e53942008-11-07 14:24:08 -08002906
2907 adder = intel_crtc->cursor_addr;
2908 I915_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
2909 I915_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
2910
2911 return 0;
2912}
2913
2914/** Sets the color ramps on behalf of RandR */
2915void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
2916 u16 blue, int regno)
2917{
2918 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2919
2920 intel_crtc->lut_r[regno] = red >> 8;
2921 intel_crtc->lut_g[regno] = green >> 8;
2922 intel_crtc->lut_b[regno] = blue >> 8;
2923}
2924
2925static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
2926 u16 *blue, uint32_t size)
2927{
2928 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2929 int i;
2930
2931 if (size != 256)
2932 return;
2933
2934 for (i = 0; i < 256; i++) {
2935 intel_crtc->lut_r[i] = red[i] >> 8;
2936 intel_crtc->lut_g[i] = green[i] >> 8;
2937 intel_crtc->lut_b[i] = blue[i] >> 8;
2938 }
2939
2940 intel_crtc_load_lut(crtc);
2941}
2942
2943/**
2944 * Get a pipe with a simple mode set on it for doing load-based monitor
2945 * detection.
2946 *
2947 * It will be up to the load-detect code to adjust the pipe as appropriate for
2948 * its requirements. The pipe will be connected to no other outputs.
2949 *
2950 * Currently this code will only succeed if there is a pipe with no outputs
2951 * configured for it. In the future, it could choose to temporarily disable
2952 * some outputs to free up a pipe for its use.
2953 *
2954 * \return crtc, or NULL if no pipes are available.
2955 */
2956
2957/* VESA 640x480x72Hz mode to set on the pipe */
2958static struct drm_display_mode load_detect_mode = {
2959 DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
2960 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
2961};
2962
2963struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output,
2964 struct drm_display_mode *mode,
2965 int *dpms_mode)
2966{
2967 struct intel_crtc *intel_crtc;
2968 struct drm_crtc *possible_crtc;
2969 struct drm_crtc *supported_crtc =NULL;
2970 struct drm_encoder *encoder = &intel_output->enc;
2971 struct drm_crtc *crtc = NULL;
2972 struct drm_device *dev = encoder->dev;
2973 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
2974 struct drm_crtc_helper_funcs *crtc_funcs;
2975 int i = -1;
2976
2977 /*
2978 * Algorithm gets a little messy:
2979 * - if the connector already has an assigned crtc, use it (but make
2980 * sure it's on first)
2981 * - try to find the first unused crtc that can drive this connector,
2982 * and use that if we find one
2983 * - if there are no unused crtcs available, try to use the first
2984 * one we found that supports the connector
2985 */
2986
2987 /* See if we already have a CRTC for this connector */
2988 if (encoder->crtc) {
2989 crtc = encoder->crtc;
2990 /* Make sure the crtc and connector are running */
2991 intel_crtc = to_intel_crtc(crtc);
2992 *dpms_mode = intel_crtc->dpms_mode;
2993 if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
2994 crtc_funcs = crtc->helper_private;
2995 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
2996 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
2997 }
2998 return crtc;
2999 }
3000
3001 /* Find an unused one (if possible) */
3002 list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) {
3003 i++;
3004 if (!(encoder->possible_crtcs & (1 << i)))
3005 continue;
3006 if (!possible_crtc->enabled) {
3007 crtc = possible_crtc;
3008 break;
3009 }
3010 if (!supported_crtc)
3011 supported_crtc = possible_crtc;
3012 }
3013
3014 /*
3015 * If we didn't find an unused CRTC, don't use any.
3016 */
3017 if (!crtc) {
3018 return NULL;
3019 }
3020
3021 encoder->crtc = crtc;
Keith Packard03d60692009-06-05 18:19:56 -07003022 intel_output->base.encoder = encoder;
Jesse Barnes79e53942008-11-07 14:24:08 -08003023 intel_output->load_detect_temp = true;
3024
3025 intel_crtc = to_intel_crtc(crtc);
3026 *dpms_mode = intel_crtc->dpms_mode;
3027
3028 if (!crtc->enabled) {
3029 if (!mode)
3030 mode = &load_detect_mode;
Kristian Høgsberg3c4fdcf2008-12-17 22:14:46 -05003031 drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb);
Jesse Barnes79e53942008-11-07 14:24:08 -08003032 } else {
3033 if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
3034 crtc_funcs = crtc->helper_private;
3035 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
3036 }
3037
3038 /* Add this connector to the crtc */
3039 encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->mode);
3040 encoder_funcs->commit(encoder);
3041 }
3042 /* let the connector get through one full cycle before testing */
3043 intel_wait_for_vblank(dev);
3044
3045 return crtc;
3046}
3047
3048void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_mode)
3049{
3050 struct drm_encoder *encoder = &intel_output->enc;
3051 struct drm_device *dev = encoder->dev;
3052 struct drm_crtc *crtc = encoder->crtc;
3053 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
3054 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
3055
3056 if (intel_output->load_detect_temp) {
3057 encoder->crtc = NULL;
Keith Packard03d60692009-06-05 18:19:56 -07003058 intel_output->base.encoder = NULL;
Jesse Barnes79e53942008-11-07 14:24:08 -08003059 intel_output->load_detect_temp = false;
3060 crtc->enabled = drm_helper_crtc_in_use(crtc);
3061 drm_helper_disable_unused_functions(dev);
3062 }
3063
3064 /* Switch crtc and output back off if necessary */
3065 if (crtc->enabled && dpms_mode != DRM_MODE_DPMS_ON) {
3066 if (encoder->crtc == crtc)
3067 encoder_funcs->dpms(encoder, dpms_mode);
3068 crtc_funcs->dpms(crtc, dpms_mode);
3069 }
3070}
3071
3072/* Returns the clock of the currently programmed mode of the given pipe. */
3073static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
3074{
3075 struct drm_i915_private *dev_priv = dev->dev_private;
3076 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
3077 int pipe = intel_crtc->pipe;
3078 u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B);
3079 u32 fp;
3080 intel_clock_t clock;
3081
3082 if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
3083 fp = I915_READ((pipe == 0) ? FPA0 : FPB0);
3084 else
3085 fp = I915_READ((pipe == 0) ? FPA1 : FPB1);
3086
3087 clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
Shaohua Li21778322009-02-23 15:19:16 +08003088 if (IS_IGD(dev)) {
3089 clock.n = ffs((fp & FP_N_IGD_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
3090 clock.m2 = (fp & FP_M2_IGD_DIV_MASK) >> FP_M2_DIV_SHIFT;
3091 } else {
3092 clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
3093 clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
3094 }
3095
Jesse Barnes79e53942008-11-07 14:24:08 -08003096 if (IS_I9XX(dev)) {
Shaohua Li21778322009-02-23 15:19:16 +08003097 if (IS_IGD(dev))
3098 clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_IGD) >>
3099 DPLL_FPA01_P1_POST_DIV_SHIFT_IGD);
3100 else
3101 clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
Jesse Barnes79e53942008-11-07 14:24:08 -08003102 DPLL_FPA01_P1_POST_DIV_SHIFT);
3103
3104 switch (dpll & DPLL_MODE_MASK) {
3105 case DPLLB_MODE_DAC_SERIAL:
3106 clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ?
3107 5 : 10;
3108 break;
3109 case DPLLB_MODE_LVDS:
3110 clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ?
3111 7 : 14;
3112 break;
3113 default:
3114 DRM_DEBUG("Unknown DPLL mode %08x in programmed "
3115 "mode\n", (int)(dpll & DPLL_MODE_MASK));
3116 return 0;
3117 }
3118
3119 /* XXX: Handle the 100Mhz refclk */
Shaohua Li21778322009-02-23 15:19:16 +08003120 intel_clock(dev, 96000, &clock);
Jesse Barnes79e53942008-11-07 14:24:08 -08003121 } else {
3122 bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
3123
3124 if (is_lvds) {
3125 clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
3126 DPLL_FPA01_P1_POST_DIV_SHIFT);
3127 clock.p2 = 14;
3128
3129 if ((dpll & PLL_REF_INPUT_MASK) ==
3130 PLLB_REF_INPUT_SPREADSPECTRUMIN) {
3131 /* XXX: might not be 66MHz */
Shaohua Li21778322009-02-23 15:19:16 +08003132 intel_clock(dev, 66000, &clock);
Jesse Barnes79e53942008-11-07 14:24:08 -08003133 } else
Shaohua Li21778322009-02-23 15:19:16 +08003134 intel_clock(dev, 48000, &clock);
Jesse Barnes79e53942008-11-07 14:24:08 -08003135 } else {
3136 if (dpll & PLL_P1_DIVIDE_BY_TWO)
3137 clock.p1 = 2;
3138 else {
3139 clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
3140 DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
3141 }
3142 if (dpll & PLL_P2_DIVIDE_BY_4)
3143 clock.p2 = 4;
3144 else
3145 clock.p2 = 2;
3146
Shaohua Li21778322009-02-23 15:19:16 +08003147 intel_clock(dev, 48000, &clock);
Jesse Barnes79e53942008-11-07 14:24:08 -08003148 }
3149 }
3150
3151 /* XXX: It would be nice to validate the clocks, but we can't reuse
3152 * i830PllIsValid() because it relies on the xf86_config connector
3153 * configuration being accurate, which it isn't necessarily.
3154 */
3155
3156 return clock.dot;
3157}
3158
3159/** Returns the currently programmed mode of the given pipe. */
3160struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
3161 struct drm_crtc *crtc)
3162{
3163 struct drm_i915_private *dev_priv = dev->dev_private;
3164 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
3165 int pipe = intel_crtc->pipe;
3166 struct drm_display_mode *mode;
3167 int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
3168 int hsync = I915_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
3169 int vtot = I915_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
3170 int vsync = I915_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
3171
3172 mode = kzalloc(sizeof(*mode), GFP_KERNEL);
3173 if (!mode)
3174 return NULL;
3175
3176 mode->clock = intel_crtc_clock_get(dev, crtc);
3177 mode->hdisplay = (htot & 0xffff) + 1;
3178 mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
3179 mode->hsync_start = (hsync & 0xffff) + 1;
3180 mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
3181 mode->vdisplay = (vtot & 0xffff) + 1;
3182 mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
3183 mode->vsync_start = (vsync & 0xffff) + 1;
3184 mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
3185
3186 drm_mode_set_name(mode);
3187 drm_mode_set_crtcinfo(mode, 0);
3188
3189 return mode;
3190}
3191
Jesse Barnes652c3932009-08-17 13:31:43 -07003192#define GPU_IDLE_TIMEOUT 500 /* ms */
3193
3194/* When this timer fires, we've been idle for awhile */
3195static void intel_gpu_idle_timer(unsigned long arg)
3196{
3197 struct drm_device *dev = (struct drm_device *)arg;
3198 drm_i915_private_t *dev_priv = dev->dev_private;
3199
3200 DRM_DEBUG("idle timer fired, downclocking\n");
3201
3202 dev_priv->busy = false;
3203
Eric Anholt01dfba92009-09-06 15:18:53 -07003204 queue_work(dev_priv->wq, &dev_priv->idle_work);
Jesse Barnes652c3932009-08-17 13:31:43 -07003205}
3206
3207void intel_increase_renderclock(struct drm_device *dev, bool schedule)
3208{
3209 drm_i915_private_t *dev_priv = dev->dev_private;
3210
3211 if (IS_IGDNG(dev))
3212 return;
3213
3214 if (!dev_priv->render_reclock_avail) {
Eric Anholt67cf7812009-08-31 08:52:02 -07003215 DRM_DEBUG("not reclocking render clock\n");
Jesse Barnes652c3932009-08-17 13:31:43 -07003216 return;
3217 }
3218
3219 /* Restore render clock frequency to original value */
3220 if (IS_G4X(dev) || IS_I9XX(dev))
3221 pci_write_config_word(dev->pdev, GCFGC, dev_priv->orig_clock);
3222 else if (IS_I85X(dev))
3223 pci_write_config_word(dev->pdev, HPLLCC, dev_priv->orig_clock);
3224 DRM_DEBUG("increasing render clock frequency\n");
3225
3226 /* Schedule downclock */
3227 if (schedule)
3228 mod_timer(&dev_priv->idle_timer, jiffies +
3229 msecs_to_jiffies(GPU_IDLE_TIMEOUT));
3230}
3231
3232void intel_decrease_renderclock(struct drm_device *dev)
3233{
3234 drm_i915_private_t *dev_priv = dev->dev_private;
3235
3236 if (IS_IGDNG(dev))
3237 return;
3238
3239 if (!dev_priv->render_reclock_avail) {
Eric Anholt67cf7812009-08-31 08:52:02 -07003240 DRM_DEBUG("not reclocking render clock\n");
Jesse Barnes652c3932009-08-17 13:31:43 -07003241 return;
3242 }
3243
3244 if (IS_G4X(dev)) {
3245 u16 gcfgc;
3246
3247 /* Adjust render clock... */
3248 pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
3249
3250 /* Down to minimum... */
3251 gcfgc &= ~GM45_GC_RENDER_CLOCK_MASK;
3252 gcfgc |= GM45_GC_RENDER_CLOCK_266_MHZ;
3253
3254 pci_write_config_word(dev->pdev, GCFGC, gcfgc);
3255 } else if (IS_I965G(dev)) {
3256 u16 gcfgc;
3257
3258 /* Adjust render clock... */
3259 pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
3260
3261 /* Down to minimum... */
3262 gcfgc &= ~I965_GC_RENDER_CLOCK_MASK;
3263 gcfgc |= I965_GC_RENDER_CLOCK_267_MHZ;
3264
3265 pci_write_config_word(dev->pdev, GCFGC, gcfgc);
3266 } else if (IS_I945G(dev) || IS_I945GM(dev)) {
3267 u16 gcfgc;
3268
3269 /* Adjust render clock... */
3270 pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
3271
3272 /* Down to minimum... */
3273 gcfgc &= ~I945_GC_RENDER_CLOCK_MASK;
3274 gcfgc |= I945_GC_RENDER_CLOCK_166_MHZ;
3275
3276 pci_write_config_word(dev->pdev, GCFGC, gcfgc);
3277 } else if (IS_I915G(dev)) {
3278 u16 gcfgc;
3279
3280 /* Adjust render clock... */
3281 pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
3282
3283 /* Down to minimum... */
3284 gcfgc &= ~I915_GC_RENDER_CLOCK_MASK;
3285 gcfgc |= I915_GC_RENDER_CLOCK_166_MHZ;
3286
3287 pci_write_config_word(dev->pdev, GCFGC, gcfgc);
3288 } else if (IS_I85X(dev)) {
3289 u16 hpllcc;
3290
3291 /* Adjust render clock... */
3292 pci_read_config_word(dev->pdev, HPLLCC, &hpllcc);
3293
3294 /* Up to maximum... */
3295 hpllcc &= ~GC_CLOCK_CONTROL_MASK;
3296 hpllcc |= GC_CLOCK_133_200;
3297
3298 pci_write_config_word(dev->pdev, HPLLCC, hpllcc);
3299 }
3300 DRM_DEBUG("decreasing render clock frequency\n");
3301}
3302
3303/* Note that no increase function is needed for this - increase_renderclock()
3304 * will also rewrite these bits
3305 */
3306void intel_decrease_displayclock(struct drm_device *dev)
3307{
3308 if (IS_IGDNG(dev))
3309 return;
3310
3311 if (IS_I945G(dev) || IS_I945GM(dev) || IS_I915G(dev) ||
3312 IS_I915GM(dev)) {
3313 u16 gcfgc;
3314
3315 /* Adjust render clock... */
3316 pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
3317
3318 /* Down to minimum... */
3319 gcfgc &= ~0xf0;
3320 gcfgc |= 0x80;
3321
3322 pci_write_config_word(dev->pdev, GCFGC, gcfgc);
3323 }
3324}
3325
3326#define CRTC_IDLE_TIMEOUT 1000 /* ms */
3327
3328static void intel_crtc_idle_timer(unsigned long arg)
3329{
3330 struct intel_crtc *intel_crtc = (struct intel_crtc *)arg;
3331 struct drm_crtc *crtc = &intel_crtc->base;
3332 drm_i915_private_t *dev_priv = crtc->dev->dev_private;
3333
3334 DRM_DEBUG("idle timer fired, downclocking\n");
3335
3336 intel_crtc->busy = false;
3337
Eric Anholt01dfba92009-09-06 15:18:53 -07003338 queue_work(dev_priv->wq, &dev_priv->idle_work);
Jesse Barnes652c3932009-08-17 13:31:43 -07003339}
3340
3341static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule)
3342{
3343 struct drm_device *dev = crtc->dev;
3344 drm_i915_private_t *dev_priv = dev->dev_private;
3345 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
3346 int pipe = intel_crtc->pipe;
3347 int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
3348 int dpll = I915_READ(dpll_reg);
3349
3350 if (IS_IGDNG(dev))
3351 return;
3352
3353 if (!dev_priv->lvds_downclock_avail)
3354 return;
3355
3356 if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
3357 DRM_DEBUG("upclocking LVDS\n");
3358
3359 /* Unlock panel regs */
3360 I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
3361
3362 dpll &= ~DISPLAY_RATE_SELECT_FPA1;
3363 I915_WRITE(dpll_reg, dpll);
3364 dpll = I915_READ(dpll_reg);
3365 intel_wait_for_vblank(dev);
3366 dpll = I915_READ(dpll_reg);
3367 if (dpll & DISPLAY_RATE_SELECT_FPA1)
3368 DRM_DEBUG("failed to upclock LVDS!\n");
3369
3370 /* ...and lock them again */
3371 I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
3372 }
3373
3374 /* Schedule downclock */
3375 if (schedule)
3376 mod_timer(&intel_crtc->idle_timer, jiffies +
3377 msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
3378}
3379
3380static void intel_decrease_pllclock(struct drm_crtc *crtc)
3381{
3382 struct drm_device *dev = crtc->dev;
3383 drm_i915_private_t *dev_priv = dev->dev_private;
3384 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
3385 int pipe = intel_crtc->pipe;
3386 int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
3387 int dpll = I915_READ(dpll_reg);
3388
3389 if (IS_IGDNG(dev))
3390 return;
3391
3392 if (!dev_priv->lvds_downclock_avail)
3393 return;
3394
3395 /*
3396 * Since this is called by a timer, we should never get here in
3397 * the manual case.
3398 */
3399 if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
3400 DRM_DEBUG("downclocking LVDS\n");
3401
3402 /* Unlock panel regs */
3403 I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
3404
3405 dpll |= DISPLAY_RATE_SELECT_FPA1;
3406 I915_WRITE(dpll_reg, dpll);
3407 dpll = I915_READ(dpll_reg);
3408 intel_wait_for_vblank(dev);
3409 dpll = I915_READ(dpll_reg);
3410 if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
3411 DRM_DEBUG("failed to downclock LVDS!\n");
3412
3413 /* ...and lock them again */
3414 I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
3415 }
3416
3417}
3418
3419/**
3420 * intel_idle_update - adjust clocks for idleness
3421 * @work: work struct
3422 *
3423 * Either the GPU or display (or both) went idle. Check the busy status
3424 * here and adjust the CRTC and GPU clocks as necessary.
3425 */
3426static void intel_idle_update(struct work_struct *work)
3427{
3428 drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
3429 idle_work);
3430 struct drm_device *dev = dev_priv->dev;
3431 struct drm_crtc *crtc;
3432 struct intel_crtc *intel_crtc;
3433
3434 if (!i915_powersave)
3435 return;
3436
3437 mutex_lock(&dev->struct_mutex);
3438
3439 /* GPU isn't processing, downclock it. */
3440 if (!dev_priv->busy) {
3441 intel_decrease_renderclock(dev);
3442 intel_decrease_displayclock(dev);
3443 }
3444
3445 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
3446 /* Skip inactive CRTCs */
3447 if (!crtc->fb)
3448 continue;
3449
3450 intel_crtc = to_intel_crtc(crtc);
3451 if (!intel_crtc->busy)
3452 intel_decrease_pllclock(crtc);
3453 }
3454
3455 mutex_unlock(&dev->struct_mutex);
3456}
3457
3458/**
3459 * intel_mark_busy - mark the GPU and possibly the display busy
3460 * @dev: drm device
3461 * @obj: object we're operating on
3462 *
3463 * Callers can use this function to indicate that the GPU is busy processing
3464 * commands. If @obj matches one of the CRTC objects (i.e. it's a scanout
3465 * buffer), we'll also mark the display as busy, so we know to increase its
3466 * clock frequency.
3467 */
3468void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
3469{
3470 drm_i915_private_t *dev_priv = dev->dev_private;
3471 struct drm_crtc *crtc = NULL;
3472 struct intel_framebuffer *intel_fb;
3473 struct intel_crtc *intel_crtc;
3474
Zhenyu Wang5e17ee72009-09-03 09:30:06 +08003475 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3476 return;
3477
Jesse Barnes652c3932009-08-17 13:31:43 -07003478 dev_priv->busy = true;
3479 intel_increase_renderclock(dev, true);
3480
3481 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
3482 if (!crtc->fb)
3483 continue;
3484
3485 intel_crtc = to_intel_crtc(crtc);
3486 intel_fb = to_intel_framebuffer(crtc->fb);
3487 if (intel_fb->obj == obj) {
3488 if (!intel_crtc->busy) {
3489 /* Non-busy -> busy, upclock */
3490 intel_increase_pllclock(crtc, true);
3491 intel_crtc->busy = true;
3492 } else {
3493 /* Busy -> busy, put off timer */
3494 mod_timer(&intel_crtc->idle_timer, jiffies +
3495 msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
3496 }
3497 }
3498 }
3499}
3500
Jesse Barnes79e53942008-11-07 14:24:08 -08003501static void intel_crtc_destroy(struct drm_crtc *crtc)
3502{
3503 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
3504
3505 drm_crtc_cleanup(crtc);
3506 kfree(intel_crtc);
3507}
3508
3509static const struct drm_crtc_helper_funcs intel_helper_funcs = {
3510 .dpms = intel_crtc_dpms,
3511 .mode_fixup = intel_crtc_mode_fixup,
3512 .mode_set = intel_crtc_mode_set,
3513 .mode_set_base = intel_pipe_set_base,
3514 .prepare = intel_crtc_prepare,
3515 .commit = intel_crtc_commit,
3516};
3517
3518static const struct drm_crtc_funcs intel_crtc_funcs = {
3519 .cursor_set = intel_crtc_cursor_set,
3520 .cursor_move = intel_crtc_cursor_move,
3521 .gamma_set = intel_crtc_gamma_set,
3522 .set_config = drm_crtc_helper_set_config,
3523 .destroy = intel_crtc_destroy,
3524};
3525
3526
Hannes Ederb358d0a2008-12-18 21:18:47 +01003527static void intel_crtc_init(struct drm_device *dev, int pipe)
Jesse Barnes79e53942008-11-07 14:24:08 -08003528{
3529 struct intel_crtc *intel_crtc;
3530 int i;
3531
3532 intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
3533 if (intel_crtc == NULL)
3534 return;
3535
3536 drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs);
3537
3538 drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
3539 intel_crtc->pipe = pipe;
Shaohua Li7662c8b2009-06-26 11:23:55 +08003540 intel_crtc->plane = pipe;
Jesse Barnes79e53942008-11-07 14:24:08 -08003541 for (i = 0; i < 256; i++) {
3542 intel_crtc->lut_r[i] = i;
3543 intel_crtc->lut_g[i] = i;
3544 intel_crtc->lut_b[i] = i;
3545 }
3546
3547 intel_crtc->cursor_addr = 0;
3548 intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF;
3549 drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
3550
Jesse Barnes652c3932009-08-17 13:31:43 -07003551 intel_crtc->busy = false;
3552
3553 setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
3554 (unsigned long)intel_crtc);
Jesse Barnes79e53942008-11-07 14:24:08 -08003555}
3556
Carl Worth08d7b3d2009-04-29 14:43:54 -07003557int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
3558 struct drm_file *file_priv)
3559{
3560 drm_i915_private_t *dev_priv = dev->dev_private;
3561 struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
Daniel Vetterc05422d2009-08-11 16:05:30 +02003562 struct drm_mode_object *drmmode_obj;
3563 struct intel_crtc *crtc;
Carl Worth08d7b3d2009-04-29 14:43:54 -07003564
3565 if (!dev_priv) {
3566 DRM_ERROR("called with no initialization\n");
3567 return -EINVAL;
3568 }
3569
Daniel Vetterc05422d2009-08-11 16:05:30 +02003570 drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
3571 DRM_MODE_OBJECT_CRTC);
Carl Worth08d7b3d2009-04-29 14:43:54 -07003572
Daniel Vetterc05422d2009-08-11 16:05:30 +02003573 if (!drmmode_obj) {
Carl Worth08d7b3d2009-04-29 14:43:54 -07003574 DRM_ERROR("no such CRTC id\n");
3575 return -EINVAL;
3576 }
3577
Daniel Vetterc05422d2009-08-11 16:05:30 +02003578 crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
3579 pipe_from_crtc_id->pipe = crtc->pipe;
Carl Worth08d7b3d2009-04-29 14:43:54 -07003580
Daniel Vetterc05422d2009-08-11 16:05:30 +02003581 return 0;
Carl Worth08d7b3d2009-04-29 14:43:54 -07003582}
3583
Jesse Barnes79e53942008-11-07 14:24:08 -08003584struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
3585{
3586 struct drm_crtc *crtc = NULL;
3587
3588 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
3589 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
3590 if (intel_crtc->pipe == pipe)
3591 break;
3592 }
3593 return crtc;
3594}
3595
Hannes Ederb358d0a2008-12-18 21:18:47 +01003596static int intel_connector_clones(struct drm_device *dev, int type_mask)
Jesse Barnes79e53942008-11-07 14:24:08 -08003597{
3598 int index_mask = 0;
3599 struct drm_connector *connector;
3600 int entry = 0;
3601
3602 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
3603 struct intel_output *intel_output = to_intel_output(connector);
Ma Lingf8aed702009-08-24 13:50:24 +08003604 if (type_mask & intel_output->clone_mask)
Jesse Barnes79e53942008-11-07 14:24:08 -08003605 index_mask |= (1 << entry);
3606 entry++;
3607 }
3608 return index_mask;
3609}
3610
3611
3612static void intel_setup_outputs(struct drm_device *dev)
3613{
Eric Anholt725e30a2009-01-22 13:01:02 -08003614 struct drm_i915_private *dev_priv = dev->dev_private;
Jesse Barnes79e53942008-11-07 14:24:08 -08003615 struct drm_connector *connector;
3616
3617 intel_crt_init(dev);
3618
3619 /* Set up integrated LVDS */
Zhenyu Wang541998a2009-06-05 15:38:44 +08003620 if (IS_MOBILE(dev) && !IS_I830(dev))
Jesse Barnes79e53942008-11-07 14:24:08 -08003621 intel_lvds_init(dev);
3622
Zhenyu Wang2c072452009-06-05 15:38:42 +08003623 if (IS_IGDNG(dev)) {
Zhenyu Wang30ad48b2009-06-05 15:38:43 +08003624 int found;
3625
Zhenyu Wang32f9d652009-07-24 01:00:32 +08003626 if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED))
3627 intel_dp_init(dev, DP_A);
3628
Zhenyu Wang30ad48b2009-06-05 15:38:43 +08003629 if (I915_READ(HDMIB) & PORT_DETECTED) {
3630 /* check SDVOB */
3631 /* found = intel_sdvo_init(dev, HDMIB); */
3632 found = 0;
3633 if (!found)
3634 intel_hdmi_init(dev, HDMIB);
Zhenyu Wang5eb08b62009-07-24 01:00:31 +08003635 if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
3636 intel_dp_init(dev, PCH_DP_B);
Zhenyu Wang30ad48b2009-06-05 15:38:43 +08003637 }
3638
3639 if (I915_READ(HDMIC) & PORT_DETECTED)
3640 intel_hdmi_init(dev, HDMIC);
3641
3642 if (I915_READ(HDMID) & PORT_DETECTED)
3643 intel_hdmi_init(dev, HDMID);
3644
Zhenyu Wang5eb08b62009-07-24 01:00:31 +08003645 if (I915_READ(PCH_DP_C) & DP_DETECTED)
3646 intel_dp_init(dev, PCH_DP_C);
3647
3648 if (I915_READ(PCH_DP_D) & DP_DETECTED)
3649 intel_dp_init(dev, PCH_DP_D);
3650
Zhenyu Wang2c072452009-06-05 15:38:42 +08003651 } else if (IS_I9XX(dev)) {
Ma Ling27185ae2009-08-24 13:50:23 +08003652 bool found = false;
Eric Anholt7d573822009-01-02 13:33:00 -08003653
Eric Anholt725e30a2009-01-22 13:01:02 -08003654 if (I915_READ(SDVOB) & SDVO_DETECTED) {
3655 found = intel_sdvo_init(dev, SDVOB);
3656 if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
3657 intel_hdmi_init(dev, SDVOB);
Ma Ling27185ae2009-08-24 13:50:23 +08003658
Keith Packarda4fc5ed2009-04-07 16:16:42 -07003659 if (!found && SUPPORTS_INTEGRATED_DP(dev))
3660 intel_dp_init(dev, DP_B);
Eric Anholt725e30a2009-01-22 13:01:02 -08003661 }
Kristian Høgsberg13520b02009-03-13 15:42:14 -04003662
3663 /* Before G4X SDVOC doesn't have its own detect register */
Kristian Høgsberg13520b02009-03-13 15:42:14 -04003664
Ma Ling27185ae2009-08-24 13:50:23 +08003665 if (I915_READ(SDVOB) & SDVO_DETECTED)
Eric Anholt725e30a2009-01-22 13:01:02 -08003666 found = intel_sdvo_init(dev, SDVOC);
Ma Ling27185ae2009-08-24 13:50:23 +08003667
3668 if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
3669
3670 if (SUPPORTS_INTEGRATED_HDMI(dev))
Eric Anholt725e30a2009-01-22 13:01:02 -08003671 intel_hdmi_init(dev, SDVOC);
Ma Ling27185ae2009-08-24 13:50:23 +08003672 if (SUPPORTS_INTEGRATED_DP(dev))
Keith Packarda4fc5ed2009-04-07 16:16:42 -07003673 intel_dp_init(dev, DP_C);
Eric Anholt725e30a2009-01-22 13:01:02 -08003674 }
Ma Ling27185ae2009-08-24 13:50:23 +08003675
Keith Packarda4fc5ed2009-04-07 16:16:42 -07003676 if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
3677 intel_dp_init(dev, DP_D);
Jesse Barnes79e53942008-11-07 14:24:08 -08003678 } else
3679 intel_dvo_init(dev);
3680
Zhenyu Wang2c072452009-06-05 15:38:42 +08003681 if (IS_I9XX(dev) && IS_MOBILE(dev) && !IS_IGDNG(dev))
Jesse Barnes79e53942008-11-07 14:24:08 -08003682 intel_tv_init(dev);
3683
3684 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
3685 struct intel_output *intel_output = to_intel_output(connector);
3686 struct drm_encoder *encoder = &intel_output->enc;
Jesse Barnes79e53942008-11-07 14:24:08 -08003687
Ma Lingf8aed702009-08-24 13:50:24 +08003688 encoder->possible_crtcs = intel_output->crtc_mask;
3689 encoder->possible_clones = intel_connector_clones(dev,
3690 intel_output->clone_mask);
Jesse Barnes79e53942008-11-07 14:24:08 -08003691 }
3692}
3693
3694static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
3695{
3696 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
3697 struct drm_device *dev = fb->dev;
3698
3699 if (fb->fbdev)
3700 intelfb_remove(dev, fb);
3701
3702 drm_framebuffer_cleanup(fb);
3703 mutex_lock(&dev->struct_mutex);
3704 drm_gem_object_unreference(intel_fb->obj);
3705 mutex_unlock(&dev->struct_mutex);
3706
3707 kfree(intel_fb);
3708}
3709
3710static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
3711 struct drm_file *file_priv,
3712 unsigned int *handle)
3713{
3714 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
3715 struct drm_gem_object *object = intel_fb->obj;
3716
3717 return drm_gem_handle_create(file_priv, object, handle);
3718}
3719
3720static const struct drm_framebuffer_funcs intel_fb_funcs = {
3721 .destroy = intel_user_framebuffer_destroy,
3722 .create_handle = intel_user_framebuffer_create_handle,
3723};
3724
3725int intel_framebuffer_create(struct drm_device *dev,
3726 struct drm_mode_fb_cmd *mode_cmd,
3727 struct drm_framebuffer **fb,
3728 struct drm_gem_object *obj)
3729{
3730 struct intel_framebuffer *intel_fb;
3731 int ret;
3732
3733 intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
3734 if (!intel_fb)
3735 return -ENOMEM;
3736
3737 ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
3738 if (ret) {
3739 DRM_ERROR("framebuffer init failed %d\n", ret);
3740 return ret;
3741 }
3742
3743 drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
3744
3745 intel_fb->obj = obj;
3746
3747 *fb = &intel_fb->base;
3748
3749 return 0;
3750}
3751
3752
3753static struct drm_framebuffer *
3754intel_user_framebuffer_create(struct drm_device *dev,
3755 struct drm_file *filp,
3756 struct drm_mode_fb_cmd *mode_cmd)
3757{
3758 struct drm_gem_object *obj;
3759 struct drm_framebuffer *fb;
3760 int ret;
3761
3762 obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle);
3763 if (!obj)
3764 return NULL;
3765
3766 ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj);
3767 if (ret) {
Jesse Barnes496818f2009-02-11 13:28:14 -08003768 mutex_lock(&dev->struct_mutex);
Jesse Barnes79e53942008-11-07 14:24:08 -08003769 drm_gem_object_unreference(obj);
Jesse Barnes496818f2009-02-11 13:28:14 -08003770 mutex_unlock(&dev->struct_mutex);
Jesse Barnes79e53942008-11-07 14:24:08 -08003771 return NULL;
3772 }
3773
3774 return fb;
3775}
3776
Jesse Barnes79e53942008-11-07 14:24:08 -08003777static const struct drm_mode_config_funcs intel_mode_funcs = {
Jesse Barnes79e53942008-11-07 14:24:08 -08003778 .fb_create = intel_user_framebuffer_create,
3779 .fb_changed = intelfb_probe,
3780};
3781
Jesse Barnes652c3932009-08-17 13:31:43 -07003782void intel_init_clock_gating(struct drm_device *dev)
3783{
3784 struct drm_i915_private *dev_priv = dev->dev_private;
3785
3786 /*
3787 * Disable clock gating reported to work incorrectly according to the
3788 * specs, but enable as much else as we can.
3789 */
3790 if (IS_G4X(dev)) {
3791 uint32_t dspclk_gate;
3792 I915_WRITE(RENCLK_GATE_D1, 0);
3793 I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE |
3794 GS_UNIT_CLOCK_GATE_DISABLE |
3795 CL_UNIT_CLOCK_GATE_DISABLE);
3796 I915_WRITE(RAMCLK_GATE_D, 0);
3797 dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE |
3798 OVRUNIT_CLOCK_GATE_DISABLE |
3799 OVCUNIT_CLOCK_GATE_DISABLE;
3800 if (IS_GM45(dev))
3801 dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
3802 I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
3803 } else if (IS_I965GM(dev)) {
3804 I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE);
3805 I915_WRITE(RENCLK_GATE_D2, 0);
3806 I915_WRITE(DSPCLK_GATE_D, 0);
3807 I915_WRITE(RAMCLK_GATE_D, 0);
3808 I915_WRITE16(DEUC, 0);
3809 } else if (IS_I965G(dev)) {
3810 I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE |
3811 I965_RCC_CLOCK_GATE_DISABLE |
3812 I965_RCPB_CLOCK_GATE_DISABLE |
3813 I965_ISC_CLOCK_GATE_DISABLE |
3814 I965_FBC_CLOCK_GATE_DISABLE);
3815 I915_WRITE(RENCLK_GATE_D2, 0);
3816 } else if (IS_I9XX(dev)) {
3817 u32 dstate = I915_READ(D_STATE);
3818
3819 dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING |
3820 DSTATE_DOT_CLOCK_GATING;
3821 I915_WRITE(D_STATE, dstate);
3822 } else if (IS_I855(dev) || IS_I865G(dev)) {
3823 I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
3824 } else if (IS_I830(dev)) {
3825 I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
3826 }
3827}
3828
Jesse Barnes79e53942008-11-07 14:24:08 -08003829void intel_modeset_init(struct drm_device *dev)
3830{
Jesse Barnes652c3932009-08-17 13:31:43 -07003831 struct drm_i915_private *dev_priv = dev->dev_private;
Jesse Barnes79e53942008-11-07 14:24:08 -08003832 int num_pipe;
3833 int i;
3834
3835 drm_mode_config_init(dev);
3836
3837 dev->mode_config.min_width = 0;
3838 dev->mode_config.min_height = 0;
3839
3840 dev->mode_config.funcs = (void *)&intel_mode_funcs;
3841
3842 if (IS_I965G(dev)) {
3843 dev->mode_config.max_width = 8192;
3844 dev->mode_config.max_height = 8192;
Keith Packard5e4d6fa2009-07-12 23:53:17 -07003845 } else if (IS_I9XX(dev)) {
3846 dev->mode_config.max_width = 4096;
3847 dev->mode_config.max_height = 4096;
Jesse Barnes79e53942008-11-07 14:24:08 -08003848 } else {
3849 dev->mode_config.max_width = 2048;
3850 dev->mode_config.max_height = 2048;
3851 }
3852
3853 /* set memory base */
3854 if (IS_I9XX(dev))
3855 dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2);
3856 else
3857 dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0);
3858
3859 if (IS_MOBILE(dev) || IS_I9XX(dev))
3860 num_pipe = 2;
3861 else
3862 num_pipe = 1;
3863 DRM_DEBUG("%d display pipe%s available.\n",
3864 num_pipe, num_pipe > 1 ? "s" : "");
3865
Jesse Barnes652c3932009-08-17 13:31:43 -07003866 if (IS_I85X(dev))
3867 pci_read_config_word(dev->pdev, HPLLCC, &dev_priv->orig_clock);
3868 else if (IS_I9XX(dev) || IS_G4X(dev))
3869 pci_read_config_word(dev->pdev, GCFGC, &dev_priv->orig_clock);
3870
Jesse Barnes79e53942008-11-07 14:24:08 -08003871 for (i = 0; i < num_pipe; i++) {
3872 intel_crtc_init(dev, i);
3873 }
3874
3875 intel_setup_outputs(dev);
Jesse Barnes652c3932009-08-17 13:31:43 -07003876
3877 intel_init_clock_gating(dev);
3878
3879 INIT_WORK(&dev_priv->idle_work, intel_idle_update);
3880 setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
3881 (unsigned long)dev);
Jesse Barnes79e53942008-11-07 14:24:08 -08003882}
3883
3884void intel_modeset_cleanup(struct drm_device *dev)
3885{
Jesse Barnes652c3932009-08-17 13:31:43 -07003886 struct drm_i915_private *dev_priv = dev->dev_private;
3887 struct drm_crtc *crtc;
3888 struct intel_crtc *intel_crtc;
3889
3890 mutex_lock(&dev->struct_mutex);
3891
3892 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
3893 /* Skip inactive CRTCs */
3894 if (!crtc->fb)
3895 continue;
3896
3897 intel_crtc = to_intel_crtc(crtc);
3898 intel_increase_pllclock(crtc, false);
3899 del_timer_sync(&intel_crtc->idle_timer);
3900 }
3901
3902 intel_increase_renderclock(dev, false);
3903 del_timer_sync(&dev_priv->idle_timer);
3904
3905 mutex_unlock(&dev->struct_mutex);
3906
Jesse Barnes79e53942008-11-07 14:24:08 -08003907 drm_mode_config_cleanup(dev);
3908}
3909
3910
3911/* current intel driver doesn't take advantage of encoders
3912 always give back the encoder for the connector
3913*/
3914struct drm_encoder *intel_best_encoder(struct drm_connector *connector)
3915{
3916 struct intel_output *intel_output = to_intel_output(connector);
3917
3918 return &intel_output->enc;
3919}
Dave Airlie28d52042009-09-21 14:33:58 +10003920
3921/*
3922 * set vga decode state - true == enable VGA decode
3923 */
3924int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
3925{
3926 struct drm_i915_private *dev_priv = dev->dev_private;
3927 u16 gmch_ctrl;
3928
3929 pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl);
3930 if (state)
3931 gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
3932 else
3933 gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
3934 pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
3935 return 0;
3936}