1/* -*- c-basic-offset: 4 -*- */
2/*
3 * Copyright � 2006 Intel Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Authors:
25 *    Eric Anholt <eric@anholt.net>
26 *
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <unistd.h>
34#include <string.h>
35#include <assert.h>
36#include <stdlib.h>
37#include <math.h>
38#include <sys/ioctl.h>
39
40#include "xf86.h"
41#include "i830.h"
42#include "i830_bios.h"
43#include "i830_display.h"
44#include "i830_debug.h"
45#include "xf86Modes.h"
46
47typedef struct {
48    /* given values */
49    int n;
50    int m1, m2;
51    int p1, p2;
52    /* derived values */
53    int	dot;
54    int	vco;
55    int	m;
56    int	p;
57} intel_clock_t;
58
59typedef struct {
60    int	min, max;
61} intel_range_t;
62
63typedef struct {
64    int	dot_limit;
65    int	p2_slow, p2_fast;
66} intel_p2_t;
67
68#define INTEL_P2_NUM		      2
69
70typedef struct intel_limit intel_limit_t;
71struct intel_limit {
72    intel_range_t   dot, vco, n, m, m1, m2, p, p1;
73    intel_p2_t	    p2;
74    Bool (* find_pll)(const intel_limit_t *, xf86CrtcPtr,
75                      int, int, intel_clock_t *);
76};
77
78#define I8XX_DOT_MIN		  25000
79#define I8XX_DOT_MAX		 350000
80#define I8XX_VCO_MIN		 930000
81#define I8XX_VCO_MAX		1400000
82#define I8XX_N_MIN		      3
83#define I8XX_N_MAX		     16
84#define I8XX_M_MIN		     96
85#define I8XX_M_MAX		    140
86#define I8XX_M1_MIN		     18
87#define I8XX_M1_MAX		     26
88#define I8XX_M2_MIN		      6
89#define I8XX_M2_MAX		     16
90#define I8XX_P_MIN		      4
91#define I8XX_P_MAX		    128
92#define I8XX_P1_MIN		      2
93#define I8XX_P1_MAX		     33
94#define I8XX_P1_LVDS_MIN	      1
95#define I8XX_P1_LVDS_MAX	      6
96#define I8XX_P2_SLOW		      4
97#define I8XX_P2_FAST		      2
98#define I8XX_P2_LVDS_SLOW	      14
99#define I8XX_P2_LVDS_FAST	      7
100#define I8XX_P2_SLOW_LIMIT	 165000
101
102#define I9XX_DOT_MIN		  20000
103#define I9XX_DOT_MAX		 400000
104#define I9XX_VCO_MIN		1400000
105#define I9XX_VCO_MAX		2800000
106#define IGD_VCO_MIN		1700000
107#define IGD_VCO_MAX		3500000
108
109/* Haven't found any reason to go this fast, but newer chips support it */
110#define I96X_VCO_MAX		3200000
111
112/*
113 * These values are taken from the broadwater/crestline PLL spreadsheet.
114 * All of the defines here are for the programmed register value, not
115 * the 'counter' value (e.g. Ncounter = Nregister + 2)
116 */
117#define I9XX_N_MIN		      1
118#define I9XX_N_MAX		      6
119/* IGD's Ncounter is a ring counter */
120#define IGD_N_MIN		      3
121#define IGD_N_MAX		      6
122#define I9XX_M_MIN		     70
123#define I9XX_M_MAX		    120
124#define IGD_M_MIN		      2
125#define IGD_M_MAX		    256
126
127/* these two come from the calm1 macro */
128#define I9XX_M1_MIN		     10
129#define I9XX_M1_MAX		     22
130#define I9XX_M2_MIN		      5
131#define I9XX_M2_MAX		      9
132/* IGD M1 is reserved, and must be 0 */
133#define IGD_M1_MIN		      0
134#define IGD_M1_MAX		      0
135#define IGD_M2_MIN		      0
136#define IGD_M2_MAX		      254
137
138#define I9XX_P_SDVO_DAC_MIN	      5
139#define I9XX_P_SDVO_DAC_MAX	     80
140#define I9XX_P_LVDS_MIN		      7
141#define I9XX_P_LVDS_MAX		     98
142#define IGD_P_LVDS_MIN		      7
143#define IGD_P_LVDS_MAX		     112
144#define I9XX_P1_MIN		      1
145#define I9XX_P1_MAX		      8
146#define I9XX_P2_SDVO_DAC_SLOW		     10
147#define I9XX_P2_SDVO_DAC_FAST		      5
148#define I9XX_P2_SDVO_DAC_SLOW_LIMIT	 200000
149#define I9XX_P2_LVDS_SLOW		     14
150#define I9XX_P2_LVDS_FAST		      7
151#define I9XX_P2_LVDS_SLOW_LIMIT		 112000
152
153#define INTEL_LIMIT_I8XX_DVO_DAC    0
154#define INTEL_LIMIT_I8XX_LVDS	    1
155#define INTEL_LIMIT_I9XX_SDVO_DAC   2
156#define INTEL_LIMIT_I9XX_LVDS	    3
157#define INTEL_LIMIT_IGD_SDVO_DAC    4
158#define INTEL_LIMIT_IGD_LVDS	    5
159#define INTEL_LIMIT_G4X_SDVO	    6
160#define INTEL_LIMIT_G4X_HDMI_DAC    7
161#define INTEL_LIMIT_G4X_SINGLE_LVDS 8
162#define INTEL_LIMIT_G4X_DUAL_LVDS   9
163
164/*The parameter is for SDVO on G4x platform*/
165#define G4X_VCO_MIN                1750000
166#define G4X_VCO_MAX                3500000
167#define G4X_DOT_SDVO_MIN           25000
168#define G4X_DOT_SDVO_MAX           270000
169#define G4X_N_SDVO_MIN             1
170#define G4X_N_SDVO_MAX             4
171#define G4X_M_SDVO_MIN             104
172#define G4X_M_SDVO_MAX             138
173#define G4X_M1_SDVO_MIN            17
174#define G4X_M1_SDVO_MAX            23
175#define G4X_M2_SDVO_MIN            5
176#define G4X_M2_SDVO_MAX            11
177#define G4X_P_SDVO_MIN             10
178#define G4X_P_SDVO_MAX             30
179#define G4X_P1_SDVO_MIN            1
180#define G4X_P1_SDVO_MAX            3
181#define G4X_P2_SDVO_SLOW           10
182#define G4X_P2_SDVO_FAST           10
183#define G4X_P2_SDVO_LIMIT          270000
184
185/*The parameter is for HDMI_DAC on G4x platform*/
186#define G4X_DOT_HDMI_DAC_MIN           22000
187#define G4X_DOT_HDMI_DAC_MAX           400000
188#define G4X_N_HDMI_DAC_MIN             1
189#define G4X_N_HDMI_DAC_MAX             4
190#define G4X_M_HDMI_DAC_MIN             104
191#define G4X_M_HDMI_DAC_MAX             138
192#define G4X_M1_HDMI_DAC_MIN            16
193#define G4X_M1_HDMI_DAC_MAX            23
194#define G4X_M2_HDMI_DAC_MIN            5
195#define G4X_M2_HDMI_DAC_MAX            11
196#define G4X_P_HDMI_DAC_MIN             5
197#define G4X_P_HDMI_DAC_MAX             80
198#define G4X_P1_HDMI_DAC_MIN            1
199#define G4X_P1_HDMI_DAC_MAX            8
200#define G4X_P2_HDMI_DAC_SLOW           10
201#define G4X_P2_HDMI_DAC_FAST           5
202#define G4X_P2_HDMI_DAC_LIMIT          165000
203
204/*The parameter is for SINGLE_LVDS on G4x platform*/
205#define G4X_DOT_SINGLE_LVDS_MIN           20000
206#define G4X_DOT_SINGLE_LVDS_MAX           115000
207#define G4X_N_SINGLE_LVDS_MIN             1
208#define G4X_N_SINGLE_LVDS_MAX             3
209#define G4X_M_SINGLE_LVDS_MIN             104
210#define G4X_M_SINGLE_LVDS_MAX             138
211#define G4X_M1_SINGLE_LVDS_MIN            17
212#define G4X_M1_SINGLE_LVDS_MAX            23
213#define G4X_M2_SINGLE_LVDS_MIN            5
214#define G4X_M2_SINGLE_LVDS_MAX            11
215#define G4X_P_SINGLE_LVDS_MIN             28
216#define G4X_P_SINGLE_LVDS_MAX             112
217#define G4X_P1_SINGLE_LVDS_MIN            2
218#define G4X_P1_SINGLE_LVDS_MAX            8
219#define G4X_P2_SINGLE_LVDS_SLOW           14
220#define G4X_P2_SINGLE_LVDS_FAST           14
221#define G4X_P2_SINGLE_LVDS_LIMIT          0
222
223/*The parameter is for DUAL_LVDS on G4x platform*/
224#define G4X_DOT_DUAL_LVDS_MIN           80000
225#define G4X_DOT_DUAL_LVDS_MAX           224000
226#define G4X_N_DUAL_LVDS_MIN             1
227#define G4X_N_DUAL_LVDS_MAX             3
228#define G4X_M_DUAL_LVDS_MIN             104
229#define G4X_M_DUAL_LVDS_MAX             138
230#define G4X_M1_DUAL_LVDS_MIN            17
231#define G4X_M1_DUAL_LVDS_MAX            23
232#define G4X_M2_DUAL_LVDS_MIN            5
233#define G4X_M2_DUAL_LVDS_MAX            11
234#define G4X_P_DUAL_LVDS_MIN             14
235#define G4X_P_DUAL_LVDS_MAX             42
236#define G4X_P1_DUAL_LVDS_MIN            2
237#define G4X_P1_DUAL_LVDS_MAX            6
238#define G4X_P2_DUAL_LVDS_SLOW           7
239#define G4X_P2_DUAL_LVDS_FAST           7
240#define G4X_P2_DUAL_LVDS_LIMIT          0
241
242static Bool
243intel_find_pll_i8xx_and_i9xx(const intel_limit_t *, xf86CrtcPtr,
244                             int, int, intel_clock_t *);
245static Bool
246intel_find_pll_g4x(const intel_limit_t *, xf86CrtcPtr,
247                   int, int, intel_clock_t *);
248static void
249i830_crtc_load_lut(xf86CrtcPtr crtc);
250
251static const intel_limit_t intel_limits[] = {
252    { /* INTEL_LIMIT_I8XX_DVO_DAC */
253        .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
254        .vco = { .min = I8XX_VCO_MIN,		.max = I8XX_VCO_MAX },
255        .n   = { .min = I8XX_N_MIN,		.max = I8XX_N_MAX },
256        .m   = { .min = I8XX_M_MIN,		.max = I8XX_M_MAX },
257        .m1  = { .min = I8XX_M1_MIN,		.max = I8XX_M1_MAX },
258        .m2  = { .min = I8XX_M2_MIN,		.max = I8XX_M2_MAX },
259        .p   = { .min = I8XX_P_MIN,		.max = I8XX_P_MAX },
260        .p1  = { .min = I8XX_P1_MIN,		.max = I8XX_P1_MAX },
261	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
262		 .p2_slow = I8XX_P2_SLOW,	.p2_fast = I8XX_P2_FAST },
263        .find_pll = intel_find_pll_i8xx_and_i9xx,
264    },
265    { /* INTEL_LIMIT_I8XX_LVDS */
266        .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
267        .vco = { .min = I8XX_VCO_MIN,		.max = I8XX_VCO_MAX },
268        .n   = { .min = I8XX_N_MIN,		.max = I8XX_N_MAX },
269        .m   = { .min = I8XX_M_MIN,		.max = I8XX_M_MAX },
270        .m1  = { .min = I8XX_M1_MIN,		.max = I8XX_M1_MAX },
271        .m2  = { .min = I8XX_M2_MIN,		.max = I8XX_M2_MAX },
272        .p   = { .min = I8XX_P_MIN,		.max = I8XX_P_MAX },
273        .p1  = { .min = I8XX_P1_LVDS_MIN,	.max = I8XX_P1_LVDS_MAX },
274	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
275		 .p2_slow = I8XX_P2_LVDS_SLOW,	.p2_fast = I8XX_P2_LVDS_FAST },
276        .find_pll = intel_find_pll_i8xx_and_i9xx,
277    },
278    { /* INTEL_LIMIT_I9XX_SDVO_DAC */
279        .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
280        .vco = { .min = I9XX_VCO_MIN,		.max = I9XX_VCO_MAX },
281        .n   = { .min = I9XX_N_MIN,		.max = I9XX_N_MAX },
282        .m   = { .min = I9XX_M_MIN,		.max = I9XX_M_MAX },
283        .m1  = { .min = I9XX_M1_MIN,		.max = I9XX_M1_MAX },
284        .m2  = { .min = I9XX_M2_MIN,		.max = I9XX_M2_MAX },
285        .p   = { .min = I9XX_P_SDVO_DAC_MIN,	.max = I9XX_P_SDVO_DAC_MAX },
286        .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
287	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
288		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
289        .find_pll = intel_find_pll_i8xx_and_i9xx,
290    },
291    { /* INTEL_LIMIT_I9XX_LVDS */
292        .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
293        .vco = { .min = I9XX_VCO_MIN,		.max = I9XX_VCO_MAX },
294        .n   = { .min = I9XX_N_MIN,		.max = I9XX_N_MAX },
295        .m   = { .min = I9XX_M_MIN,		.max = I9XX_M_MAX },
296        .m1  = { .min = I9XX_M1_MIN,		.max = I9XX_M1_MAX },
297        .m2  = { .min = I9XX_M2_MIN,		.max = I9XX_M2_MAX },
298        .p   = { .min = I9XX_P_LVDS_MIN,	.max = I9XX_P_LVDS_MAX },
299        .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
300	/* The single-channel range is 25-112Mhz, and dual-channel
301	 * is 80-224Mhz.  Prefer single channel as much as possible.
302	 */
303	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
304		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_FAST },
305        .find_pll = intel_find_pll_i8xx_and_i9xx,
306    },
307    { /* INTEL_LIMIT_IGD_SDVO */
308        .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX},
309        .vco = { .min = IGD_VCO_MIN,		.max = IGD_VCO_MAX },
310        .n   = { .min = IGD_N_MIN,		.max = IGD_N_MAX },
311        .m   = { .min = IGD_M_MIN,		.max = IGD_M_MAX },
312        .m1  = { .min = IGD_M1_MIN,		.max = IGD_M1_MAX },
313        .m2  = { .min = IGD_M2_MIN,		.max = IGD_M2_MAX },
314        .p   = { .min = I9XX_P_SDVO_DAC_MIN,    .max = I9XX_P_SDVO_DAC_MAX },
315        .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
316	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
317		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
318        .find_pll = intel_find_pll_i8xx_and_i9xx,
319    },
320    { /* INTEL_LIMIT_IGD_LVDS */
321        .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
322        .vco = { .min = IGD_VCO_MIN,		.max = IGD_VCO_MAX },
323        .n   = { .min = IGD_N_MIN,		.max = IGD_N_MAX },
324        .m   = { .min = IGD_M_MIN,		.max = IGD_M_MAX },
325        .m1  = { .min = IGD_M1_MIN,		.max = IGD_M1_MAX },
326        .m2  = { .min = IGD_M2_MIN,		.max = IGD_M2_MAX },
327        .p   = { .min = IGD_P_LVDS_MIN,	.max = IGD_P_LVDS_MAX },
328        .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
329	/* IGD only supports single-channel mode. */
330	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
331		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_SLOW },
332        .find_pll = intel_find_pll_i8xx_and_i9xx,
333    },
334    /* below parameter and function is for G4X Chipset Family*/
335    {   /* INTEL_LIMIT_G4X_SDVO */
336        .dot = { .min = G4X_DOT_SDVO_MIN,       .max = G4X_DOT_SDVO_MAX },
337        .vco = { .min = G4X_VCO_MIN,            .max = G4X_VCO_MAX},
338        .n   = { .min = G4X_N_SDVO_MIN,         .max = G4X_N_SDVO_MAX },
339        .m   = { .min = G4X_M_SDVO_MIN,         .max = G4X_M_SDVO_MAX },
340        .m1  = { .min = G4X_M1_SDVO_MIN,        .max = G4X_M1_SDVO_MAX },
341        .m2  = { .min = G4X_M2_SDVO_MIN,        .max = G4X_M2_SDVO_MAX },
342        .p   = { .min = G4X_P_SDVO_MIN,         .max = G4X_P_SDVO_MAX },
343        .p1  = { .min = G4X_P1_SDVO_MIN,        .max = G4X_P1_SDVO_MAX},
344        .p2  = { .dot_limit = G4X_P2_SDVO_LIMIT,
345                 .p2_slow = G4X_P2_SDVO_SLOW,
346                 .p2_fast = G4X_P2_SDVO_FAST },
347        .find_pll = intel_find_pll_g4x,
348    },
349    {   /* INTEL_LIMIT_G4X_HDMI_DAC */
350        .dot = { .min = G4X_DOT_HDMI_DAC_MIN,	.max = G4X_DOT_HDMI_DAC_MAX },
351        .vco = { .min = G4X_VCO_MIN,	        .max = G4X_VCO_MAX},
352        .n   = { .min = G4X_N_HDMI_DAC_MIN,	.max = G4X_N_HDMI_DAC_MAX },
353        .m   = { .min = G4X_M_HDMI_DAC_MIN,	.max = G4X_M_HDMI_DAC_MAX },
354        .m1  = { .min = G4X_M1_HDMI_DAC_MIN,	.max = G4X_M1_HDMI_DAC_MAX },
355        .m2  = { .min = G4X_M2_HDMI_DAC_MIN,	.max = G4X_M2_HDMI_DAC_MAX },
356        .p   = { .min = G4X_P_HDMI_DAC_MIN,	.max = G4X_P_HDMI_DAC_MAX },
357        .p1  = { .min = G4X_P1_HDMI_DAC_MIN,	.max = G4X_P1_HDMI_DAC_MAX},
358        .p2  = { .dot_limit = G4X_P2_HDMI_DAC_LIMIT,
359                 .p2_slow = G4X_P2_HDMI_DAC_SLOW,
360                 .p2_fast = G4X_P2_HDMI_DAC_FAST },
361        .find_pll = intel_find_pll_g4x,
362    },
363    {   /* INTEL_LIMIT_G4X_SINGLE_LVDS */
364        .dot = { .min = G4X_DOT_SINGLE_LVDS_MIN,
365                 .max = G4X_DOT_SINGLE_LVDS_MAX },
366        .vco = { .min = G4X_VCO_MIN,
367                 .max = G4X_VCO_MAX },
368        .n   = { .min = G4X_N_SINGLE_LVDS_MIN,
369                 .max = G4X_N_SINGLE_LVDS_MAX },
370        .m   = { .min = G4X_M_SINGLE_LVDS_MIN,
371                 .max = G4X_M_SINGLE_LVDS_MAX },
372        .m1  = { .min = G4X_M1_SINGLE_LVDS_MIN,
373                 .max = G4X_M1_SINGLE_LVDS_MAX },
374        .m2  = { .min = G4X_M2_SINGLE_LVDS_MIN,
375                 .max = G4X_M2_SINGLE_LVDS_MAX },
376        .p   = { .min = G4X_P_SINGLE_LVDS_MIN,
377                 .max = G4X_P_SINGLE_LVDS_MAX },
378        .p1  = { .min = G4X_P1_SINGLE_LVDS_MIN,
379                 .max = G4X_P1_SINGLE_LVDS_MAX },
380        .p2  = { .dot_limit = G4X_P2_SINGLE_LVDS_LIMIT,
381                 .p2_slow = G4X_P2_SINGLE_LVDS_SLOW,
382                 .p2_fast = G4X_P2_SINGLE_LVDS_FAST },
383        .find_pll = intel_find_pll_g4x,
384    },
385    {   /* INTEL_LIMIT_G4X_DUAL_LVDS */
386        .dot = { .min = G4X_DOT_DUAL_LVDS_MIN,
387                 .max = G4X_DOT_DUAL_LVDS_MAX },
388        .vco = { .min = G4X_VCO_MIN,
389                 .max = G4X_VCO_MAX},
390        .n   = { .min = G4X_N_DUAL_LVDS_MIN,
391                 .max = G4X_N_DUAL_LVDS_MAX },
392        .m   = { .min = G4X_M_DUAL_LVDS_MIN,
393                 .max = G4X_M_DUAL_LVDS_MAX },
394        .m1  = { .min = G4X_M1_DUAL_LVDS_MIN,
395                 .max = G4X_M1_DUAL_LVDS_MAX },
396        .m2  = { .min = G4X_M2_DUAL_LVDS_MIN,
397                 .max = G4X_M2_DUAL_LVDS_MAX },
398        .p   = { .min = G4X_P_DUAL_LVDS_MIN,
399                 .max = G4X_P_DUAL_LVDS_MAX },
400        .p1  = { .min = G4X_P1_DUAL_LVDS_MIN,
401                 .max = G4X_P1_DUAL_LVDS_MAX},
402        .p2  = { .dot_limit = G4X_P2_DUAL_LVDS_LIMIT,
403                 .p2_slow = G4X_P2_DUAL_LVDS_SLOW,
404                 .p2_fast = G4X_P2_DUAL_LVDS_FAST },
405        .find_pll = intel_find_pll_g4x,
406    },
407};
408
409static const intel_limit_t *intel_limit_g4x (xf86CrtcPtr crtc)
410{
411    ScrnInfoPtr	pScrn = crtc->scrn;
412    I830Ptr	pI830 = I830PTR(pScrn);
413    const intel_limit_t *limit;
414
415    if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) {
416        if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) {
417            /* LVDS with dual channel */
418            limit = &intel_limits[INTEL_LIMIT_G4X_DUAL_LVDS];
419        } else /* LVDS with single channel */
420            limit = &intel_limits[INTEL_LIMIT_G4X_SINGLE_LVDS];
421    } else if (i830PipeHasType (crtc, I830_OUTPUT_HDMI) ||
422               i830PipeHasType (crtc, I830_OUTPUT_ANALOG)) {
423        limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC];
424    } else if (i830PipeHasType (crtc, I830_OUTPUT_SDVO)) {
425        limit = &intel_limits[INTEL_LIMIT_G4X_SDVO];
426    } else /* The option is for other outputs */
427        limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
428    return limit;
429}
430
431static const intel_limit_t *intel_limit (xf86CrtcPtr crtc)
432{
433    ScrnInfoPtr	pScrn = crtc->scrn;
434    I830Ptr	pI830 = I830PTR(pScrn);
435    const intel_limit_t *limit;
436
437    if (IS_G4X(pI830)) {
438        limit = intel_limit_g4x(crtc);
439    } else if (IS_I9XX(pI830) && !IS_IGD(pI830)) {
440	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
441	    limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
442	else
443	    limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
444    } else if (IS_IGD(pI830)) {
445	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
446	    limit = &intel_limits[INTEL_LIMIT_IGD_LVDS];
447	else
448	    limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC];
449    } else {
450	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
451	    limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS];
452	else
453	    limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC];
454    }
455
456    return limit;
457}
458
459/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
460
461static void i8xx_clock(int refclk, intel_clock_t *clock)
462{
463    clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
464    clock->p = clock->p1 * clock->p2;
465    clock->vco = refclk * clock->m / (clock->n + 2);
466    clock->dot = clock->vco / clock->p;
467}
468
469/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
470
471static void i9xx_clock(int refclk, intel_clock_t *clock)
472{
473    clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
474    clock->p = clock->p1 * clock->p2;
475    clock->vco = refclk * clock->m / (clock->n + 2);
476    clock->dot = clock->vco / clock->p;
477}
478
479/* m1 is reserved as 0 in IGD, n is a ring counter */
480static void igd_clock(int refclk, intel_clock_t *clock)
481{
482    clock->m = clock->m2 + 2;
483    clock->p = clock->p1 * clock->p2;
484    clock->vco = refclk * clock->m / clock->n;
485    clock->dot = clock->vco / clock->p;
486}
487
488static void intel_clock(I830Ptr pI830, int refclk, intel_clock_t *clock)
489{
490    if (IS_I9XX(pI830)) {
491	if (IS_IGD(pI830))
492	    igd_clock(refclk, clock);
493	else
494	    i9xx_clock (refclk, clock);
495    } else
496	i8xx_clock (refclk, clock);
497}
498
499static void
500i830PrintPll(ScrnInfoPtr pScrn, char *prefix, intel_clock_t *clock)
501{
502    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
503	       "%s: dotclock %d vco %d ((m %d, m1 %d, m2 %d), n %d, "
504	       "(p %d, p1 %d, p2 %d))\n",
505	       prefix, clock->dot, clock->vco,
506	       clock->m, clock->m1, clock->m2,
507	       clock->n,
508	       clock->p, clock->p1, clock->p2);
509}
510
511/**
512 * Returns whether any output on the specified pipe is of the specified type
513 */
514Bool
515i830PipeHasType (xf86CrtcPtr crtc, int type)
516{
517    ScrnInfoPtr	pScrn = crtc->scrn;
518    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
519    int		i;
520
521    for (i = 0; i < xf86_config->num_output; i++)
522    {
523	xf86OutputPtr  output = xf86_config->output[i];
524	if (output->crtc == crtc)
525	{
526	    I830OutputPrivatePtr    intel_output = output->driver_private;
527	    if (intel_output->type == type)
528		return TRUE;
529	}
530    }
531    return FALSE;
532}
533
534#define i830PllInvalid(s)   { /* ErrorF (s) */; return FALSE; }
535/**
536 * Returns whether the given set of divisors are valid for a given refclk with
537 * the given outputs.
538 */
539
540static Bool
541i830PllIsValid(xf86CrtcPtr crtc, intel_clock_t *clock)
542{
543    const intel_limit_t *limit = intel_limit (crtc);
544    ScrnInfoPtr pScrn = crtc->scrn;
545    I830Ptr pI830 = I830PTR(pScrn);
546
547    if (clock->p1  < limit->p1.min  || limit->p1.max  < clock->p1)
548	i830PllInvalid ("p1 out of range\n");
549    if (clock->p   < limit->p.min   || limit->p.max   < clock->p)
550	i830PllInvalid ("p out of range\n");
551    if (clock->m2  < limit->m2.min  || limit->m2.max  < clock->m2)
552	i830PllInvalid ("m2 out of range\n");
553    if (clock->m1  < limit->m1.min  || limit->m1.max  < clock->m1)
554	i830PllInvalid ("m1 out of range\n");
555    if (clock->m1 <= clock->m2 && !IS_IGD(pI830))
556	i830PllInvalid ("m1 <= m2\n");
557    if (clock->m   < limit->m.min   || limit->m.max   < clock->m)
558	i830PllInvalid ("m out of range\n");
559    if (clock->n   < limit->n.min   || limit->n.max   < clock->n)
560	i830PllInvalid ("n out of range\n");
561    if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
562	i830PllInvalid ("vco out of range\n");
563    /* XXX: We may need to be checking "Dot clock" depending on the multiplier,
564     * output, etc., rather than just a single range.
565     */
566    if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
567	i830PllInvalid ("dot out of range\n");
568
569    return TRUE;
570}
571
572static Bool
573intel_find_pll_i8xx_and_i9xx(const intel_limit_t * limit, xf86CrtcPtr crtc,
574	                     int target, int refclk, intel_clock_t *best_clock)
575{
576    ScrnInfoPtr pScrn = crtc->scrn;
577    I830Ptr pI830 = I830PTR(pScrn);
578    intel_clock_t clock;
579    int err = target;
580
581    if (i830PipeHasType(crtc, I830_OUTPUT_LVDS))
582    {
583	/* For LVDS, if the panel is on, just rely on its current settings for
584	 * dual-channel.  We haven't figured out how to reliably set up
585	 * different single/dual channel state, if we even can.
586	 */
587	if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
588	    clock.p2 = limit->p2.p2_fast;
589	else
590	    clock.p2 = limit->p2.p2_slow;
591    } else {
592	if (target < limit->p2.dot_limit)
593	    clock.p2 = limit->p2.p2_slow;
594	else
595	    clock.p2 = limit->p2.p2_fast;
596    }
597
598    memset (best_clock, 0, sizeof (*best_clock));
599
600    for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++)
601    {
602	for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++)
603	{
604	    /* m1 is always 0 in IGD */
605	    if (clock.m2 >= clock.m1 && !IS_IGD(pI830))
606		break;
607	    for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++)
608	    {
609		for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; clock.p1++)
610		{
611		    int this_err;
612
613		    intel_clock (pI830, refclk, &clock);
614
615		    if (!i830PllIsValid(crtc, &clock))
616			continue;
617
618		    this_err = abs(clock.dot - target);
619		    if (this_err < err) {
620			*best_clock = clock;
621			err = this_err;
622		    }
623		}
624	    }
625	}
626    }
627    return (err != target);
628}
629
630static Bool
631intel_find_pll_g4x(const intel_limit_t * limit, xf86CrtcPtr crtc,
632                   int target, int refclk, intel_clock_t *best_clock)
633{
634    ScrnInfoPtr pScrn = crtc->scrn;
635    I830Ptr pI830 = I830PTR(pScrn);
636    intel_clock_t clock;
637    int  max_n;
638    Bool found = FALSE;
639    int err_most = target * 0.0048;
640
641    if (i830PipeHasType(crtc, I830_OUTPUT_LVDS))
642    {
643        /* For LVDS, if the panel is on, just rely on its current settings for
644         * dual-channel.  We haven't figured out how to reliably set up
645         * different single/dual channel state, if we even can.
646         */
647        if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
648            clock.p2 = limit->p2.p2_fast;
649        else
650            clock.p2 = limit->p2.p2_slow;
651    } else {
652        if (target < limit->p2.dot_limit)
653            clock.p2 = limit->p2.p2_slow;
654        else
655            clock.p2 = limit->p2.p2_fast;
656    }
657
658    max_n = limit->n.max;
659    /* based on hardware requirement prefer smaller n to precision */
660    for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
661        /* based on hardware requirement prefere larger m1,m2, p1*/
662        for (clock.m1 = limit->m1.max;
663            clock.m1 >= limit->m1.min; clock.m1--) {
664            for (clock.m2 = limit->m2.max;
665                clock.m2 >= limit->m2.min; clock.m2--) {
666                for (clock.p1 = limit->p1.max;
667                    clock.p1 >= limit->p1.min; clock.p1--) {
668                    int this_err;
669
670                    intel_clock (pI830, refclk, &clock);
671                    if (!i830PllIsValid(crtc, &clock))
672                        continue;
673                    this_err = abs(clock.dot - target) ;
674                    if (this_err < err_most) {
675                        memcpy(best_clock, &clock, sizeof(intel_clock_t));
676                        err_most = this_err;
677                        /* prefer smaller n to precision */
678                        max_n = clock.n;
679                        found = TRUE;
680                    }
681                }
682            }
683        }
684    }
685    return found;
686}
687
688void
689i830WaitForVblank(ScrnInfoPtr pScreen)
690{
691    /* Wait for 20ms, i.e. one cycle at 50hz. */
692    usleep(30000);
693}
694
695void
696i830PipeSetBase(xf86CrtcPtr crtc, int x, int y)
697{
698    ScrnInfoPtr pScrn = crtc->scrn;
699    I830Ptr pI830 = I830PTR(pScrn);
700    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
701    int plane = intel_crtc->plane;
702    unsigned long Start, Offset, Stride;
703    int dspbase = (plane == 0 ? DSPABASE : DSPBBASE);
704    int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF);
705    int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
706    int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
707
708    Offset = ((y * pScrn->displayWidth + x) * pI830->cpp);
709    Stride = pScrn->displayWidth * pI830->cpp;
710    if (pI830->front_buffer == NULL) {
711	/* During startup we may be called as part of monitor detection while
712	 * there is no memory allocation done, so just supply a dummy base
713	 * address.
714	 */
715	Start = 0;
716    } else if (crtc->rotatedData != NULL) {
717	/* offset is done by shadow painting code, not here */
718	Start = (char *)crtc->rotatedData - (char *)pI830->FbBase;
719	Offset = 0;
720	Stride = intel_crtc->rotate_mem->pitch;
721    } else {
722	Start = pI830->front_buffer->offset;
723    }
724
725    crtc->x = x;
726    crtc->y = y;
727
728    OUTREG(dspstride, Stride);
729    if (IS_I965G(pI830)) {
730        OUTREG(dspbase, Offset);
731	POSTING_READ(dspbase);
732        OUTREG(dspsurf, Start);
733	POSTING_READ(dspsurf);
734	OUTREG(dsptileoff, (y << 16) | x);
735    } else {
736	OUTREG(dspbase, Start + Offset);
737	POSTING_READ(dspbase);
738    }
739}
740
741/*
742 * Both crtc activation and video overlay enablement on pipe B
743 * will fail on i830 if pipe A is not running. This function
744 * makes sure pipe A is active for these cases
745 */
746
747int
748i830_crtc_pipe (xf86CrtcPtr crtc)
749{
750    if (crtc == NULL)
751	return 0;
752    return ((I830CrtcPrivatePtr) crtc->driver_private)->pipe;
753}
754
755static xf86CrtcPtr
756i830_crtc_for_pipe (ScrnInfoPtr scrn, int pipe)
757{
758    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
759    int			c;
760
761    for (c = 0; c < xf86_config->num_crtc; c++)
762    {
763	xf86CrtcPtr crtc = xf86_config->crtc[c];
764	if (i830_crtc_pipe (crtc) == pipe)
765	    return crtc;
766    }
767    return NULL;
768}
769
770Bool
771i830_pipe_a_require_activate (ScrnInfoPtr scrn)
772{
773    xf86CrtcPtr	crtc = i830_crtc_for_pipe (scrn, 0);
774    /* VESA 640x480x72Hz mode to set on the pipe */
775    static DisplayModeRec   mode = {
776	NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
777	31500,
778	640, 664, 704, 832, 0,
779	480, 489, 491, 520, 0,
780	V_NHSYNC | V_NVSYNC,
781	0, 0,
782	0, 0, 0, 0, 0, 0, 0,
783	0, 0, 0, 0, 0, 0,
784	FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
785    };
786
787    if (!crtc)
788	return FALSE;
789    if (crtc->enabled)
790	return FALSE;
791    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
792    crtc->funcs->mode_set (crtc, &mode, &mode, 0, 0);
793    crtc->funcs->dpms (crtc, DPMSModeOn);
794    return TRUE;
795}
796
797void
798i830_pipe_a_require_deactivate (ScrnInfoPtr scrn)
799{
800    xf86CrtcPtr	crtc = i830_crtc_for_pipe (scrn, 0);
801
802    if (!crtc)
803	return;
804    if (crtc->enabled)
805	return;
806    crtc->funcs->dpms (crtc, DPMSModeOff);
807    return;
808}
809
810/* FIXME: use pixmap private instead if possible */
811static Bool
812i830_display_tiled(xf86CrtcPtr crtc)
813{
814    ScrnInfoPtr pScrn = crtc->scrn;
815    I830Ptr pI830 = I830PTR(pScrn);
816
817    /* Rotated data is currently linear, allocated either via XAA or EXA */
818    if (crtc->rotatedData)
819	return FALSE;
820
821    if (pI830->front_buffer && pI830->front_buffer->tiling != TILE_NONE)
822	return TRUE;
823
824    return FALSE;
825}
826
827/*
828 * Several restrictions:
829 *   - DSP[AB]CNTR - no line duplication && no pixel multiplier
830 *   - pixel format == 15 bit, 16 bit, or 32 bit xRGB_8888
831 *   - no alpha buffer discard
832 *   - no dual wide display
833 *   - progressive mode only (DSP[AB]CNTR)
834 *   - uncompressed fb is <= 2048 in width, 0 mod 8
835 *   - uncompressed fb is <= 1536 in height, 0 mod 2
836 *   - SR display watermarks must be equal between 16bpp and 32bpp?
837 *
838 * FIXME: verify above conditions are true
839 *
840 * Enable 8xx style FB compression
841 */
842static void
843i830_enable_fb_compression_8xx(xf86CrtcPtr crtc)
844{
845    ScrnInfoPtr pScrn = crtc->scrn;
846    I830Ptr pI830 = I830PTR(pScrn);
847    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
848    uint32_t fbc_ctl = 0;
849    unsigned long compressed_stride;
850    int plane = (intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
851    unsigned long uncompressed_stride = pScrn->displayWidth * pI830->cpp;
852    unsigned long interval = 1000;
853
854    if (INREG(FBC_CONTROL) & FBC_CTL_EN)
855	return;
856
857    compressed_stride = pI830->compressed_front_buffer->size /
858	FBC_LL_SIZE;
859
860    if (uncompressed_stride < compressed_stride)
861	compressed_stride = uncompressed_stride;
862
863    /* FBC_CTL wants 64B units */
864    compressed_stride = (compressed_stride / 64) - 1;
865
866    /* Set it up... */
867    /* Wait for compressing bit to clear */
868    while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
869	; /* nothing */
870    i830WaitForVblank(pScrn);
871    OUTREG(FBC_CFB_BASE, pI830->compressed_front_buffer->bus_addr);
872    OUTREG(FBC_LL_BASE, pI830->compressed_ll_buffer->bus_addr + 6);
873    OUTREG(FBC_CONTROL2, FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM |
874	   FBC_CTL_CPU_FENCE | plane);
875    OUTREG(FBC_FENCE_OFF, crtc->y);
876
877    /* Zero buffers */
878    memset(pI830->FbBase + pI830->compressed_front_buffer->offset, 0,
879	   pI830->compressed_front_buffer->size);
880    memset(pI830->FbBase + pI830->compressed_ll_buffer->offset, 0,
881	   pI830->compressed_ll_buffer->size);
882
883    /* enable it... */
884    fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
885    fbc_ctl |= (compressed_stride & 0xff) << FBC_CTL_STRIDE_SHIFT;
886    fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
887    fbc_ctl |= FBC_CTL_UNCOMPRESSIBLE;
888    fbc_ctl |= pI830->front_buffer->fence_nr;
889    OUTREG(FBC_CONTROL, fbc_ctl);
890}
891
892/*
893 * Disable 8xx style FB compression
894 */
895static void
896i830_disable_fb_compression_8xx(xf86CrtcPtr crtc)
897{
898    ScrnInfoPtr pScrn = crtc->scrn;
899    I830Ptr pI830 = I830PTR(pScrn);
900    uint32_t fbc_ctl;
901
902    /* Disable compression */
903    fbc_ctl = INREG(FBC_CONTROL);
904    fbc_ctl &= ~FBC_CTL_EN;
905    OUTREG(FBC_CONTROL, fbc_ctl);
906
907    /* Wait for compressing bit to clear */
908    while (INREG(FBC_STATUS) & FBC_STAT_COMPRESSING)
909	; /* nothing */
910}
911
912static void
913i830_disable_fb_compression2(xf86CrtcPtr crtc)
914{
915    ScrnInfoPtr pScrn = crtc->scrn;
916    I830Ptr pI830 = I830PTR(pScrn);
917    uint32_t dpfc_ctl;
918
919    /* Disable compression */
920    dpfc_ctl = INREG(DPFC_CONTROL);
921    dpfc_ctl &= ~DPFC_CTL_EN;
922    OUTREG(DPFC_CONTROL, dpfc_ctl);
923    i830WaitForVblank(pScrn);
924}
925
926static void
927i830_enable_fb_compression2(xf86CrtcPtr crtc)
928{
929    ScrnInfoPtr pScrn = crtc->scrn;
930    I830Ptr pI830 = I830PTR(pScrn);
931    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
932    int plane = (intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB);
933    unsigned long stall_watermark = 200, frames = 50;
934
935    if (INREG(DPFC_CONTROL) & DPFC_CTL_EN)
936	return;
937
938    /* Set it up... */
939    i830_disable_fb_compression2(crtc);
940    OUTREG(DPFC_CB_BASE, pI830->compressed_front_buffer->offset);
941    /* Update i830_memory.c too if compression ratio changes */
942    OUTREG(DPFC_CONTROL, plane | DPFC_CTL_FENCE_EN | DPFC_CTL_LIMIT_4X |
943	   pI830->front_buffer->fence_nr);
944    OUTREG(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
945	   (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
946	   (frames << DPFC_RECOMP_TIMER_COUNT_SHIFT));
947    OUTREG(DPFC_FENCE_YOFF, crtc->y);
948
949    /* Zero buffers */
950    memset(pI830->FbBase + pI830->compressed_front_buffer->offset, 0,
951	   pI830->compressed_front_buffer->size);
952
953    /* enable it... */
954    OUTREG(DPFC_CONTROL, INREG(DPFC_CONTROL) | DPFC_CTL_EN);
955}
956
957static void
958i830_enable_fb_compression(xf86CrtcPtr crtc)
959{
960    ScrnInfoPtr pScrn = crtc->scrn;
961    I830Ptr pI830 = I830PTR(pScrn);
962
963    if (IS_GM45(pI830))
964	return i830_enable_fb_compression2(crtc);
965
966    i830_enable_fb_compression_8xx(crtc);
967}
968
969static void
970i830_disable_fb_compression(xf86CrtcPtr crtc)
971{
972    ScrnInfoPtr pScrn = crtc->scrn;
973    I830Ptr pI830 = I830PTR(pScrn);
974
975    if (IS_GM45(pI830))
976	return i830_disable_fb_compression2(crtc);
977
978    i830_disable_fb_compression_8xx(crtc);
979}
980
981static Bool
982i830_use_fb_compression(xf86CrtcPtr crtc)
983{
984    ScrnInfoPtr pScrn = crtc->scrn;
985    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
986    I830Ptr pI830 = I830PTR(pScrn);
987    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
988    unsigned long uncompressed_size;
989    int plane = (intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB);
990    int i, count = 0;
991
992    /* Only available on one pipe at a time */
993    for (i = 0; i < xf86_config->num_crtc; i++) {
994	if (xf86_config->crtc[i]->enabled)
995	    count++;
996    }
997
998    /* Here we disable it to catch one->two pipe enabled configs */
999    if (count > 1) {
1000	if (i830_fb_compression_supported(pI830))
1001	    i830_disable_fb_compression(crtc);
1002	return FALSE;
1003    }
1004
1005    if (!pI830->fb_compression)
1006	return FALSE;
1007
1008    if (!i830_display_tiled(crtc))
1009	return FALSE;
1010
1011    /* Pre-965 only supports plane A */
1012    if (!IS_I965GM(pI830) && plane != FBC_CTL_PLANEA)
1013	return FALSE;
1014
1015    /* Need 15, 16, or 32 (w/alpha) pixel format */
1016    if (!(pScrn->bitsPerPixel == 16 || /* covers 15 bit mode as well */
1017	  pScrn->bitsPerPixel == 32)) /* mode_set dtrt if fbc is in use */
1018	return FALSE;
1019
1020    /* Can't cache more lines than we can track */
1021    if (crtc->mode.VDisplay > FBC_LL_SIZE)
1022	return FALSE;
1023
1024    /*
1025     * Make sure the compressor doesn't go past the end of our compressed
1026     * buffer if the uncompressed size is large.
1027     */
1028    uncompressed_size = crtc->mode.HDisplay * crtc->mode.VDisplay *
1029	pI830->cpp;
1030    if (pI830->compressed_front_buffer->size < uncompressed_size)
1031	return FALSE;
1032
1033    /*
1034     * No checks for pixel multiply, incl. horizontal, or interlaced modes
1035     * since they're currently unused.
1036     */
1037    return TRUE;
1038}
1039
1040#if defined(DRM_IOCTL_MODESET_CTL)
1041static void i830_modeset_ctl(xf86CrtcPtr crtc, int pre)
1042{
1043    ScrnInfoPtr pScrn = crtc->scrn;
1044    I830Ptr pI830 = I830PTR(pScrn);
1045    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
1046    struct drm_modeset_ctl modeset;
1047
1048    if (pI830->directRenderingType <= DRI_NONE)
1049      return;
1050
1051    modeset.crtc = intel_crtc->pipe;
1052
1053    /*
1054     * DPMS will be called many times (especially off), but we only
1055     * want to catch the transition from on->off and off->on.
1056     */
1057    if (pre && intel_crtc->dpms_mode != DPMSModeOff) {
1058	/* On -> off is a pre modeset */
1059	modeset.cmd = _DRM_PRE_MODESET;
1060	ioctl(pI830->drmSubFD, DRM_IOCTL_MODESET_CTL, &modeset);
1061    } else if (!pre && intel_crtc->dpms_mode == DPMSModeOff) {
1062	/* Off -> on means post modeset */
1063	modeset.cmd = _DRM_POST_MODESET;
1064	ioctl(pI830->drmSubFD, DRM_IOCTL_MODESET_CTL, &modeset);
1065    }
1066}
1067#else
1068static void i830_modeset_ctl(xf86CrtcPtr crtc, int dpms_state)
1069{
1070    return;
1071}
1072#endif /* DRM_IOCTL_MODESET_CTL */
1073
1074static void
1075i830_disable_vga_plane (xf86CrtcPtr crtc)
1076{
1077    ScrnInfoPtr pScrn = crtc->scrn;
1078    I830Ptr pI830 = I830PTR(pScrn);
1079    uint8_t sr01;
1080
1081    /*
1082     * Bug #17235: G4X machine needs following steps
1083     * for disable VGA.
1084     * - set bit 5 of SR01;
1085     * - Wait 30us;
1086     * - disable vga plane;
1087     * - restore SR01;
1088     */
1089    if (IS_G4X(pI830)) {
1090	OUTREG8(SRX, 1);
1091	sr01 = INREG8(SRX + 1);
1092	OUTREG8(SRX + 1, sr01 | (1 << 5));
1093	usleep(30);
1094    }
1095
1096    OUTREG(VGACNTRL, VGA_DISP_DISABLE);
1097    i830WaitForVblank(pScrn);
1098
1099    /* restore SR01 */
1100    if (IS_G4X(pI830)) {
1101	OUTREG8(SRX, 1);
1102	OUTREG8(SRX + 1, sr01);
1103    }
1104}
1105
1106static void
1107i830_crtc_enable(xf86CrtcPtr crtc)
1108{
1109    ScrnInfoPtr pScrn = crtc->scrn;
1110    I830Ptr pI830 = I830PTR(pScrn);
1111    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
1112    int pipe = intel_crtc->pipe;
1113    int plane = intel_crtc->plane;
1114    int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
1115    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
1116    int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
1117    int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
1118    uint32_t temp;
1119
1120    /* Enable the DPLL */
1121    temp = INREG(dpll_reg);
1122    if ((temp & DPLL_VCO_ENABLE) == 0)
1123    {
1124	OUTREG(dpll_reg, temp);
1125	POSTING_READ(dpll_reg);
1126	/* Wait for the clocks to stabilize. */
1127	usleep(150);
1128	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
1129	POSTING_READ(dpll_reg);
1130	/* Wait for the clocks to stabilize. */
1131	usleep(150);
1132	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
1133	POSTING_READ(dpll_reg);
1134	/* Wait for the clocks to stabilize. */
1135	usleep(150);
1136    }
1137
1138    /* Enable the pipe */
1139    temp = INREG(pipeconf_reg);
1140    if ((temp & PIPEACONF_ENABLE) == 0)
1141	OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
1142
1143    /* Enable the plane */
1144    temp = INREG(dspcntr_reg);
1145    if ((temp & DISPLAY_PLANE_ENABLE) == 0)
1146    {
1147	OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
1148	/* Flush the plane changes */
1149	OUTREG(dspbase_reg, INREG(dspbase_reg));
1150    }
1151
1152    i830_crtc_load_lut(crtc);
1153
1154    /* Give the overlay scaler a chance to enable if it's on this pipe */
1155    i830_crtc_dpms_video(crtc, TRUE);
1156
1157    /* Reenable compression if needed */
1158    if (i830_use_fb_compression(crtc))
1159	i830_enable_fb_compression(crtc);
1160    i830_modeset_ctl(crtc, 0);
1161}
1162
1163void
1164i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe)
1165{
1166    ScrnInfoPtr pScrn = crtc->scrn;
1167    I830Ptr pI830 = I830PTR(pScrn);
1168    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
1169    int pipe = intel_crtc->pipe;
1170    int plane = intel_crtc->plane;
1171    int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
1172    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
1173    int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
1174    int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
1175    uint32_t temp;
1176
1177    i830_modeset_ctl(crtc, 1);
1178    /* Shut off compression if in use */
1179    if (i830_use_fb_compression(crtc))
1180	i830_disable_fb_compression(crtc);
1181
1182    /* Give the overlay scaler a chance to disable if it's on this pipe */
1183    i830_crtc_dpms_video(crtc, FALSE);
1184
1185    /*
1186     * The documentation says :
1187     * - Disable planes (VGA or hires)
1188     * - Disable pipe
1189     * - Disable VGA display
1190     */
1191
1192    /* Disable display plane */
1193    temp = INREG(dspcntr_reg);
1194    if ((temp & DISPLAY_PLANE_ENABLE) != 0)
1195    {
1196	OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
1197	/* Flush the plane changes */
1198	OUTREG(dspbase_reg, INREG(dspbase_reg));
1199	POSTING_READ(dspbase_reg);
1200    }
1201
1202    if (!IS_I9XX(pI830)) {
1203	/* Wait for vblank for the disable to take effect */
1204	i830WaitForVblank(pScrn);
1205    }
1206
1207    /* May need to leave pipe A on */
1208    if (disable_pipe)
1209    {
1210	/* Next, disable display pipes */
1211	temp = INREG(pipeconf_reg);
1212	if ((temp & PIPEACONF_ENABLE) != 0) {
1213	    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
1214	    POSTING_READ(pipeconf_reg);
1215	}
1216
1217	/* Wait for vblank for the disable to take effect. */
1218	i830WaitForVblank(pScrn);
1219
1220	temp = INREG(dpll_reg);
1221	if ((temp & DPLL_VCO_ENABLE) != 0) {
1222	    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
1223	    POSTING_READ(dpll_reg);
1224	}
1225
1226	/* Wait for the clocks to turn off. */
1227	usleep(150);
1228    }
1229
1230    /* Disable the VGA plane that we never use. */
1231    i830_disable_vga_plane (crtc);
1232}
1233
1234/**
1235 * Sets the power management mode of the pipe and plane.
1236 *
1237 * This code should probably grow support for turning the cursor off and back
1238 * on appropriately at the same time as we're turning the pipe off/on.
1239 */
1240static void
1241i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
1242{
1243    ScrnInfoPtr pScrn = crtc->scrn;
1244    I830Ptr pI830 = I830PTR(pScrn);
1245    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
1246    int pipe = intel_crtc->pipe;
1247    Bool disable_pipe = TRUE;
1248
1249    /* XXX: When our outputs are all unaware of DPMS modes other than off and
1250     * on, we should map those modes to DPMSModeOff in the CRTC.
1251     */
1252    switch (mode) {
1253    case DPMSModeOn:
1254    case DPMSModeStandby:
1255    case DPMSModeSuspend:
1256	i830_crtc_enable(crtc);
1257	break;
1258    case DPMSModeOff:
1259	if ((pipe == 0) && (pI830->quirk_flag & QUIRK_PIPEA_FORCE))
1260	    disable_pipe = FALSE;
1261	i830_crtc_disable(crtc, disable_pipe);
1262	intel_crtc->enabled = FALSE;
1263	break;
1264    }
1265
1266    intel_crtc->dpms_mode = mode;
1267}
1268
1269static Bool
1270i830_crtc_lock (xf86CrtcPtr crtc)
1271{
1272    /* Sync the engine before mode switch, to finish any outstanding
1273     * WAIT_FOR_EVENTS that may rely on CRTC state.
1274     */
1275    I830Sync(crtc->scrn);
1276
1277    return FALSE;
1278}
1279
1280static void
1281i830_crtc_unlock (xf86CrtcPtr crtc)
1282{
1283}
1284
1285static void
1286i830_crtc_prepare (xf86CrtcPtr crtc)
1287{
1288    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
1289    /* Temporarily turn off FB compression during modeset */
1290    if (i830_use_fb_compression(crtc))
1291        i830_disable_fb_compression(crtc);
1292    if (intel_crtc->enabled)
1293	crtc->funcs->hide_cursor (crtc);
1294    crtc->funcs->dpms (crtc, DPMSModeOff);
1295}
1296
1297static void
1298i830_crtc_commit (xf86CrtcPtr crtc)
1299{
1300    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
1301    Bool		deactivate = FALSE;
1302
1303    if (!intel_crtc->enabled && intel_crtc->pipe != 0)
1304	deactivate = i830_pipe_a_require_activate (crtc->scrn);
1305
1306    intel_crtc->enabled = TRUE;
1307
1308    crtc->funcs->dpms (crtc, DPMSModeOn);
1309    if (crtc->scrn->pScreen != NULL)
1310	xf86_reload_cursors (crtc->scrn->pScreen);
1311    if (deactivate)
1312	i830_pipe_a_require_deactivate (crtc->scrn);
1313
1314    /* Reenable FB compression if possible */
1315    if (i830_use_fb_compression(crtc))
1316	i830_enable_fb_compression(crtc);
1317}
1318
1319void
1320i830_output_prepare (xf86OutputPtr output)
1321{
1322    output->funcs->dpms (output, DPMSModeOff);
1323}
1324
1325void
1326i830_output_commit (xf86OutputPtr output)
1327{
1328    output->funcs->dpms (output, DPMSModeOn);
1329}
1330
1331static Bool
1332i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
1333		     DisplayModePtr adjusted_mode)
1334{
1335    return TRUE;
1336}
1337
1338/** Returns the core display clock speed for i830 - i945 */
1339static int
1340i830_get_core_clock_speed(ScrnInfoPtr pScrn)
1341{
1342    I830Ptr pI830 = I830PTR(pScrn);
1343
1344    /* Core clock values taken from the published datasheets.
1345     * The 830 may go up to 166 Mhz, which we should check.
1346     */
1347    if (IS_I945G(pI830) || (IS_G33CLASS(pI830) && !IS_IGDGM(pI830)))
1348	return 400000;
1349    else if (IS_I915G(pI830))
1350	return 333000;
1351    else if (IS_I945GM(pI830) || IS_845G(pI830) || IS_IGDGM(pI830))
1352	return 200000;
1353    else if (IS_I915GM(pI830)) {
1354	uint16_t gcfgc;
1355
1356      pci_device_cfg_read_u16 (pI830->PciInfo, &gcfgc, I915_GCFGC);
1357      if (gcfgc & I915_LOW_FREQUENCY_ENABLE)
1358	    return 133000;
1359	else {
1360	    switch (gcfgc & I915_DISPLAY_CLOCK_MASK) {
1361	    case I915_DISPLAY_CLOCK_333_MHZ:
1362		return 333000;
1363	    default:
1364	    case I915_DISPLAY_CLOCK_190_200_MHZ:
1365		return 190000;
1366	    }
1367	}
1368    } else if (IS_I865G(pI830))
1369	return 266000;
1370    else if (IS_I855(pI830)) {
1371        struct pci_device *bridge = intel_host_bridge ();
1372	uint16_t hpllcc;
1373	pci_device_cfg_read_u16 (bridge, &hpllcc, I855_HPLLCC);
1374
1375	/* Assume that the hardware is in the high speed state.  This
1376	 * should be the default.
1377	 */
1378	switch (hpllcc & I855_CLOCK_CONTROL_MASK) {
1379	case I855_CLOCK_133_200:
1380	case I855_CLOCK_100_200:
1381	    return 200000;
1382	case I855_CLOCK_166_250:
1383	    return 250000;
1384	case I855_CLOCK_100_133:
1385	    return 133000;
1386	}
1387    } else /* 852, 830 */
1388	return 133000;
1389
1390    return 0; /* Silence gcc warning */
1391}
1392
1393/**
1394 * Return the pipe currently connected to the panel fitter,
1395 * or -1 if the panel fitter is not present or not in use
1396 */
1397static int
1398i830_panel_fitter_pipe(I830Ptr pI830)
1399{
1400    uint32_t pfit_control;
1401
1402    /* i830 doesn't have a panel fitter */
1403    if (IS_I830(pI830))
1404	return -1;
1405
1406    pfit_control = INREG(PFIT_CONTROL);
1407
1408    /* See if the panel fitter is in use */
1409    if ((pfit_control & PFIT_ENABLE) == 0)
1410	return -1;
1411
1412    /* 965 can place panel fitter on either pipe */
1413    if (IS_I965G(pI830))
1414	return (pfit_control & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT;
1415
1416    /* older chips can only use pipe 1 */
1417    return 1;
1418}
1419
1420/**
1421 * Sets up the DSPARB register to split the display fifo appropriately between
1422 * the display planes.
1423 *
1424 * Adjusting this register requires that the planes be off.
1425 */
1426static void
1427i830_update_dsparb(ScrnInfoPtr pScrn)
1428{
1429   xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1430   I830Ptr pI830 = I830PTR(pScrn);
1431   int total_hdisplay = 0, planea_hdisplay = 0, planeb_hdisplay = 0;
1432   int fifo_entries = 0, planea_entries = 0, planeb_entries = 0, i;
1433
1434   if ((INREG(DSPACNTR) & DISPLAY_PLANE_ENABLE) &&
1435       (INREG(DSPBCNTR) & DISPLAY_PLANE_ENABLE))
1436       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1437		  "tried to update DSPARB with both planes enabled!\n");
1438
1439  /*
1440    * FIFO entries will be split based on programmed modes
1441    */
1442   if (IS_I965GM(pI830))
1443       fifo_entries = 127;
1444   else if (IS_I9XX(pI830))
1445       fifo_entries = 95;
1446   else if (IS_MOBILE(pI830)) {
1447       fifo_entries = 255;
1448   } else {
1449	/* The 845/865 only have a AEND field.  Though the field size would
1450	* allow 128 entries, the 865 rendered the cursor wrong then.
1451	* The BIOS set it up for 96.
1452	*/
1453	fifo_entries = 95;
1454   }
1455
1456   for (i = 0; i < xf86_config->num_crtc; i++) {
1457      xf86CrtcPtr crtc = xf86_config->crtc[i];
1458      I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
1459      if (crtc->enabled) {
1460	  total_hdisplay += crtc->mode.HDisplay;
1461	  if (intel_crtc->plane == 0)
1462	      planea_hdisplay = crtc->mode.HDisplay;
1463	  else
1464	      planeb_hdisplay = crtc->mode.HDisplay;
1465      }
1466   }
1467
1468   planea_entries = fifo_entries * planea_hdisplay / total_hdisplay;
1469   planeb_entries = fifo_entries * planeb_hdisplay / total_hdisplay;
1470
1471   if (IS_I9XX(pI830))
1472       OUTREG(DSPARB,
1473	      ((planea_entries + planeb_entries) << DSPARB_CSTART_SHIFT) |
1474	      (planea_entries << DSPARB_BSTART_SHIFT));
1475   else if (IS_MOBILE(pI830))
1476       OUTREG(DSPARB,
1477	      ((planea_entries + planeb_entries) << DSPARB_BEND_SHIFT) |
1478	      (planea_entries << DSPARB_AEND_SHIFT));
1479   else
1480       OUTREG(DSPARB, planea_entries << DSPARB_AEND_SHIFT);
1481}
1482
1483/**
1484 * Sets up registers for the given mode/adjusted_mode pair.
1485 *
1486 * The clocks, CRTCs and outputs attached to this CRTC must be off.
1487 *
1488 * This shouldn't enable any clocks, CRTCs, or outputs, but they should
1489 * be easily turned on/off after this.
1490 */
1491static void
1492i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
1493		   DisplayModePtr adjusted_mode,
1494		   int x, int y)
1495{
1496    ScrnInfoPtr pScrn = crtc->scrn;
1497    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1498    I830Ptr pI830 = I830PTR(pScrn);
1499    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
1500    I830OutputPrivatePtr intel_output;
1501    int pipe = intel_crtc->pipe;
1502    int plane = intel_crtc->plane;
1503    int fp_reg = (pipe == 0) ? FPA0 : FPB0;
1504    int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
1505    int dpll_md_reg = (pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
1506    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
1507    int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
1508    int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
1509    int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
1510    int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
1511    int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
1512    int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
1513    int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
1514    int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
1515    int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS;
1516    int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE;
1517    int i, num_outputs = 0;
1518    int refclk;
1519    intel_clock_t clock;
1520    uint32_t dpll = 0, fp = 0, dspcntr, pipeconf, lvds_bits = 0;
1521    Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
1522    Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
1523    const intel_limit_t *limit;
1524
1525    /* Set up some convenient bools for what outputs are connected to
1526     * our pipe, used in DPLL setup.
1527     */
1528    for (i = 0; i < xf86_config->num_output; i++) {
1529	xf86OutputPtr  output = xf86_config->output[i];
1530	intel_output = output->driver_private;
1531
1532	if (output->crtc != crtc)
1533	    continue;
1534
1535	switch (intel_output->type) {
1536	case I830_OUTPUT_LVDS:
1537	    is_lvds = TRUE;
1538	    lvds_bits = intel_output->lvds_bits;
1539	    break;
1540	case I830_OUTPUT_SDVO:
1541	case I830_OUTPUT_HDMI:
1542	    is_sdvo = TRUE;
1543	    if (intel_output->needs_tv_clock)
1544		is_tv = TRUE;
1545	    break;
1546	case I830_OUTPUT_DVO_TMDS:
1547	case I830_OUTPUT_DVO_LVDS:
1548	case I830_OUTPUT_DVO_TVOUT:
1549	    is_dvo = TRUE;
1550	    break;
1551	case I830_OUTPUT_TVOUT:
1552	    is_tv = TRUE;
1553	    break;
1554	case I830_OUTPUT_ANALOG:
1555	    is_crt = TRUE;
1556	    break;
1557	}
1558
1559	num_outputs++;
1560    }
1561
1562    if (num_outputs > 1)
1563	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "clone detected, disabling SSC\n");
1564
1565    /* Don't use SSC when cloned */
1566    if (is_lvds && pI830->lvds_use_ssc && num_outputs < 2) {
1567	refclk = pI830->lvds_ssc_freq * 1000;
1568	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1569		   "using SSC reference clock of %d MHz\n", refclk / 1000);
1570    } else if (IS_I9XX(pI830)) {
1571	refclk = 96000;
1572    } else {
1573	refclk = 48000;
1574    }
1575
1576    /*
1577     * Returns a set of divisors for the desired target clock with the given
1578     * refclk, or FALSE.  The returned values represent the clock equation:
1579     * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
1580     */
1581    limit = intel_limit (crtc);
1582    ok = limit->find_pll(limit, crtc, adjusted_mode->Clock, refclk, &clock);
1583    if (!ok)
1584	FatalError("Couldn't find PLL settings for mode!\n");
1585
1586    if (fabs(adjusted_mode->Clock - clock.dot) / clock.dot > .02) {
1587	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1588		   "Chosen PLL clock of %.1f Mhz more than 2%% away from "
1589		   "desired %.1f Mhz\n",
1590		   (float)clock.dot / 1000,
1591		   (float)adjusted_mode->Clock / 1000);
1592    }
1593
1594    /* SDVO TV has fixed PLL values depends on its clock range,
1595       this mirrors vbios setting. */
1596    if (is_sdvo && is_tv) {
1597	if (adjusted_mode->Clock >= 100000 &&
1598		adjusted_mode->Clock < 140500) {
1599	    clock.p1 = 2;
1600	    clock.p2 = 10;
1601	    clock.n = 3;
1602	    clock.m1 = 16;
1603	    clock.m2 = 8;
1604	} else if (adjusted_mode->Clock >= 140500 &&
1605		adjusted_mode->Clock <= 200000) {
1606	    clock.p1 = 1;
1607	    clock.p2 = 10;
1608	    clock.n = 6;
1609	    clock.m1 = 12;
1610	    clock.m2 = 8;
1611	}
1612    }
1613
1614    if (IS_IGD(pI830))
1615	fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
1616    else
1617	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
1618
1619    dpll = DPLL_VGA_MODE_DIS;
1620    if (IS_I9XX(pI830)) {
1621	if (is_lvds)
1622	    dpll |= DPLLB_MODE_LVDS;
1623	else
1624	    dpll |= DPLLB_MODE_DAC_SERIAL;
1625	if (is_sdvo)
1626	{
1627	    dpll |= DPLL_DVO_HIGH_SPEED;
1628	    if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)))
1629	    {
1630		int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
1631		dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
1632	    }
1633	}
1634
1635	/* compute bitmask from p1 value */
1636	if (IS_IGD(pI830))
1637	    dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_IGD;
1638	else
1639	    dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
1640	switch (clock.p2) {
1641	case 5:
1642	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
1643	    break;
1644	case 7:
1645	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
1646	    break;
1647	case 10:
1648	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
1649	    break;
1650	case 14:
1651	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
1652	    break;
1653	}
1654	if (IS_I965G(pI830) && !IS_GM45(pI830))
1655	    dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
1656    } else {
1657	if (is_lvds) {
1658	    dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
1659	} else {
1660	    if (clock.p1 == 2)
1661		dpll |= PLL_P1_DIVIDE_BY_TWO;
1662	    else
1663		dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT;
1664	    if (clock.p2 == 4)
1665		dpll |= PLL_P2_DIVIDE_BY_4;
1666	}
1667    }
1668
1669    if (is_sdvo && is_tv)
1670	dpll |= PLL_REF_INPUT_TVCLKINBC;
1671    else if (is_tv)
1672    {
1673	/* XXX: just matching BIOS for now */
1674/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
1675	dpll |= 3;
1676    }
1677    else if (is_lvds && pI830->lvds_use_ssc && num_outputs < 2)
1678	dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
1679    else
1680	dpll |= PLL_REF_INPUT_DREFCLK;
1681
1682    /* Set up the display plane register */
1683    dspcntr = DISPPLANE_GAMMA_ENABLE;
1684    switch (pScrn->bitsPerPixel) {
1685    case 8:
1686	dspcntr |= DISPPLANE_8BPP;
1687	break;
1688    case 16:
1689	if (pScrn->depth == 15)
1690	    dspcntr |= DISPPLANE_15_16BPP;
1691	else
1692	    dspcntr |= DISPPLANE_16BPP;
1693	break;
1694    case 32:
1695	dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
1696	break;
1697    default:
1698	FatalError("unknown display bpp\n");
1699    }
1700
1701    if (pipe == 0)
1702	dspcntr |= DISPPLANE_SEL_PIPE_A;
1703    else
1704	dspcntr |= DISPPLANE_SEL_PIPE_B;
1705
1706    if (IS_I965G(pI830) && i830_display_tiled(crtc))
1707	dspcntr |= DISPLAY_PLANE_TILED;
1708
1709    pipeconf = INREG(pipeconf_reg);
1710    if (pipe == 0 && !IS_I965G(pI830))
1711    {
1712	/* Enable pixel doubling when the dot clock is > 90% of the (display)
1713	 * core speed.
1714	 *
1715	 * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
1716	 * pipe == 0 check?
1717	 */
1718	if (mode->Clock > i830_get_core_clock_speed(pScrn) * 9 / 10)
1719	    pipeconf |= PIPEACONF_DOUBLE_WIDE;
1720	else
1721	    pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
1722    }
1723    /*
1724     * This "shouldn't" be needed as the dpms on code
1725     * will be run after the mode is set. On 9xx, it helps.
1726     * On 855, it can lock up the chip (and the entire machine)
1727     */
1728    if (!IS_I85X (pI830))
1729    {
1730	dspcntr |= DISPLAY_PLANE_ENABLE;
1731	pipeconf |= PIPEACONF_ENABLE;
1732	dpll |= DPLL_VCO_ENABLE;
1733    }
1734
1735    /* Disable the panel fitter if it was on our pipe */
1736    if (i830_panel_fitter_pipe (pI830) == pipe)
1737	OUTREG(PFIT_CONTROL, 0);
1738
1739    if (pI830->debug_modes) {
1740	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1741		   "Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
1742	xf86PrintModeline(pScrn->scrnIndex, mode);
1743	if (!xf86ModesEqual(mode, adjusted_mode)) {
1744	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1745		       "Adjusted mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
1746	    xf86PrintModeline(pScrn->scrnIndex, adjusted_mode);
1747	}
1748	i830PrintPll(pScrn, "chosen", &clock);
1749    }
1750
1751    if (dpll & DPLL_VCO_ENABLE)
1752    {
1753	OUTREG(fp_reg, fp);
1754	OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
1755	POSTING_READ(dpll_reg);
1756	usleep(150);
1757    }
1758
1759    /* The LVDS pin pair needs to be on before the DPLLs are enabled.
1760     * This is an exception to the general rule that mode_set doesn't turn
1761     * things on.
1762     */
1763    if (is_lvds)
1764    {
1765	uint32_t lvds = INREG(LVDS);
1766
1767	lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
1768	/* Set the B0-B3 data pairs corresponding to whether we're going to
1769	 * set the DPLLs for dual-channel mode or not.
1770	 */
1771	if (clock.p2 == I9XX_P2_LVDS_FAST)
1772	    lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
1773	else
1774	    lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
1775
1776	if (pI830->lvds_24_bit_mode) {
1777	    /* Option set which requests 24-bit mode
1778	     * (LVDS_A3_POWER_UP, as opposed to 18-bit mode) here; we
1779	     * still need to look more thoroughly into how panels
1780	     * behave in the two modes.  This option enables that
1781	     * experimentation.
1782	     */
1783	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1784		       "Selecting less common 24 bit TMDS pixel format.\n");
1785	    lvds |= LVDS_A3_POWER_UP;
1786	    lvds |= LVDS_DATA_FORMAT_DOT_ONE;
1787	} else {
1788	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1789		       "Selecting standard 18 bit TMDS pixel format.\n");
1790	}
1791
1792	/* Enable dithering if we're in 18-bit mode. */
1793	if (IS_I965G(pI830))
1794	{
1795	    if ((lvds & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
1796		lvds &= ~LVDS_DITHER_ENABLE;
1797	    else
1798		lvds |= LVDS_DITHER_ENABLE;
1799	}
1800
1801	lvds |= lvds_bits;
1802
1803	OUTREG(LVDS, lvds);
1804	POSTING_READ(LVDS);
1805    }
1806
1807    OUTREG(fp_reg, fp);
1808    OUTREG(dpll_reg, dpll);
1809    POSTING_READ(dpll_reg);
1810    /* Wait for the clocks to stabilize. */
1811    usleep(150);
1812
1813    if (IS_I965G(pI830)) {
1814	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
1815	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
1816	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
1817    } else {
1818	/* write it again -- the BIOS does, after all */
1819	OUTREG(dpll_reg, dpll);
1820    }
1821    POSTING_READ(dpll_reg);
1822    /* Wait for the clocks to stabilize. */
1823    usleep(150);
1824
1825    if (!DSPARB_HWCONTROL(pI830))
1826	i830_update_dsparb(pScrn);
1827
1828    OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
1829	((adjusted_mode->CrtcHTotal - 1) << 16));
1830    OUTREG(hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) |
1831	((adjusted_mode->CrtcHBlankEnd - 1) << 16));
1832    OUTREG(hsync_reg, (adjusted_mode->CrtcHSyncStart - 1) |
1833	((adjusted_mode->CrtcHSyncEnd - 1) << 16));
1834    OUTREG(vtot_reg, (adjusted_mode->CrtcVDisplay - 1) |
1835	((adjusted_mode->CrtcVTotal - 1) << 16));
1836
1837    OUTREG(vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) |
1838	((adjusted_mode->CrtcVBlankEnd - 1) << 16));
1839    OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
1840	((adjusted_mode->CrtcVSyncEnd - 1) << 16));
1841    /* pipesrc and dspsize control the size that is scaled from, which should
1842     * always be the user's requested size.
1843     */
1844    OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
1845    OUTREG(dsppos_reg, 0);
1846    OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
1847    OUTREG(pipeconf_reg, pipeconf);
1848    POSTING_READ(pipeconf_reg);
1849    i830WaitForVblank(pScrn);
1850
1851    OUTREG(dspcntr_reg, dspcntr);
1852    /* Flush the plane changes */
1853    i830PipeSetBase(crtc, x, y);
1854
1855    i830WaitForVblank(pScrn);
1856}
1857
1858
1859/** Loads the palette/gamma unit for the CRTC with the prepared values */
1860static void
1861i830_crtc_load_lut(xf86CrtcPtr crtc)
1862{
1863    ScrnInfoPtr pScrn = crtc->scrn;
1864    I830Ptr pI830 = I830PTR(pScrn);
1865    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
1866    int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B;
1867    int i;
1868
1869    /* The clocks have to be on to load the palette. */
1870    if (!crtc->enabled)
1871	return;
1872
1873    for (i = 0; i < 256; i++) {
1874	OUTREG(palreg + 4 * i,
1875	       (intel_crtc->lut_r[i] << 16) |
1876	       (intel_crtc->lut_g[i] << 8) |
1877	       intel_crtc->lut_b[i]);
1878    }
1879}
1880
1881/** Sets the color ramps on behalf of RandR */
1882static void
1883i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
1884		    int size)
1885{
1886    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
1887    int i;
1888
1889    assert(size == 256);
1890
1891    for (i = 0; i < 256; i++) {
1892	intel_crtc->lut_r[i] = red[i] >> 8;
1893	intel_crtc->lut_g[i] = green[i] >> 8;
1894	intel_crtc->lut_b[i] = blue[i] >> 8;
1895    }
1896
1897    i830_crtc_load_lut(crtc);
1898}
1899
1900/**
1901 * Allocates memory for a locked-in-framebuffer shadow of the given
1902 * width and height for this CRTC's rotated shadow framebuffer.
1903 */
1904
1905static void *
1906i830_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
1907{
1908    ScrnInfoPtr pScrn = crtc->scrn;
1909    I830Ptr pI830 = I830PTR(pScrn);
1910    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
1911    unsigned long rotate_pitch;
1912    int align = KB(4), size;
1913
1914    width = i830_pad_drawable_width(width, pI830->cpp);
1915    rotate_pitch = width * pI830->cpp;
1916    size = rotate_pitch * height;
1917
1918    assert(intel_crtc->rotate_mem == NULL);
1919    intel_crtc->rotate_mem = i830_allocate_memory(pScrn, "rotated crtc",
1920						  size, rotate_pitch, align,
1921						  0, TILE_NONE);
1922    if (intel_crtc->rotate_mem == NULL) {
1923	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1924		   "Couldn't allocate shadow memory for rotated CRTC\n");
1925	return NULL;
1926    }
1927    memset(pI830->FbBase + intel_crtc->rotate_mem->offset, 0, size);
1928
1929    return pI830->FbBase + intel_crtc->rotate_mem->offset;
1930}
1931
1932/**
1933 * Creates a pixmap for this CRTC's rotated shadow framebuffer.
1934 */
1935static PixmapPtr
1936i830_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
1937{
1938    ScrnInfoPtr pScrn = crtc->scrn;
1939    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
1940    I830Ptr pI830 = I830PTR(pScrn);
1941    int rotate_pitch;
1942    PixmapPtr rotate_pixmap;
1943
1944    if (!data)
1945	data = i830_crtc_shadow_allocate (crtc, width, height);
1946
1947    rotate_pitch = i830_pad_drawable_width(width, pI830->cpp) * pI830->cpp;
1948
1949    rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
1950					   width, height,
1951					   pScrn->depth,
1952					   pScrn->bitsPerPixel,
1953					   rotate_pitch,
1954					   data);
1955
1956    if (rotate_pixmap == NULL) {
1957	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1958		   "Couldn't allocate shadow pixmap for rotated CRTC\n");
1959    }
1960    if (intel_crtc->rotate_mem && intel_crtc->rotate_mem->bo)
1961	i830_set_pixmap_bo(rotate_pixmap, intel_crtc->rotate_mem->bo);
1962    return rotate_pixmap;
1963}
1964
1965static void
1966i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
1967{
1968    ScrnInfoPtr pScrn = crtc->scrn;
1969    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
1970
1971    if (rotate_pixmap) {
1972	i830_set_pixmap_bo(rotate_pixmap, NULL);
1973	FreeScratchPixmapHeader(rotate_pixmap);
1974    }
1975
1976    if (data) {
1977	/* Be sure to sync acceleration before the memory gets unbound. */
1978	I830Sync(pScrn);
1979	i830_free_memory(pScrn, intel_crtc->rotate_mem);
1980	intel_crtc->rotate_mem = NULL;
1981    }
1982}
1983
1984#if RANDR_13_INTERFACE
1985static void
1986i830_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
1987{
1988    if (crtc->enabled)
1989	i830PipeSetBase(crtc, x, y);
1990}
1991#endif
1992
1993/* The screen bo has changed, reset each active crtc to point at
1994 * the same location that it currently points at, but in the new bo
1995 */
1996void
1997i830_set_new_crtc_bo(ScrnInfoPtr pScrn)
1998{
1999    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2000    int			i;
2001
2002    for (i = 0; i < xf86_config->num_crtc; i++) {
2003	xf86CrtcPtr crtc = xf86_config->crtc[i];
2004
2005	if (crtc->enabled && !crtc->transform_in_use)
2006	    i830PipeSetBase(crtc, crtc->x, crtc->y);
2007    }
2008}
2009
2010void
2011i830DescribeOutputConfiguration(ScrnInfoPtr pScrn)
2012{
2013    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2014    I830Ptr pI830 = I830PTR(pScrn);
2015    int i;
2016
2017    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n");
2018
2019    for (i = 0; i < xf86_config->num_crtc; i++) {
2020	xf86CrtcPtr crtc = xf86_config->crtc[i];
2021	I830CrtcPrivatePtr intel_crtc = crtc ? crtc->driver_private : NULL;
2022	uint32_t dspcntr = intel_crtc->plane == 0 ? INREG(DSPACNTR) :
2023	    INREG(DSPBCNTR);
2024	uint32_t pipeconf = i == 0 ? INREG(PIPEACONF) :
2025	    INREG(PIPEBCONF);
2026	Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
2027	Bool hw_pipe_enable = (pipeconf & PIPEACONF_ENABLE) != 0;
2028
2029	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2030		   "  Pipe %c is %s\n",
2031		   'A' + i, crtc->enabled ? "on" : "off");
2032	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2033		   "  Display plane %c is now %s and connected to pipe %c.\n",
2034		   'A' + intel_crtc->plane,
2035		   hw_plane_enable ? "enabled" : "disabled",
2036		   dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
2037	if (hw_pipe_enable != crtc->enabled) {
2038	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2039		       "  Hardware claims pipe %c is %s while software "
2040		       "believes it is %s\n",
2041		       'A' + i, hw_pipe_enable ? "on" : "off",
2042		       crtc->enabled ? "on" : "off");
2043	}
2044	if (hw_plane_enable != crtc->enabled) {
2045	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2046		       "  Hardware claims plane %c is %s while software "
2047		       "believes it is %s\n",
2048		       'A' + i, hw_plane_enable ? "on" : "off",
2049		       crtc->enabled ? "on" : "off");
2050	}
2051    }
2052
2053    for (i = 0; i < xf86_config->num_output; i++) {
2054	xf86OutputPtr	output = xf86_config->output[i];
2055	xf86CrtcPtr	crtc = output->crtc;
2056	I830CrtcPrivatePtr	intel_crtc = crtc ? crtc->driver_private : NULL;
2057
2058	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2059		   "  Output %s is connected to pipe %s\n",
2060		   output->name, intel_crtc == NULL ? "none" :
2061		   (intel_crtc->pipe == 0 ? "A" : "B"));
2062    }
2063}
2064
2065/**
2066 * Get a pipe with a simple mode set on it for doing load-based monitor
2067 * detection.
2068 *
2069 * It will be up to the load-detect code to adjust the pipe as appropriate for
2070 * its requirements.  The pipe will be connected to no other outputs.
2071 *
2072 * Currently this code will only succeed if there is a pipe with no outputs
2073 * configured for it.  In the future, it could choose to temporarily disable
2074 * some outputs to free up a pipe for its use.
2075 *
2076 * \return crtc, or NULL if no pipes are available.
2077 */
2078
2079/* VESA 640x480x72Hz mode to set on the pipe */
2080static DisplayModeRec   load_detect_mode = {
2081    NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
2082    31500,
2083    640, 664, 704, 832, 0,
2084    480, 489, 491, 520, 0,
2085    V_NHSYNC | V_NVSYNC,
2086    0, 0,
2087
2088    640, 640, 664, 704, 832, 832, 0,
2089    480, 489, 489, 491, 520, 520,
2090    FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
2091};
2092
2093xf86CrtcPtr
2094i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, int *dpms_mode)
2095{
2096    ScrnInfoPtr		    pScrn = output->scrn;
2097    xf86CrtcConfigPtr	    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2098    I830OutputPrivatePtr    intel_output = output->driver_private;
2099    I830CrtcPrivatePtr	    intel_crtc;
2100    xf86CrtcPtr		    supported_crtc =NULL;
2101    xf86CrtcPtr		    crtc = NULL;
2102    int			    i;
2103
2104    if (output->crtc)
2105    {
2106	crtc = output->crtc;
2107	/*
2108	 * Make sure the crtc and output are running
2109	 */
2110	intel_crtc = crtc->driver_private;
2111	*dpms_mode = intel_crtc->dpms_mode;
2112	if (intel_crtc->dpms_mode != DPMSModeOn)
2113	{
2114	    crtc->funcs->dpms (crtc, DPMSModeOn);
2115	    output->funcs->dpms (output, DPMSModeOn);
2116	}
2117	return crtc;
2118    }
2119
2120    for (i = 0; i < xf86_config->num_crtc; i++)
2121    {
2122	xf86CrtcPtr possible_crtc;
2123	if (!(output->possible_crtcs & (1 << i)))
2124	    continue;
2125	possible_crtc = xf86_config->crtc[i];
2126	if (!possible_crtc->enabled)
2127	{
2128	    crtc = possible_crtc;
2129	    break;
2130	}
2131	if (!supported_crtc)
2132	    supported_crtc = possible_crtc;
2133    }
2134    if (!crtc)
2135    {
2136	crtc = supported_crtc;
2137	if (!crtc)
2138	    return NULL;
2139    }
2140
2141    output->crtc = crtc;
2142    intel_output->load_detect_temp = TRUE;
2143
2144    intel_crtc = crtc->driver_private;
2145    *dpms_mode = intel_crtc->dpms_mode;
2146
2147    if (!crtc->enabled)
2148    {
2149	if (!mode)
2150	    mode = &load_detect_mode;
2151	xf86CrtcSetMode (crtc, mode, RR_Rotate_0, 0, 0);
2152    }
2153    else
2154    {
2155	if (intel_crtc->dpms_mode != DPMSModeOn)
2156	    crtc->funcs->dpms (crtc, DPMSModeOn);
2157
2158	/* Add this output to the crtc */
2159	output->funcs->mode_set (output, &crtc->mode, &crtc->mode);
2160	output->funcs->commit (output);
2161    }
2162    /* let the output get through one full cycle before testing */
2163    i830WaitForVblank (pScrn);
2164
2165    return crtc;
2166}
2167
2168void
2169i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode)
2170{
2171    ScrnInfoPtr		    pScrn = output->scrn;
2172    I830OutputPrivatePtr    intel_output = output->driver_private;
2173    xf86CrtcPtr		    crtc = output->crtc;
2174
2175    if (intel_output->load_detect_temp)
2176    {
2177	output->crtc = NULL;
2178	intel_output->load_detect_temp = FALSE;
2179	crtc->enabled = xf86CrtcInUse (crtc);
2180	xf86DisableUnusedFunctions(pScrn);
2181    }
2182    /*
2183     * Switch crtc and output back off if necessary
2184     */
2185    if (crtc->enabled && dpms_mode != DPMSModeOn)
2186    {
2187	if (output->crtc == crtc)
2188	    output->funcs->dpms (output, dpms_mode);
2189	crtc->funcs->dpms (crtc, dpms_mode);
2190    }
2191}
2192
2193/* Returns the clock of the currently programmed mode of the given pipe. */
2194static int
2195i830_crtc_clock_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
2196{
2197    I830Ptr pI830 = I830PTR(pScrn);
2198    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
2199    int pipe = intel_crtc->pipe;
2200    uint32_t dpll = INREG((pipe == 0) ? DPLL_A : DPLL_B);
2201    uint32_t fp;
2202    intel_clock_t clock;
2203
2204    if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
2205	fp = INREG((pipe == 0) ? FPA0 : FPB0);
2206    else
2207	fp = INREG((pipe == 0) ? FPA1 : FPB1);
2208
2209    clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
2210    if (IS_IGD(pI830)) {
2211	clock.n = ffs((fp & FP_N_IGD_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
2212	clock.m2 = (fp & FP_M2_IGD_DIV_MASK) >> FP_M2_DIV_SHIFT;
2213    } else {
2214	clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
2215	clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
2216    }
2217    if (IS_I9XX(pI830)) {
2218	if (IS_IGD(pI830))
2219	    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_IGD) >>
2220			   DPLL_FPA01_P1_POST_DIV_SHIFT_IGD);
2221	else
2222	    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
2223			   DPLL_FPA01_P1_POST_DIV_SHIFT);
2224
2225	switch (dpll & DPLL_MODE_MASK) {
2226	case DPLLB_MODE_DAC_SERIAL:
2227	    clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
2228	    break;
2229	case DPLLB_MODE_LVDS:
2230	    clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
2231	    break;
2232	default:
2233	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2234		       "Unknown DPLL mode %08x in programmed mode\n",
2235		       (int)(dpll & DPLL_MODE_MASK));
2236	    return 0;
2237	}
2238
2239	if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
2240	    intel_clock(pI830, 100000, &clock);
2241	else
2242	    intel_clock(pI830, 96000, &clock);
2243    } else {
2244	Bool is_lvds = (pipe == 1) && (INREG(LVDS) & LVDS_PORT_EN);
2245
2246	if (is_lvds) {
2247	    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
2248			   DPLL_FPA01_P1_POST_DIV_SHIFT);
2249
2250	    /* if LVDS is dual-channel, p2 = 7 */
2251	    if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
2252		clock.p2 = 7;
2253	    else
2254		clock.p2 = 14;
2255
2256	    if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
2257		intel_clock(pI830, 66000, &clock); /* XXX: might not be 66MHz */
2258	    else
2259		intel_clock(pI830, 48000, &clock);
2260	} else {
2261	    if (dpll & PLL_P1_DIVIDE_BY_TWO) {
2262		clock.p1 = 2;
2263	    } else {
2264		clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
2265		    DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
2266	    }
2267	    if (dpll & PLL_P2_DIVIDE_BY_4)
2268		clock.p2 = 4;
2269	    else
2270		clock.p2 = 2;
2271
2272	    intel_clock(pI830, 48000, &clock);
2273	}
2274    }
2275
2276    /* XXX: It would be nice to validate the clocks, but we can't reuse
2277     * i830PllIsValid() because it relies on the xf86_config output
2278     * configuration being accurate, which it isn't necessarily.
2279     */
2280    if (0)
2281	i830PrintPll(pScrn, "probed", &clock);
2282
2283    return clock.dot;
2284}
2285
2286/** Returns the currently programmed mode of the given pipe. */
2287DisplayModePtr
2288i830_crtc_mode_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
2289{
2290    I830Ptr pI830 = I830PTR(pScrn);
2291    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
2292    int pipe = intel_crtc->pipe;
2293    DisplayModePtr mode;
2294    int htot = INREG((pipe == 0) ? HTOTAL_A : HTOTAL_B);
2295    int hsync = INREG((pipe == 0) ? HSYNC_A : HSYNC_B);
2296    int vtot = INREG((pipe == 0) ? VTOTAL_A : VTOTAL_B);
2297    int vsync = INREG((pipe == 0) ? VSYNC_A : VSYNC_B);
2298
2299    mode = xcalloc(1, sizeof(DisplayModeRec));
2300    if (mode == NULL)
2301	return NULL;
2302
2303    mode->Clock = i830_crtc_clock_get(pScrn, crtc);
2304    mode->HDisplay = (htot & 0xffff) + 1;
2305    mode->HTotal = ((htot & 0xffff0000) >> 16) + 1;
2306    mode->HSyncStart = (hsync & 0xffff) + 1;
2307    mode->HSyncEnd = ((hsync & 0xffff0000) >> 16) + 1;
2308    mode->VDisplay = (vtot & 0xffff) + 1;
2309    mode->VTotal = ((vtot & 0xffff0000) >> 16) + 1;
2310    mode->VSyncStart = (vsync & 0xffff) + 1;
2311    mode->VSyncEnd = ((vsync & 0xffff0000) >> 16) + 1;
2312    xf86SetModeDefaultName(mode);
2313    xf86SetModeCrtc(mode, 0);
2314
2315    return mode;
2316}
2317
2318static const xf86CrtcFuncsRec i830_crtc_funcs = {
2319    .dpms = i830_crtc_dpms,
2320    .save = NULL, /* XXX */
2321    .restore = NULL, /* XXX */
2322    .lock = i830_crtc_lock,
2323    .unlock = i830_crtc_unlock,
2324    .mode_fixup = i830_crtc_mode_fixup,
2325    .prepare = i830_crtc_prepare,
2326    .mode_set = i830_crtc_mode_set,
2327    .commit = i830_crtc_commit,
2328    .gamma_set = i830_crtc_gamma_set,
2329    .shadow_create = i830_crtc_shadow_create,
2330    .shadow_allocate = i830_crtc_shadow_allocate,
2331    .shadow_destroy = i830_crtc_shadow_destroy,
2332    .set_cursor_colors = i830_crtc_set_cursor_colors,
2333    .set_cursor_position = i830_crtc_set_cursor_position,
2334    .show_cursor = i830_crtc_show_cursor,
2335    .hide_cursor = i830_crtc_hide_cursor,
2336    .load_cursor_argb = i830_crtc_load_cursor_argb,
2337    .destroy = NULL, /* XXX */
2338#if RANDR_13_INTERFACE
2339    .set_origin = i830_crtc_set_origin,
2340#endif
2341};
2342
2343void
2344i830_crtc_init(ScrnInfoPtr pScrn, int pipe)
2345{
2346    xf86CrtcPtr crtc;
2347    I830CrtcPrivatePtr intel_crtc;
2348    int i;
2349
2350    crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs);
2351    if (crtc == NULL)
2352	return;
2353
2354    intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
2355    intel_crtc->pipe = pipe;
2356    intel_crtc->dpms_mode = DPMSModeOff;
2357    intel_crtc->plane = pipe;
2358
2359    /* Initialize the LUTs for when we turn on the CRTC. */
2360    for (i = 0; i < 256; i++) {
2361	intel_crtc->lut_r[i] = i;
2362	intel_crtc->lut_g[i] = i;
2363	intel_crtc->lut_b[i] = i;
2364    }
2365    crtc->driver_private = intel_crtc;
2366}
2367
2368