/[pkgs]/devel/kernel/drm-intel-pm.patch
ViewVC logotype

Contents of /devel/kernel/drm-intel-pm.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (show annotations) (download) (as text)
Wed Sep 2 15:46:20 2009 UTC (2 months, 3 weeks ago) by ajax
Branch: MAIN
CVS Tags: kernel-2_6_32-0_24_rc4_git0_fc13, kernel-2_6_32-0_47_rc7_git1_fc13, kernel-2_6_32-0_14_rc0_git18_fc13, kernel-2_6_31-0_210_rc9_git1_fc12, kernel-2_6_31-0_213_rc9_git1_fc12, kernel-2_6_31-0_203_rc8_git2_fc12, kernel-2_6_32-0_48_rc7_git1_fc13, kernel-2_6_32-0_5_rc0_git4_fc13, kernel-2_6_31-0_204_rc9_fc12, kernel-2_6_32-0_33_rc5_git1_fc13, kernel-2_6_31-2_fc12, kernel-2_6_31-0_199_rc8_git2_fc12, F-12-split, kernel-2_6_32-0_51_rc7_git2_fc13, kernel-2_6_31-0_219_rc9_git2_fc12, kernel-2_6_31-1_fc12, kernel-2_6_31-0_198_rc8_git2_fc12, kernel-2_6_32-0_46_rc7_git1_fc13, kernel-2_6_31-0_209_rc9_git1_fc12, kernel-2_6_31-0_212_rc9_git1_fc12, kernel-2_6_32-0_15_rc1_git0_fc13, kernel-2_6_31-0_218_rc9_git2_fc12, kernel-2_6_31-0_202_rc8_git2_fc12, kernel-2_6_31-0_214_rc9_git1_fc12, kernel-2_6_32-0_39_rc5_git6_fc13, HEAD
Changes since 1.4: +1 -1 lines
File MIME type: text/x-patch
* Wed Sep 02 2009 Adam Jackson <ajax@redhat.com>
- drm-intel-pm.patch: Disable by default, too flickery on too many machines.
  Enable with i915.powersave=1.
1 diff -up linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_drv.c.jx linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_drv.c
2 --- linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_drv.c.jx 2009-08-03 14:00:43.000000000 -0400
3 +++ linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_drv.c 2009-08-03 14:01:07.000000000 -0400
4 @@ -43,6 +43,21 @@ module_param_named(modeset, i915_modeset
5 unsigned int i915_fbpercrtc = 0;
6 module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
7
8 +unsigned int i915_powersave = 0;
9 +module_param_named(powersave, i915_powersave, int, 0400);
10 +
11 +unsigned int i915_lvdsclock = 1;
12 +module_param_named(lvdsclock, i915_lvdsclock, int, 0400);
13 +
14 +unsigned int i915_lvdsscale = 85;
15 +module_param_named(lvdsscale, i915_lvdsscale, int, 0400);
16 +
17 +unsigned int i915_displayclock = 1;
18 +module_param_named(displayclock, i915_displayclock, int, 0600);
19 +
20 +unsigned int i915_renderclock = 0;
21 +module_param_named(renderclock, i915_renderclock, int, 0600);
22 +
23 static struct drm_driver driver;
24
25 static struct pci_device_id pciidlist[] = {
26 diff -up linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_drv.h.jx linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_drv.h
27 --- linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_drv.h.jx 2009-08-03 14:00:44.000000000 -0400
28 +++ linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_drv.h 2009-08-03 14:01:07.000000000 -0400
29 @@ -438,6 +438,12 @@ typedef struct drm_i915_private {
30 struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
31 } mm;
32 struct sdvo_device_mapping sdvo_mappings[2];
33 +
34 + /* Reclocking support */
35 + struct work_struct idle_work;
36 + struct timer_list idle_timer;
37 + bool busy;
38 + u16 orig_clock;
39 } drm_i915_private_t;
40
41 /** driver private structure attached to each drm_gem_object */
42 @@ -567,6 +573,11 @@ enum intel_chip_family {
43 extern struct drm_ioctl_desc i915_ioctls[];
44 extern int i915_max_ioctl;
45 extern unsigned int i915_fbpercrtc;
46 +extern unsigned int i915_powersave;
47 +extern unsigned int i915_lvdsclock;
48 +extern unsigned int i915_lvdsscale;
49 +extern unsigned int i915_displayclock;
50 +extern unsigned int i915_renderclock;
51
52 extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
53 extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
54 @@ -895,6 +906,9 @@ extern int i915_wait_ring(struct drm_dev
55 /* dsparb controlled by hw only */
56 #define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev))
57
58 +#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IGDNG(dev))
59 +#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IGDNG(dev))
60 +
61 #define PRIMARY_RINGBUFFER_SIZE (128*1024)
62
63 #endif
64 diff -up linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_gem.c.jx linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_gem.c
65 --- linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_gem.c.jx 2009-08-03 14:00:43.000000000 -0400
66 +++ linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_gem.c 2009-08-03 14:01:07.000000000 -0400
67 @@ -29,6 +29,7 @@
68 #include "drm.h"
69 #include "i915_drm.h"
70 #include "i915_drv.h"
71 +#include "intel_drv.h"
72 #include <linux/swap.h>
73 #include <linux/pci.h>
74
75 @@ -980,6 +981,7 @@ i915_gem_set_domain_ioctl(struct drm_dev
76 {
77 struct drm_i915_gem_set_domain *args = data;
78 struct drm_gem_object *obj;
79 + struct drm_i915_gem_object *obj_priv;
80 uint32_t read_domains = args->read_domains;
81 uint32_t write_domain = args->write_domain;
82 int ret;
83 @@ -1003,8 +1005,12 @@ i915_gem_set_domain_ioctl(struct drm_dev
84 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
85 if (obj == NULL)
86 return -EBADF;
87 + obj_priv = obj->driver_private;
88
89 mutex_lock(&dev->struct_mutex);
90 +
91 + intel_mark_busy(dev, obj);
92 +
93 #if WATCH_BUF
94 DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n",
95 obj, obj->size, read_domains, write_domain);
96 @@ -2761,6 +2767,8 @@ i915_gem_object_set_to_gpu_domain(struct
97 BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU);
98 BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU);
99
100 + intel_mark_busy(dev, obj);
101 +
102 #if WATCH_BUF
103 DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
104 __func__, obj,
105 diff -up linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_reg.h.jx linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_reg.h
106 --- linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_reg.h.jx 2009-08-03 14:00:44.000000000 -0400
107 +++ linux-2.6.30.noarch/drivers/gpu/drm/i915/i915_reg.h 2009-08-03 14:01:07.000000000 -0400
108 @@ -55,7 +55,7 @@
109 /* PCI config space */
110
111 #define HPLLCC 0xc0 /* 855 only */
112 -#define GC_CLOCK_CONTROL_MASK (3 << 0)
113 +#define GC_CLOCK_CONTROL_MASK (0xf << 0)
114 #define GC_CLOCK_133_200 (0 << 0)
115 #define GC_CLOCK_100_200 (1 << 0)
116 #define GC_CLOCK_100_133 (2 << 0)
117 @@ -65,6 +65,25 @@
118 #define GC_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
119 #define GC_DISPLAY_CLOCK_333_MHZ (4 << 4)
120 #define GC_DISPLAY_CLOCK_MASK (7 << 4)
121 +#define GM45_GC_RENDER_CLOCK_MASK (0xf << 0)
122 +#define GM45_GC_RENDER_CLOCK_266_MHZ (8 << 0)
123 +#define GM45_GC_RENDER_CLOCK_320_MHZ (9 << 0)
124 +#define GM45_GC_RENDER_CLOCK_400_MHZ (0xb << 0)
125 +#define GM45_GC_RENDER_CLOCK_533_MHZ (0xc << 0)
126 +#define I965_GC_RENDER_CLOCK_MASK (0xf << 0)
127 +#define I965_GC_RENDER_CLOCK_267_MHZ (2 << 0)
128 +#define I965_GC_RENDER_CLOCK_333_MHZ (3 << 0)
129 +#define I965_GC_RENDER_CLOCK_444_MHZ (4 << 0)
130 +#define I965_GC_RENDER_CLOCK_533_MHZ (5 << 0)
131 +#define I945_GC_RENDER_CLOCK_MASK (7 << 0)
132 +#define I945_GC_RENDER_CLOCK_166_MHZ (0 << 0)
133 +#define I945_GC_RENDER_CLOCK_200_MHZ (1 << 0)
134 +#define I945_GC_RENDER_CLOCK_250_MHZ (3 << 0)
135 +#define I945_GC_RENDER_CLOCK_400_MHZ (5 << 0)
136 +#define I915_GC_RENDER_CLOCK_MASK (7 << 0)
137 +#define I915_GC_RENDER_CLOCK_166_MHZ (0 << 0)
138 +#define I915_GC_RENDER_CLOCK_200_MHZ (1 << 0)
139 +#define I915_GC_RENDER_CLOCK_333_MHZ (4 << 0)
140 #define LBB 0xf4
141
142 /* VGA stuff */
143 @@ -1586,6 +1605,7 @@
144 #define PIPECONF_PROGRESSIVE (0 << 21)
145 #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
146 #define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
147 +#define PIPECONF_CXSR_DOWNCLOCK (1<<16)
148 #define PIPEASTAT 0x70024
149 #define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31)
150 #define PIPE_CRC_ERROR_ENABLE (1UL<<29)
151 diff -up linux-2.6.30.noarch/drivers/gpu/drm/i915/intel_display.c.jx linux-2.6.30.noarch/drivers/gpu/drm/i915/intel_display.c
152 --- linux-2.6.30.noarch/drivers/gpu/drm/i915/intel_display.c.jx 2009-08-03 14:00:44.000000000 -0400
153 +++ linux-2.6.30.noarch/drivers/gpu/drm/i915/intel_display.c 2009-08-03 14:11:56.000000000 -0400
154 @@ -38,6 +38,7 @@
155
156 bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
157 static void intel_update_watermarks(struct drm_device *dev);
158 +static void intel_increase_pllclock(struct drm_crtc *crtc, int schedule);
159
160 typedef struct {
161 /* given values */
162 @@ -67,6 +68,8 @@ struct intel_limit {
163 intel_p2_t p2;
164 bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
165 int, int, intel_clock_t *);
166 + bool (* find_reduced_pll)(const intel_limit_t *, struct drm_crtc *,
167 + int, int, intel_clock_t *);
168 };
169
170 #define I8XX_DOT_MIN 25000
171 @@ -192,7 +195,7 @@ struct intel_limit {
172 #define G4X_P2_SINGLE_CHANNEL_LVDS_LIMIT 0
173
174 /*The parameter is for DUAL_CHANNEL_LVDS on G4x platform*/
175 -#define G4X_DOT_DUAL_CHANNEL_LVDS_MIN 80000
176 +#define G4X_DOT_DUAL_CHANNEL_LVDS_MIN 10000
177 #define G4X_DOT_DUAL_CHANNEL_LVDS_MAX 224000
178 #define G4X_N_DUAL_CHANNEL_LVDS_MIN 1
179 #define G4X_N_DUAL_CHANNEL_LVDS_MAX 3
180 @@ -261,6 +264,9 @@ static bool
181 intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
182 int target, int refclk, intel_clock_t *best_clock);
183 static bool
184 +intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
185 + int target, int refclk, intel_clock_t *best_clock);
186 +static bool
187 intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
188 int target, int refclk, intel_clock_t *best_clock);
189 static bool
190 @@ -286,6 +292,7 @@ static const intel_limit_t intel_limits_
191 .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
192 .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST },
193 .find_pll = intel_find_best_PLL,
194 + .find_reduced_pll = intel_find_best_reduced_PLL,
195 };
196
197 static const intel_limit_t intel_limits_i8xx_lvds = {
198 @@ -300,6 +307,7 @@ static const intel_limit_t intel_limits_
199 .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
200 .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST },
201 .find_pll = intel_find_best_PLL,
202 + .find_reduced_pll = intel_find_best_reduced_PLL,
203 };
204
205 static const intel_limit_t intel_limits_i9xx_sdvo = {
206 @@ -314,6 +322,7 @@ static const intel_limit_t intel_limits_
207 .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
208 .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
209 .find_pll = intel_find_best_PLL,
210 + .find_reduced_pll = intel_find_best_reduced_PLL,
211 };
212
213 static const intel_limit_t intel_limits_i9xx_lvds = {
214 @@ -331,6 +340,7 @@ static const intel_limit_t intel_limits_
215 .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
216 .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST },
217 .find_pll = intel_find_best_PLL,
218 + .find_reduced_pll = intel_find_best_reduced_PLL,
219 };
220
221 /* below parameter and function is for G4X Chipset Family*/
222 @@ -348,6 +358,7 @@ static const intel_limit_t intel_limits_
223 .p2_fast = G4X_P2_SDVO_FAST
224 },
225 .find_pll = intel_g4x_find_best_PLL,
226 + .find_reduced_pll = intel_g4x_find_best_PLL,
227 };
228
229 static const intel_limit_t intel_limits_g4x_hdmi = {
230 @@ -364,6 +375,7 @@ static const intel_limit_t intel_limits_
231 .p2_fast = G4X_P2_HDMI_DAC_FAST
232 },
233 .find_pll = intel_g4x_find_best_PLL,
234 + .find_reduced_pll = intel_g4x_find_best_PLL,
235 };
236
237 static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
238 @@ -388,6 +400,7 @@ static const intel_limit_t intel_limits_
239 .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST
240 },
241 .find_pll = intel_g4x_find_best_PLL,
242 + .find_reduced_pll = intel_g4x_find_best_PLL,
243 };
244
245 static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
246 @@ -412,6 +425,7 @@ static const intel_limit_t intel_limits_
247 .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST
248 },
249 .find_pll = intel_g4x_find_best_PLL,
250 + .find_reduced_pll = intel_g4x_find_best_PLL,
251 };
252
253 static const intel_limit_t intel_limits_g4x_display_port = {
254 @@ -449,6 +463,7 @@ static const intel_limit_t intel_limits_
255 .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
256 .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
257 .find_pll = intel_find_best_PLL,
258 + .find_reduced_pll = intel_find_best_reduced_PLL,
259 };
260
261 static const intel_limit_t intel_limits_igd_lvds = {
262 @@ -464,6 +479,7 @@ static const intel_limit_t intel_limits_
263 .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
264 .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW },
265 .find_pll = intel_find_best_PLL,
266 + .find_reduced_pll = intel_find_best_reduced_PLL,
267 };
268
269 static const intel_limit_t intel_limits_igdng_sdvo = {
270 @@ -688,15 +704,16 @@ intel_find_best_PLL(const intel_limit_t
271
272 memset (best_clock, 0, sizeof (*best_clock));
273
274 - for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
275 - for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) {
276 - /* m1 is always 0 in IGD */
277 - if (clock.m2 >= clock.m1 && !IS_IGD(dev))
278 - break;
279 - for (clock.n = limit->n.min; clock.n <= limit->n.max;
280 - clock.n++) {
281 - for (clock.p1 = limit->p1.min;
282 - clock.p1 <= limit->p1.max; clock.p1++) {
283 + for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
284 + for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
285 + clock.m1++) {
286 + for (clock.m2 = limit->m2.min;
287 + clock.m2 <= limit->m2.max; clock.m2++) {
288 + /* m1 is always 0 in IGD */
289 + if (clock.m2 >= clock.m1 && !IS_IGD(dev))
290 + break;
291 + for (clock.n = limit->n.min;
292 + clock.n <= limit->n.max; clock.n++) {
293 int this_err;
294
295 intel_clock(dev, refclk, &clock);
296 @@ -717,6 +734,46 @@ intel_find_best_PLL(const intel_limit_t
297 return (err != target);
298 }
299
300 +
301 +static bool
302 +intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
303 + int target, int refclk, intel_clock_t *best_clock)
304 +
305 +{
306 + struct drm_device *dev = crtc->dev;
307 + intel_clock_t clock;
308 + int err = target;
309 + bool found = false;
310 +
311 + memcpy(&clock, best_clock, sizeof(intel_clock_t));
312 +
313 + for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
314 + for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) {
315 + /* m1 is always 0 in IGD */
316 + if (clock.m2 >= clock.m1 && !IS_IGD(dev))
317 + break;
318 + for (clock.n = limit->n.min; clock.n <= limit->n.max;
319 + clock.n++) {
320 + int this_err;
321 +
322 + intel_clock(dev, refclk, &clock);
323 +
324 +// if (!intel_PLL_is_valid(crtc, &clock))
325 +// continue;
326 +
327 + this_err = abs(clock.dot - target);
328 + if (this_err < err) {
329 + *best_clock = clock;
330 + err = this_err;
331 + found = true;
332 + }
333 + }
334 + }
335 + }
336 +
337 + return found;
338 +}
339 +
340 static bool
341 intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
342 int target, int refclk, intel_clock_t *best_clock)
343 @@ -747,7 +804,7 @@ intel_g4x_find_best_PLL(const intel_limi
344 max_n = limit->n.max;
345 /* based on hardware requriment prefer smaller n to precision */
346 for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
347 - /* based on hardware requirment prefere larger m1,m2, p1 */
348 + /* based on hardware requirment prefere larger m1,m2, */
349 for (clock.m1 = limit->m1.max;
350 clock.m1 >= limit->m1.min; clock.m1--) {
351 for (clock.m2 = limit->m2.max;
352 @@ -757,8 +814,8 @@ intel_g4x_find_best_PLL(const intel_limi
353 int this_err;
354
355 intel_clock(dev, refclk, &clock);
356 - if (!intel_PLL_is_valid(crtc, &clock))
357 - continue;
358 +// if (!intel_PLL_is_valid(crtc, &clock))
359 +// continue;
360 this_err = abs(clock.dot - target) ;
361 if (this_err < err_most) {
362 *best_clock = clock;
363 @@ -832,15 +889,14 @@ intel_igdng_find_best_PLL(const intel_li
364
365 memset(best_clock, 0, sizeof(*best_clock));
366 max_n = limit->n.max;
367 - /* based on hardware requriment prefer smaller n to precision */
368 - for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
369 - /* based on hardware requirment prefere larger m1,m2, p1 */
370 - for (clock.m1 = limit->m1.max;
371 - clock.m1 >= limit->m1.min; clock.m1--) {
372 - for (clock.m2 = limit->m2.max;
373 - clock.m2 >= limit->m2.min; clock.m2--) {
374 - for (clock.p1 = limit->p1.max;
375 - clock.p1 >= limit->p1.min; clock.p1--) {
376 + for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
377 + /* based on hardware requriment prefer smaller n to precision */
378 + for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
379 + /* based on hardware requirment prefere larger m1,m2 */
380 + for (clock.m1 = limit->m1.max;
381 + clock.m1 >= limit->m1.min; clock.m1--) {
382 + for (clock.m2 = limit->m2.max;
383 + clock.m2 >= limit->m2.min; clock.m2--) {
384 int this_err;
385
386 intel_clock(dev, refclk, &clock);
387 @@ -1029,6 +1085,7 @@ intel_pipe_set_base(struct drm_crtc *crt
388 intel_wait_for_vblank(dev);
389 i915_gem_object_unpin(intel_fb->obj);
390 }
391 + intel_increase_pllclock(crtc, true);
392
393 if (!dev->primary->master)
394 return 0;
395 @@ -2036,6 +2093,18 @@ static int intel_get_fifo_size(struct dr
396 return size;
397 }
398
399 +static void g4x_update_wm(struct drm_device *dev)
400 +{
401 + struct drm_i915_private *dev_priv = dev->dev_private;
402 + u32 fw_blc_self = I915_READ(FW_BLC_SELF);
403 +
404 + if (i915_powersave)
405 + fw_blc_self |= FW_BLC_SELF_EN;
406 + else
407 + fw_blc_self &= ~FW_BLC_SELF_EN;
408 + I915_WRITE(FW_BLC_SELF, fw_blc_self);
409 +}
410 +
411 static void i965_update_wm(struct drm_device *dev)
412 {
413 struct drm_i915_private *dev_priv = dev->dev_private;
414 @@ -2087,7 +2156,7 @@ static void i9xx_update_wm(struct drm_de
415 cwm = 2;
416
417 /* Calc sr entries for one plane configs */
418 - if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
419 + if (HAS_FW_BLC(dev) && sr_hdisplay && (!planea_clock || !planeb_clock)) {
420 /* self-refresh has much higher latency */
421 const static int sr_latency_ns = 6000;
422
423 @@ -2102,8 +2171,7 @@ static void i9xx_update_wm(struct drm_de
424 srwm = total_size - sr_entries;
425 if (srwm < 0)
426 srwm = 1;
427 - if (IS_I9XX(dev))
428 - I915_WRITE(FW_BLC_SELF, (srwm & 0x3f));
429 + I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f));
430 }
431
432 DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
433 @@ -2177,9 +2245,6 @@ static void intel_update_watermarks(stru
434 unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
435 int enabled = 0, pixel_size = 0;
436
437 - if (DSPARB_HWCONTROL(dev))
438 - return;
439 -
440 /* Get the clock config from both planes */
441 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
442 intel_crtc = to_intel_crtc(crtc);
443 @@ -2212,7 +2277,9 @@ static void intel_update_watermarks(stru
444 else if (IS_IGD(dev))
445 igd_disable_cxsr(dev);
446
447 - if (IS_I965G(dev))
448 + if (IS_G4X(dev))
449 + g4x_update_wm(dev);
450 + else if (IS_I965G(dev))
451 i965_update_wm(dev);
452 else if (IS_I9XX(dev) || IS_MOBILE(dev))
453 i9xx_update_wm(dev, planea_clock, planeb_clock, sr_hdisplay,
454 @@ -2246,9 +2313,9 @@ static int intel_crtc_mode_set(struct dr
455 int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
456 int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
457 int refclk, num_outputs = 0;
458 - intel_clock_t clock;
459 - u32 dpll = 0, fp = 0, dspcntr, pipeconf;
460 - bool ok, is_sdvo = false, is_dvo = false;
461 + intel_clock_t clock, reduced_clock;
462 + u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf;
463 + bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
464 bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
465 bool is_edp = false;
466 struct drm_mode_config *mode_config = &dev->mode_config;
467 @@ -2331,6 +2398,14 @@ static int intel_crtc_mode_set(struct dr
468 return -EINVAL;
469 }
470
471 + if (limit->find_reduced_pll && is_lvds) {
472 + memcpy(&reduced_clock, &clock, sizeof(intel_clock_t));
473 + has_reduced_clock = limit->find_reduced_pll(limit, crtc,
474 + (adjusted_mode->clock*i915_lvdsscale/100),
475 + refclk,
476 + &reduced_clock);
477 + }
478 +
479 /* SDVO TV has fixed PLL values depend on its clock range,
480 this mirrors vbios setting. */
481 if (is_sdvo && is_tv) {
482 @@ -2376,10 +2451,17 @@ static int intel_crtc_mode_set(struct dr
483 link_bw, &m_n);
484 }
485
486 - if (IS_IGD(dev))
487 + if (IS_IGD(dev)) {
488 fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
489 - else
490 + if (has_reduced_clock)
491 + fp2 = (1 << reduced_clock.n) << 16 |
492 + reduced_clock.m1 << 8 | reduced_clock.m2;
493 + } else {
494 fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
495 + if (has_reduced_clock)
496 + fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
497 + reduced_clock.m2;
498 + }
499
500 if (!IS_IGDNG(dev))
501 dpll = DPLL_VGA_MODE_DIS;
502 @@ -2408,6 +2490,8 @@ static int intel_crtc_mode_set(struct dr
503 /* also FPA1 */
504 if (IS_IGDNG(dev))
505 dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
506 + if (IS_G4X(dev) && has_reduced_clock)
507 + dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
508 }
509 switch (clock.p2) {
510 case 5:
511 @@ -2534,9 +2618,25 @@ static int intel_crtc_mode_set(struct dr
512 }
513 if (is_dp)
514 intel_dp_set_m_n(crtc, mode, adjusted_mode);
515 +
516
517 if (!is_edp) {
518 I915_WRITE(fp_reg, fp);
519 + if (has_reduced_clock && i915_powersave && i915_lvdsclock) {
520 + I915_WRITE(fp_reg + 4, fp2);
521 + intel_crtc->lowfreq_avail = true;
522 + if (HAS_PIPE_CXSR(dev)) {
523 + DRM_DEBUG("enabling CxSR downclocking\n");
524 + pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
525 + }
526 + } else {
527 + I915_WRITE(fp_reg + 4, fp);
528 + intel_crtc->lowfreq_avail = false;
529 + if (HAS_PIPE_CXSR(dev)) {
530 + DRM_DEBUG("disabling CxSR downclocking\n");
531 + pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
532 + }
533 + }
534 I915_WRITE(dpll_reg, dpll);
535 I915_READ(dpll_reg);
536 /* Wait for the clocks to stabilize. */
537 @@ -2748,6 +2848,8 @@ fail_locked:
538 return ret;
539 }
540
541 +#define CRTC_IDLE_TIMEOUT 1000 /* ms */
542 +
543 static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
544 {
545 struct drm_device *dev = crtc->dev;
546 @@ -2757,6 +2859,12 @@ static int intel_crtc_cursor_move(struct
547 uint32_t temp = 0;
548 uint32_t adder;
549
550 + if (!intel_crtc->busy)
551 + intel_increase_pllclock(crtc, true);
552 + intel_crtc->busy = true;
553 + mod_timer(&intel_crtc->idle_timer, jiffies +
554 + msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
555 +
556 if (x < 0) {
557 temp |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
558 x = -x;
559 @@ -3054,6 +3162,286 @@ struct drm_display_mode *intel_crtc_mode
560 return mode;
561 }
562
563 +#define GPU_IDLE_TIMEOUT 500 /* ms */
564 +
565 +/* When this timer fires, we've been idle for awhile */
566 +static void intel_gpu_idle_timer(unsigned long arg)
567 +{
568 + struct drm_device *dev = (struct drm_device *)arg;
569 + drm_i915_private_t *dev_priv = dev->dev_private;
570 +
571 + DRM_DEBUG("idle timer fired, downclocking\n");
572 +
573 + dev_priv->busy = false;
574 +
575 + schedule_work(&dev_priv->idle_work);
576 +}
577 +
578 +void intel_increase_renderclock(struct drm_device *dev, int schedule)
579 +{
580 + drm_i915_private_t *dev_priv = dev->dev_private;
581 +
582 + if (!i915_renderclock)
583 + return;
584 +
585 + if (IS_G4X(dev) || IS_I9XX(dev)) {
586 + /* Up to maximum... */
587 + pci_write_config_word(dev->pdev, GCFGC, dev_priv->orig_clock);
588 + } else if (IS_I85X(dev)) {
589 + pci_write_config_word(dev->pdev, HPLLCC, dev_priv->orig_clock);
590 + }
591 + DRM_DEBUG("increasing render clock frequency\n");
592 +
593 + if (!schedule)
594 + return;
595 +
596 + /* Schedule downclock */
597 + mod_timer(&dev_priv->idle_timer, jiffies +
598 + msecs_to_jiffies(GPU_IDLE_TIMEOUT));
599 +}
600 +
601 +void intel_decrease_renderclock(struct drm_device *dev)
602 +{
603 + if (!i915_renderclock)
604 + return;
605 +
606 + if (IS_G4X(dev)) {
607 + u16 gcfgc;
608 +
609 + /* Adjust render clock... */
610 + pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
611 +
612 + /* Down to minimum... */
613 + gcfgc &= ~GM45_GC_RENDER_CLOCK_MASK;
614 + gcfgc |= GM45_GC_RENDER_CLOCK_266_MHZ;
615 +
616 + pci_write_config_word(dev->pdev, GCFGC, gcfgc);
617 + } else if (IS_I965G(dev)) {
618 + u16 gcfgc;
619 +
620 + /* Adjust render clock... */
621 + pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
622 +
623 + /* Down to minimum... */
624 + gcfgc &= ~I965_GC_RENDER_CLOCK_MASK;
625 + gcfgc |= I965_GC_RENDER_CLOCK_267_MHZ;
626 +
627 + pci_write_config_word(dev->pdev, GCFGC, gcfgc);
628 + } else if (IS_I945G(dev) || IS_I945GM(dev)) {
629 + u16 gcfgc;
630 +
631 + /* Adjust render clock... */
632 + pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
633 +
634 + /* Down to minimum... */
635 + gcfgc &= ~I945_GC_RENDER_CLOCK_MASK;
636 + gcfgc |= I945_GC_RENDER_CLOCK_166_MHZ;
637 +
638 + pci_write_config_word(dev->pdev, GCFGC, gcfgc);
639 + } else if (IS_I915G(dev) || IS_I915GM(dev)) {
640 + u16 gcfgc;
641 +
642 + /* Adjust render clock... */
643 + pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
644 +
645 + /* Down to minimum... */
646 + gcfgc &= ~I915_GC_RENDER_CLOCK_MASK;
647 + gcfgc |= I915_GC_RENDER_CLOCK_166_MHZ;
648 +
649 + pci_write_config_word(dev->pdev, GCFGC, gcfgc);
650 + } else if (IS_I85X(dev)) {
651 + u16 hpllcc;
652 +
653 + /* Adjust render clock... */
654 + pci_read_config_word(dev->pdev, HPLLCC, &hpllcc);
655 +
656 + /* Up to maximum... */
657 + hpllcc &= ~GC_CLOCK_CONTROL_MASK;
658 + hpllcc |= GC_CLOCK_133_200;
659 +
660 + pci_write_config_word(dev->pdev, HPLLCC, hpllcc);
661 + }
662 + DRM_DEBUG("decreasing render clock frequency\n");
663 +}
664 +
665 +/* Note that no increase function is needed for this - increase_renderclock()
666 + * will also rewrite these bits
667 + */
668 +void intel_decrease_displayclock(struct drm_device *dev)
669 +{
670 + if (!i915_displayclock)
671 + return;
672 +
673 + if (IS_I945G(dev) || IS_I945GM(dev) || IS_I915G(dev) ||
674 + IS_I915GM(dev)) {
675 + u16 gcfgc;
676 +
677 + /* Adjust render clock... */
678 + pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
679 +
680 + /* Down to minimum... */
681 + gcfgc &= ~0xf0;
682 + gcfgc |= 0x80;
683 +
684 + pci_write_config_word(dev->pdev, GCFGC, gcfgc);
685 + }
686 +}
687 +
688 +static void intel_crtc_idle_timer(unsigned long arg)
689 +{
690 + struct intel_crtc *intel_crtc = (struct intel_crtc *)arg;
691 + struct drm_crtc *crtc = &intel_crtc->base;
692 + drm_i915_private_t *dev_priv = crtc->dev->dev_private;
693 +
694 + DRM_DEBUG("idle timer fired, downclocking\n");
695 +
696 + intel_crtc->busy = false;
697 +
698 + schedule_work(&dev_priv->idle_work);
699 +}
700 +
701 +static void intel_increase_pllclock(struct drm_crtc *crtc, int schedule)
702 +{
703 + struct drm_device *dev = crtc->dev;
704 + drm_i915_private_t *dev_priv = dev->dev_private;
705 + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
706 + int pipe = intel_crtc->pipe;
707 + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
708 + int dpll = I915_READ(dpll_reg);
709 +
710 + if (!i915_lvdsclock)
711 + return;
712 +
713 + if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
714 + DRM_DEBUG("upclocking LVDS\n");
715 +
716 + I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
717 + I915_WRITE(dpll_reg, dpll & ~DISPLAY_RATE_SELECT_FPA1);
718 + dpll = I915_READ(dpll_reg);
719 + intel_wait_for_vblank(dev);
720 + dpll = I915_READ(dpll_reg);
721 + if (dpll & DISPLAY_RATE_SELECT_FPA1)
722 + DRM_DEBUG("failed to upclock LVDS!\n");
723 + I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
724 + }
725 +
726 + if (!schedule)
727 + return;
728 +
729 + /* Schedule downclock */
730 + mod_timer(&intel_crtc->idle_timer, jiffies +
731 + msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
732 +}
733 +
734 +static void intel_decrease_pllclock(struct drm_crtc *crtc)
735 +{
736 + struct drm_device *dev = crtc->dev;
737 + drm_i915_private_t *dev_priv = dev->dev_private;
738 + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
739 + int pipe = intel_crtc->pipe;
740 + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
741 + int dpll = I915_READ(dpll_reg);
742 +
743 + if (!i915_lvdsclock)
744 + return;
745 +
746 + /*
747 + * Since this is called by a timer, we should never get here in
748 + * the manual case.
749 + */
750 + if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
751 + DRM_DEBUG("downclocking LVDS\n");
752 + I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
753 +
754 + dpll |= DISPLAY_RATE_SELECT_FPA1;
755 + I915_WRITE(dpll_reg, dpll);
756 + dpll = I915_READ(dpll_reg);
757 + intel_wait_for_vblank(dev);
758 + dpll = I915_READ(dpll_reg);
759 + if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
760 + DRM_DEBUG("failed to downclock LVDS!\n");
761 + I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
762 + }
763 +
764 +}
765 +
766 +/**
767 + * intel_idle_update - adjust clocks for idleness
768 + * @work: work struct
769 + *
770 + * Either the GPU or display (or both) went idle. Check the busy status
771 + * here and adjust the CRTC and GPU clocks as necessary.
772 + */
773 +static void intel_idle_update(struct work_struct *work)
774 +{
775 + drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
776 + idle_work);
777 + struct drm_device *dev = dev_priv->dev;
778 + struct drm_crtc *crtc;
779 + struct intel_crtc *intel_crtc;
780 +
781 + if (!i915_powersave)
782 + return;
783 +
784 + mutex_lock(&dev->struct_mutex);
785 +
786 + /* GPU isn't processing, downclock it. */
787 + if (!dev_priv->busy) {
788 + intel_decrease_renderclock(dev);
789 + intel_decrease_displayclock(dev);
790 + }
791 +
792 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
793 + /* Skip inactive CRTCs */
794 + if (!crtc->fb)
795 + continue;
796 +
797 + intel_crtc = to_intel_crtc(crtc);
798 + if (!intel_crtc->busy)
799 + intel_decrease_pllclock(crtc);
800 + }
801 +
802 + mutex_unlock(&dev->struct_mutex);
803 +}
804 +
805 +/**
806 + * intel_mark_busy - mark the GPU and possibly the display busy
807 + * @dev: drm device
808 + * @obj: object we're operating on
809 + *
810 + * Callers can use this function to indicate that the GPU is busy processing
811 + * commands. If @obj matches one of the CRTC objects (i.e. it's a scanout
812 + * buffer), we'll also mark the display as busy, so we know to increase its
813 + * clock frequency.
814 + */
815 +void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
816 +{
817 + drm_i915_private_t *dev_priv = dev->dev_private;
818 + struct drm_crtc *crtc = NULL;
819 + struct intel_framebuffer *intel_fb;
820 + struct intel_crtc *intel_crtc;
821 +
822 + dev_priv->busy = true;
823 + intel_increase_renderclock(dev, true);
824 +
825 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
826 + if (!crtc->fb)
827 + continue;
828 +
829 + intel_crtc = to_intel_crtc(crtc);
830 + intel_fb = to_intel_framebuffer(crtc->fb);
831 + if (intel_fb->obj == obj) {
832 + if (!intel_crtc->busy)
833 + intel_increase_pllclock(crtc, true);
834 + intel_crtc->busy = true;
835 + mod_timer(&intel_crtc->idle_timer, jiffies +
836 + msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
837 + }
838 + }
839 +
840 +
841 +}
842 +
843 static void intel_crtc_destroy(struct drm_crtc *crtc)
844 {
845 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
846 @@ -3110,6 +3498,10 @@ static void intel_crtc_init(struct drm_d
847 intel_crtc->mode_set.crtc = &intel_crtc->base;
848 intel_crtc->mode_set.connectors = (struct drm_connector **)(intel_crtc + 1);
849 intel_crtc->mode_set.num_connectors = 0;
850 + intel_crtc->busy = false;
851 +
852 + setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
853 + (unsigned long)intel_crtc);
854
855 if (i915_fbpercrtc) {
856
857 @@ -3399,6 +3791,7 @@ static const struct drm_mode_config_func
858
859 void intel_modeset_init(struct drm_device *dev)
860 {
861 + struct drm_i915_private *dev_priv = dev->dev_private;
862 int num_pipe;
863 int i;
864
865 @@ -3433,15 +3826,38 @@ void intel_modeset_init(struct drm_devic
866 DRM_DEBUG("%d display pipe%s available.\n",
867 num_pipe, num_pipe > 1 ? "s" : "");
868
869 + if (IS_I85X(dev))
870 + pci_read_config_word(dev->pdev, HPLLCC, &dev_priv->orig_clock);
871 + else if (IS_I9XX(dev) || IS_G4X(dev))
872 + pci_read_config_word(dev->pdev, GCFGC, &dev_priv->orig_clock);
873 +
874 for (i = 0; i < num_pipe; i++) {
875 intel_crtc_init(dev, i);
876 }
877
878 intel_setup_outputs(dev);
879 +
880 + INIT_WORK(&dev_priv->idle_work, intel_idle_update);
881 + setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
882 + (unsigned long)dev);
883 }
884
885 void intel_modeset_cleanup(struct drm_device *dev)
886 {
887 + struct drm_i915_private *dev_priv = dev->dev_private;
888 +
889 + /* Clean up up/down clocking */
890 + if (!HAS_PIPE_CXSR(dev)) {
891 + u32 dpll_b = I915_READ(DPLL_B);
892 +
893 + del_timer_sync(&dev_priv->idle_timer);
894 + dpll_b &= ~DISPLAY_RATE_SELECT_FPA1;
895 + I915_WRITE(DPLL_B, dpll_b);
896 + POSTING_READ(DPLL_B);
897 + intel_wait_for_vblank(dev);
898 + }
899 +
900 + intel_increase_renderclock(dev, false);
901 drm_mode_config_cleanup(dev);
902 }
903
904 diff -up linux-2.6.30.noarch/drivers/gpu/drm/i915/intel_drv.h.jx linux-2.6.30.noarch/drivers/gpu/drm/i915/intel_drv.h
905 --- linux-2.6.30.noarch/drivers/gpu/drm/i915/intel_drv.h.jx 2009-08-03 14:00:44.000000000 -0400
906 +++ linux-2.6.30.noarch/drivers/gpu/drm/i915/intel_drv.h 2009-08-03 14:01:07.000000000 -0400
907 @@ -99,6 +99,9 @@ struct intel_crtc {
908 struct intel_framebuffer *fbdev_fb;
909 /* a mode_set for fbdev users on this crtc */
910 struct drm_mode_set mode_set;
911 + bool busy; /* is scanout buffer being updated frequently? */
912 + struct timer_list idle_timer;
913 + bool lowfreq_avail;
914 };
915
916 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
917 @@ -117,6 +120,7 @@ extern void intel_hdmi_init(struct drm_d
918 extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
919 extern void intel_dvo_init(struct drm_device *dev);
920 extern void intel_tv_init(struct drm_device *dev);
921 +extern void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj);
922 extern void intel_lvds_init(struct drm_device *dev);
923 extern void intel_dp_init(struct drm_device *dev, int dp_reg);
924 void

admin@fedoraproject.org
ViewVC Help
Powered by ViewVC 1.1.2