blob: 0b7c5e5193efc0d97eca4bc5d4f3dfbb516bbe2d [file] [log] [blame]
Ville Syrjälä4d2577e2014-12-10 21:17:36 +02001/*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25#include <unistd.h>
26#include <stdlib.h>
27#include <stdio.h>
28#include <stdbool.h>
29#include <err.h>
30#include <string.h>
31#include "intel_io.h"
32#include "intel_chipset.h"
33
34static uint32_t display_base;
35static uint32_t devid;
36
37#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
38
39static uint32_t read_reg(uint32_t addr)
40{
Jani Nikulafb1515c2015-04-15 15:50:19 +030041 return INREG(display_base + addr);
Ville Syrjälä4d2577e2014-12-10 21:17:36 +020042}
43
44struct gmch_wm {
45 int wm, wm1, dl, fifo, fbc, burst;
46 bool dl_prec, valid;
47};
48
49enum plane {
50 PRI_HPLL_SR,
51 CUR_HPLL_SR,
52 PRI_SR,
53 CUR_SR,
54 PRI_A,
55 CUR_A,
56 SPR_A,
57 SPR_B,
58 PRI_B,
59 CUR_B,
60 SPR_C,
61 SPR_D,
62 PRI_C,
63 CUR_C,
64 SPR_E,
65 SPR_F,
66 MAX_PLANE,
67};
68
69#define NAME(x) [x] = #x
70
71static const char * const plane_name[] = {
72 NAME(PRI_HPLL_SR),
73 NAME(CUR_HPLL_SR),
74 NAME(PRI_SR),
75 NAME(CUR_SR),
76 NAME(PRI_A),
77 NAME(CUR_A),
78 NAME(SPR_A),
79 NAME(SPR_B),
80 NAME(PRI_B),
81 NAME(CUR_B),
82 NAME(SPR_C),
83 NAME(SPR_D),
84 NAME(PRI_C),
85 NAME(CUR_C),
86 NAME(SPR_E),
87 NAME(SPR_F),
88};
89
90struct ilk_wm_level {
91 int primary, sprite, cursor, latency, fbc;
92 bool enabled, sprite_enabled;
93 bool primary_trickle_feed_dis, sprite_trickle_feed_dis;
94};
95
96struct ilk_wm {
97 struct ilk_wm_level pipe[3];
98 struct ilk_wm_level lp[3];
99};
100
101#define MASK(size) ((1 << (size)) - 1)
102
103#define REG_DECODE1(x, shift, size) \
104 (((x) >> (shift)) & MASK(size))
105
106#define REG_DECODE2(lo, shift_lo, size_lo, hi, shift_hi, size_hi) \
107 ((((lo) >> (shift_lo)) & MASK(size_lo)) | \
108 ((((hi) >> (shift_hi)) & MASK(size_hi)) << (size_lo)))
109
110static const char pipe_name(int pipe)
111{
112 return 'A' + pipe;
113}
114
115static const char *endis(bool enabled)
116{
117 return enabled ? "enabled" : "disabled";
118}
119
120static int is_gen7_plus(uint32_t d)
121{
122 return !(IS_GEN5(d) || IS_GEN6(d));
123}
124
125static int is_hsw_plus(uint32_t d)
126{
127 return !(IS_GEN5(d) || IS_GEN6(d) || IS_IVYBRIDGE(d));
128}
129
130static void ilk_wm_dump(void)
131{
132 int i;
133 uint32_t dspcntr[3];
134 uint32_t spcntr[3];
135 uint32_t wm_pipe[3];
136 uint32_t wm_lp[3];
137 uint32_t wm_lp_spr[3];
138 uint32_t arb_ctl, arb_ctl2, wm_misc = 0;
139 int num_pipes = is_gen7_plus(devid) ? 3 : 2;
140 struct ilk_wm wm = {};
141
142 intel_register_access_init(intel_get_pci_device(), 0);
143
144 for (i = 0; i < num_pipes; i++) {
145 dspcntr[i] = read_reg(0x70180 + i * 0x1000);
146 if (is_gen7_plus(devid))
147 spcntr[i] = read_reg(0x70280 + i * 0x1000);
148 else
149 spcntr[i] = read_reg(0x72180 + i * 0x1000);
150 }
151
152 wm_pipe[0] = read_reg(0x45100);
153 wm_pipe[1] = read_reg(0x45104);
154 if (num_pipes == 3)
155 wm_pipe[2] = read_reg(0x45200);
156 wm_lp[0] = read_reg(0x45108);
157 wm_lp[1] = read_reg(0x4510c);
158 wm_lp[2] = read_reg(0x45110);
159
160 wm_lp_spr[0] = read_reg(0x45120);
161 if (is_gen7_plus(devid)) {
162 wm_lp_spr[1] = read_reg(0x45124);
163 wm_lp_spr[2] = read_reg(0x45128);
164 }
165
166 arb_ctl = read_reg(0x45000);
167 arb_ctl2 = read_reg(0x45004);
168 if (is_hsw_plus(devid))
169 wm_misc = read_reg(0x45260);
170
171 intel_register_access_fini();
172
173 for (i = 0; i < num_pipes; i++)
174 printf(" WM_PIPE_%c = 0x%08x\n", pipe_name(i), wm_pipe[i]);
175 printf(" WM_LP1 = 0x%08x\n", wm_lp[0]);
176 printf(" WM_LP2 = 0x%08x\n", wm_lp[1]);
177 printf(" WM_LP3 = 0x%08x\n", wm_lp[2]);
178 printf(" WM_LP1_SPR = 0x%08x\n", wm_lp_spr[0]);
179 if (is_gen7_plus(devid)) {
180 printf(" WM_LP2_SPR = 0x%08x\n", wm_lp_spr[1]);
181 printf(" WM_LP3_SPR = 0x%08x\n", wm_lp_spr[2]);
182 }
183 printf(" ARB_CTL = 0x%08x\n", arb_ctl);
184 printf(" ARB_CTL2 = 0x%08x\n", arb_ctl2);
185 if (is_hsw_plus(devid))
186 printf(" WM_MISC = 0x%08x\n", wm_misc);
187
188 for (i = 0 ; i < num_pipes; i++) {
189 wm.pipe[i].primary = REG_DECODE1(wm_pipe[i], 16, 8);
190 wm.pipe[i].sprite = REG_DECODE1(wm_pipe[i], 8, 8);
191 wm.pipe[i].cursor = REG_DECODE1(wm_pipe[i], 0, 6);
192
193 wm.pipe[i].primary_trickle_feed_dis =
194 REG_DECODE1(dspcntr[i], 14, 1);
195 if (!IS_GEN5(devid))
196 wm.pipe[i].sprite_trickle_feed_dis =
197 REG_DECODE1(spcntr[i], 14, 1);
198 }
199
200 for (i = 0; i < 3; i++) {
201 wm.lp[i].enabled = REG_DECODE1(wm_lp[i], 31, 1);
202 wm.lp[i].latency = REG_DECODE1(wm_lp[i], 24, 7);
203 if (IS_GEN8(devid))
204 wm.lp[i].fbc = REG_DECODE1(wm_lp[i], 19, 5);
205 else
206 wm.lp[i].fbc = REG_DECODE1(wm_lp[i], 20, 4);
207 wm.lp[i].primary = REG_DECODE1(wm_lp[i], 8, 11);
208 wm.lp[i].cursor = REG_DECODE1(wm_lp[i], 0, 8);
209
210 if (i == 0 || is_gen7_plus(devid)) {
211 if (!is_gen7_plus(devid))
212 wm.lp[i].sprite_enabled = REG_DECODE1(wm_lp_spr[i], 31, 1);
213 wm.lp[i].sprite = REG_DECODE1(wm_lp_spr[i], 0, 11);
214 }
215 }
216
217 for (i = 0; i < num_pipes; i++) {
218 printf("WM_PIPE_%c: primary=%d, cursor=%d, sprite=%d\n",
219 pipe_name(i), wm.pipe[i].primary, wm.pipe[i].cursor, wm.pipe[i].sprite);
220 }
221 if (is_gen7_plus(devid)) {
222 for (i = 0; i < 3; i++) {
223 printf("WM_LP%d: %s, latency=%d, fbc=%d, primary=%d, cursor=%d, sprite=%d\n",
224 i + 1, endis(wm.lp[i].enabled), wm.lp[i].latency, wm.lp[i].fbc,
225 wm.lp[i].primary, wm.lp[i].cursor, wm.lp[i].sprite);
226 }
227 } else {
228 i = 0;
229 printf("WM_LP%d: %s, latency=%d, fbc=%d, primary=%d, cursor=%d, sprite=%d (%s)\n",
230 i + 1, endis(wm.lp[i].enabled), wm.lp[i].latency, wm.lp[i].fbc,
231 wm.lp[i].primary, wm.lp[i].cursor, wm.lp[i].sprite,
232 endis(wm.lp[i].sprite_enabled));
233 for (i = 1; i < 3; i++) {
234 printf("WM_LP%d: %s, latency=%d, fbc=%d, primary=%d, cursor=%d\n",
235 i + 1, endis(wm.lp[i].enabled), wm.lp[i].latency, wm.lp[i].fbc,
236 wm.lp[i].primary, wm.lp[i].cursor);
237 }
238 }
239 for (i = 0; i < num_pipes; i++) {
240 printf("Primary %c trickle feed = %s\n",
241 pipe_name(i), endis(!wm.pipe[i].primary_trickle_feed_dis));
242 if (!IS_GEN5(devid))
243 printf("Sprite %c trickle feed = %s\n",
244 pipe_name(i), endis(!wm.pipe[i].sprite_trickle_feed_dis));
245 }
246 if (is_hsw_plus(devid)) {
247 printf("DDB partitioning = %s\n",
248 REG_DECODE1(wm_misc, 0, 1) ? "5/6" : "1/2");
249 } else if (is_gen7_plus(devid)) {
250 printf("DDB partitioning = %s\n",
251 REG_DECODE1(arb_ctl2, 6, 1) ? "5/6" : "1/2");
252 }
253 printf("FBC watermark = %s\n",
254 endis(!REG_DECODE1(arb_ctl, 15, 1)));
255}
256
257static void vlv_wm_dump(void)
258{
259 int i;
260 unsigned int num_pipes = IS_CHERRYVIEW(devid) ? 3 : 2;
261 uint32_t dsparb, dsparb2, dsparb3;
262 uint32_t fw1, fw2, fw3, fw4, fw5, fw6, fw7, fw8, fw9, howm, howm1;
263 uint32_t ddl1, ddl2, ddl3;
264 uint32_t fw_blc_self, mi_arb,cbr1;
265 uint32_t dsp_ss_pm, ddr_setup2;
266 struct gmch_wm wms[MAX_PLANE] = {};
267
268 intel_register_access_init(intel_get_pci_device(), 0);
269
270 dsparb = read_reg(0x70030);
271 dsparb2 = read_reg(0x70060);
272
273 fw1 = read_reg(0x70034);
274 fw2 = read_reg(0x70038);
275 fw3 = read_reg(0x7003c);
276 fw4 = read_reg(0x70070);
277 fw5 = read_reg(0x70074);
278 fw6 = read_reg(0x70078);
279
280 howm = read_reg(0x70064);
281 howm1 = read_reg(0x70068);
282
283 ddl1 = read_reg(0x70050);
284 ddl2 = read_reg(0x70054);
285
286 fw_blc_self = read_reg(0x6500);
287 mi_arb = read_reg(0x6504);
288 cbr1 = read_reg(0x70400);
289
290 if (IS_CHERRYVIEW(devid)) {
291 dsparb3 = read_reg(0x7006c);
292
293 fw7 = read_reg(0x700b4);
294 fw8 = read_reg(0x700b8);
295 fw9 = read_reg(0x7007c);
296
297 ddl3 = read_reg(0x70058);
298
299 intel_punit_read(0x36, &dsp_ss_pm);
300 intel_punit_read(0x139, &ddr_setup2);
301 } else {
302 fw7 = read_reg(0x7007c);
303 }
304
305 intel_register_access_fini();
306
307 printf(" FW1 = 0x%08x\n", fw1);
308 printf(" FW2 = 0x%08x\n", fw2);
309 printf(" FW3 = 0x%08x\n", fw3);
310 printf(" FW4 = 0x%08x\n", fw4);
311 printf(" FW5 = 0x%08x\n", fw5);
312 printf(" FW6 = 0x%08x\n", fw6);
313 printf(" FW7 = 0x%08x\n", fw7);
314 if (IS_CHERRYVIEW(devid)) {
315 printf(" FW8 = 0x%08x\n", fw8);
316 printf(" FW9 = 0x%08x\n", fw9);
317 }
318 printf(" HOWM = 0x%08x\n", howm);
319 printf(" HOWM1 = 0x%08x\n", howm1);
320 printf(" DDL1 = 0x%08x\n", ddl1);
321 printf(" DDL2 = 0x%08x\n", ddl2);
322 if (IS_CHERRYVIEW(devid))
323 printf(" DDL3 = 0x%08x\n", ddl3);
324 printf(" DSPARB = 0x%08x\n", dsparb);
325 printf(" DSPARB2 = 0x%08x\n", dsparb2);
326 if (IS_CHERRYVIEW(devid))
327 printf(" DSPARB3 = 0x%08x\n", dsparb3);
328 printf("FW_BLC_SELF = 0x%08x\n", fw_blc_self);
329 printf(" MI_ARB = 0x%08x\n", mi_arb);
330 printf(" CBR1 = 0x%08x\n", cbr1);
331 if (IS_CHERRYVIEW(devid)) {
332 printf(" DSP_SS_PM = 0x%08x\n", dsp_ss_pm);
333 printf(" DDR_SETUP2 = 0x%08x\n", ddr_setup2);
334 }
335
336 wms[PRI_A].valid = true;
337 wms[PRI_B].valid = true;
338 wms[CUR_A].valid = true;
339 wms[CUR_B].valid = true;
340 wms[SPR_A].valid = true;
341 wms[SPR_B].valid = true;
342 wms[SPR_C].valid = true;
343 wms[SPR_D].valid = true;
344 wms[PRI_SR].valid = true;
345 wms[CUR_SR].valid = true;
346
347 if (IS_CHERRYVIEW(devid)) {
348 wms[PRI_C].valid = true;
349 wms[CUR_C].valid = true;
350 wms[SPR_E].valid = true;
351 wms[SPR_F].valid = true;
352 }
353
354 wms[PRI_A].fifo = REG_DECODE2(dsparb, 0, 8, dsparb2, 0, 1) - 0;
355 wms[SPR_A].fifo = REG_DECODE2(dsparb, 8, 8, dsparb2, 4, 1) - wms[PRI_A].fifo;
356 wms[SPR_B].fifo = 512 - 1 - wms[SPR_A].fifo - wms[PRI_A].fifo;
357 wms[CUR_A].fifo = 0x3f;
358
359 wms[PRI_B].fifo = REG_DECODE2(dsparb, 16, 8, dsparb2, 8, 1) - 0;
360 wms[SPR_C].fifo = REG_DECODE2(dsparb, 24, 8, dsparb2, 12, 1) - wms[PRI_B].fifo;
361 wms[SPR_D].fifo = 512 - 1 - wms[SPR_C].fifo - wms[PRI_B].fifo;
362 wms[CUR_B].fifo = 0x3f;
363
364 if (IS_CHERRYVIEW(devid)) {
365 wms[PRI_C].fifo = REG_DECODE2(dsparb3, 0, 8, dsparb2, 16, 1) - 0;
366 wms[SPR_E].fifo = REG_DECODE2(dsparb3, 8, 8, dsparb2, 20, 1) - wms[PRI_C].fifo;
367 wms[SPR_F].fifo = 512 - 1 - wms[SPR_E].fifo - wms[PRI_C].fifo;
368 wms[CUR_C].fifo = 0x3f;
369 }
370
371 wms[PRI_SR].fifo = 512 * num_pipes - 1;
372 wms[CUR_SR].fifo = 0x3f;
373
374 wms[PRI_HPLL_SR].fifo = 512 * num_pipes - 1;
375 wms[CUR_HPLL_SR].fifo = 0x3f;
376
377 wms[PRI_A].wm = REG_DECODE2(fw1, 0, 8, howm, 0, 1);
378 wms[PRI_B].wm = REG_DECODE2(fw1, 8, 8, howm, 12, 1);
379 wms[CUR_B].wm = REG_DECODE1(fw1, 16, 6);
380 wms[PRI_SR].wm = REG_DECODE2(fw1, 23, 9, howm, 24, 2);
381
382 wms[SPR_A].wm = REG_DECODE2(fw2, 0, 8, howm, 4, 1);
383 wms[CUR_A].wm = REG_DECODE1(fw2, 8, 6);
384 wms[SPR_B].wm = REG_DECODE2(fw2, 16, 8, howm, 8, 1);
385
386 wms[CUR_SR].wm = REG_DECODE1(fw3, 24, 6);
387
388 wms[SPR_A].wm1 = REG_DECODE2(fw4, 0, 8, howm1, 4, 1);
389 wms[CUR_A].wm1 = REG_DECODE1(fw4, 8, 6);
390 wms[SPR_B].wm1 = REG_DECODE2(fw4, 16, 8, howm1, 8, 1);
391
392 wms[CUR_SR].wm1 = REG_DECODE1(fw5, 0, 6);
393 wms[CUR_B].wm1 = REG_DECODE1(fw5, 8, 6);
394 wms[PRI_A].wm1 = REG_DECODE2(fw5, 16, 8, howm1, 0, 1);
395 wms[PRI_B].wm1 = REG_DECODE2(fw5, 24, 8, howm1, 12, 1);
396
397 wms[PRI_SR].wm1 = REG_DECODE2(fw6, 0, 9, howm1, 24, 2);
398
399 wms[SPR_C].wm = REG_DECODE2(fw7, 0, 8, howm, 16, 1);
400 wms[SPR_C].wm1 = REG_DECODE2(fw7, 8, 8, howm1, 16, 1);
401 wms[SPR_D].wm = REG_DECODE2(fw7, 16, 8, howm, 20, 1);
402 wms[SPR_D].wm1 = REG_DECODE2(fw7, 24, 8, howm1, 20, 1);
403
404 if (IS_CHERRYVIEW(devid)) {
405 wms[SPR_E].wm = REG_DECODE2(fw8, 0, 8, howm, 22, 1);
406 wms[SPR_E].wm1 = REG_DECODE2(fw8, 8, 8, howm1, 22, 1);
407 wms[SPR_F].wm = REG_DECODE2(fw8, 16, 8, howm, 23, 1);
408 wms[SPR_F].wm1 = REG_DECODE2(fw8, 24, 8, howm1, 23, 1);
409
410 wms[CUR_C].wm = REG_DECODE1(fw9, 0, 6);
411 wms[CUR_C].wm1 = REG_DECODE1(fw9, 8, 6);
412 wms[PRI_C].wm = REG_DECODE2(fw9, 16, 8, howm, 21, 1);
413 wms[PRI_C].wm1 = REG_DECODE2(fw9, 24, 8, howm1, 21, 1);
414 }
415
416 wms[PRI_A].dl = REG_DECODE1(ddl1, 0, 7);
417 wms[SPR_A].dl = REG_DECODE1(ddl1, 8, 7);
418 wms[SPR_B].dl = REG_DECODE1(ddl1, 16, 7);
419 wms[CUR_A].dl = REG_DECODE1(ddl1, 24, 7);
420
421 wms[PRI_A].dl_prec = REG_DECODE1(ddl1, 7, 1);
422 wms[SPR_A].dl_prec = REG_DECODE1(ddl1, 15, 1);
423 wms[SPR_B].dl_prec = REG_DECODE1(ddl1, 23, 1);
424 wms[CUR_A].dl_prec = REG_DECODE1(ddl1, 31, 1);
425
426 wms[PRI_B].dl = REG_DECODE1(ddl2, 0, 7);
427 wms[SPR_C].dl = REG_DECODE1(ddl2, 8, 7);
428 wms[SPR_D].dl = REG_DECODE1(ddl2, 16, 7);
429 wms[CUR_B].dl = REG_DECODE1(ddl2, 24, 7);
430
431 wms[PRI_B].dl_prec = REG_DECODE1(ddl2, 7, 1);
432 wms[SPR_C].dl_prec = REG_DECODE1(ddl2, 15, 1);
433 wms[SPR_D].dl_prec = REG_DECODE1(ddl2, 23, 1);
434 wms[CUR_B].dl_prec = REG_DECODE1(ddl2, 31, 1);
435
436 if (IS_CHERRYVIEW(devid)) {
437 wms[PRI_C].dl = REG_DECODE1(ddl3, 0, 7);
438 wms[SPR_E].dl = REG_DECODE1(ddl3, 8, 7);
439 wms[SPR_F].dl = REG_DECODE1(ddl3, 16, 7);
440 wms[CUR_C].dl = REG_DECODE1(ddl3, 24, 7);
441
442 wms[PRI_C].dl_prec = REG_DECODE1(ddl3, 7, 1);
443 wms[SPR_E].dl_prec = REG_DECODE1(ddl3, 15, 1);
444 wms[SPR_F].dl_prec = REG_DECODE1(ddl3, 23, 1);
445 wms[CUR_C].dl_prec = REG_DECODE1(ddl3, 31, 1);
446 }
447
448 for (i = 0; i < ARRAY_SIZE(wms); i++) {
449 if (!wms[i].valid)
450 continue;
451 printf("%s: WM = %d, WM1 = %d, DDL = %d (prec=%d), FIFO = %d\n",
452 plane_name[i], wms[i].wm, wms[i].wm1, wms[i].dl, wms[i].dl_prec, wms[i].fifo);
453 }
454
455 printf("CxSR = %s\n",
456 endis(REG_DECODE1(fw_blc_self, 15, 1)));
457 printf("Trickle feed = %s\n",
458 endis(!REG_DECODE1(mi_arb, 2, 1)));
459 printf("PND deadline = %s\n",
460 endis(!REG_DECODE1(cbr1, 31, 1)));
461
462 if (IS_CHERRYVIEW(devid)) {
463 printf("PM5 = %s\n",
464 endis(REG_DECODE1(dsp_ss_pm, 6, 1)));
465 printf("PM5 state = %s\n",
466 endis(REG_DECODE1(dsp_ss_pm, 22, 1)));
467 printf("DDR force high frequency = %s\n",
468 endis(REG_DECODE1(ddr_setup2, 0, 1)));
469 printf("DDR force low frequency = %s\n",
470 endis(REG_DECODE1(ddr_setup2, 1, 1)));
471 }
472}
473
474static void g4x_wm_dump(void)
475{
476 int i;
477 uint32_t dspacntr, dspbcntr;
478 uint32_t dsparb;
479 uint32_t fw1, fw2, fw3;
480 uint32_t mi_display_power_down;
481 uint32_t mi_arb_state;
482 struct gmch_wm wms[MAX_PLANE] = {};
483
484 intel_register_access_init(intel_get_pci_device(), 0);
485
486 dspacntr = read_reg(0x70180);
487 dspbcntr = read_reg(0x71180);
488 dsparb = read_reg(0x70030);
489 fw1 = read_reg(0x70034);
490 fw2 = read_reg(0x70038);
491 fw3 = read_reg(0x7003c);
492 mi_display_power_down = read_reg(0x20e0);
493 mi_arb_state = read_reg(0x20e4);
494
495 intel_register_access_fini();
496
497 printf(" DSPACNTR = 0x%08x\n", dspacntr);
498 printf(" DSPBCNTR = 0x%08x\n", dspbcntr);
499 printf(" FW1 = 0x%08x\n", fw1);
500 printf(" FW2 = 0x%08x\n", fw2);
501 printf(" FW3 = 0x%08x\n", fw3);
502 printf(" DSPARB = 0x%08x\n", dsparb);
503 printf("MI_DISPLAY_POWER_DOWN = 0x%08x\n", mi_display_power_down);
504 printf(" MI_ARB_STATE = 0x%08x\n", mi_arb_state);
505
506 wms[PRI_A].valid = true;
507 wms[PRI_B].valid = true;
508 wms[CUR_A].valid = true;
509 wms[CUR_B].valid = true;
510 wms[SPR_A].valid = true;
511 wms[SPR_B].valid = true;
512 wms[PRI_SR].valid = true;
513 wms[CUR_SR].valid = true;
514 wms[PRI_HPLL_SR].valid = true;
515 wms[CUR_HPLL_SR].valid = true;
516
517 wms[PRI_A].fifo = REG_DECODE1(dsparb, 0, 7) - 0;
518 wms[PRI_B].fifo = REG_DECODE1(dsparb, 7, 7) - wms[PRI_A].fifo;
519
520 wms[PRI_A].wm = REG_DECODE1(fw1, 0, 7);
521 wms[PRI_B].wm = REG_DECODE1(fw1, 8, 7);
522 wms[CUR_B].wm = REG_DECODE1(fw1, 16, 6);
523 wms[PRI_SR].wm = REG_DECODE1(fw1, 23, 9);
524
525 wms[PRI_SR].fbc = REG_DECODE1(fw2, 0, 8);
526 wms[PRI_HPLL_SR].fbc = REG_DECODE1(fw2, 8, 6);
527
528 wms[SPR_B].wm = REG_DECODE1(fw2, 16, 7);
529 wms[CUR_A].wm = REG_DECODE1(fw2, 8, 6);
530 wms[SPR_A].wm = REG_DECODE1(fw2, 0, 7);
531
532 wms[CUR_SR].wm = REG_DECODE1(fw3, 24, 6);
533 wms[CUR_HPLL_SR].wm = REG_DECODE1(fw3, 16, 6);
534 wms[PRI_HPLL_SR].wm = REG_DECODE1(fw3, 0, 9);
535
536 for (i = 0; i < ARRAY_SIZE(wms); i++) {
537 if (!wms[i].valid)
538 continue;
539 printf("%s: WM = %d, FBC = %d, FIFO = %d\n",
540 plane_name[i], wms[i].wm, wms[i].fbc, wms[i].fifo);
541 }
542 printf("CxSR = %s\n",
543 endis(REG_DECODE1(mi_display_power_down, 15, 1)));
544 printf("HPLL SR = %s\n",
545 endis(REG_DECODE1(fw3, 31, 1)));
546 printf("FBC SR = %s\n",
547 endis(REG_DECODE1(fw2, 31, 1)));
548 printf("Display A trickle feed = %s\n",
549 endis(!REG_DECODE1(dspacntr, 14, 1)));
550 printf("Display B trickle feed = %s\n",
551 endis(!REG_DECODE1(dspbcntr, 14, 1)));
552 printf("Display A uses sprite data buffer = %s\n",
553 endis(!REG_DECODE1(dspacntr, 13, 1)));
554 printf("Display B uses sprite data buffer = %s\n",
555 endis(!REG_DECODE1(dspbcntr, 13, 1)));
556 printf("Primary display = %c\n",
557 REG_DECODE1(mi_arb_state, 0, 1) ? 'B' : 'A');
558}
559
560static void gen4_wm_dump(void)
561{
562 int i;
563 int totalsize = IS_CRESTLINE(devid) ? 128 : 96;
564 uint32_t dsparb;
565 uint32_t fw1, fw2, fw3;
566 uint32_t mi_display_power_down;
567 uint32_t mi_arb_state;
568 struct gmch_wm wms[MAX_PLANE] = {};
569
570 intel_register_access_init(intel_get_pci_device(), 0);
571
572 dsparb = read_reg(0x70030);
573 fw1 = read_reg(0x70034);
574 fw2 = read_reg(0x70038);
575 fw3 = read_reg(0x7003c);
576 mi_display_power_down = read_reg(0x20e0);
577 mi_arb_state = read_reg(0x20e4);
578
579 intel_register_access_fini();
580
581 printf(" FW1 = 0x%08x\n", fw1);
582 printf(" FW2 = 0x%08x\n", fw2);
583 printf(" FW3 = 0x%08x\n", fw3);
584 printf(" DSPARB = 0x%08x\n", dsparb);
585 printf("MI_DISPLAY_POWER_DOWN = 0x%08x\n", mi_display_power_down);
586 printf(" MI_ARB_STATE = 0x%08x\n", mi_arb_state);
587
588 wms[PRI_A].valid = true;
589 wms[PRI_B].valid = true;
590 wms[PRI_C].valid = true;
591 wms[CUR_A].valid = true;
592 wms[CUR_B].valid = true;
593 wms[PRI_SR].valid = true;
594 wms[CUR_SR].valid = true;
595 wms[PRI_HPLL_SR].valid = true;
596 wms[CUR_HPLL_SR].valid = true;
597
598 wms[PRI_A].fifo = REG_DECODE1(dsparb, 0, 7) - 0;
599 wms[PRI_B].fifo = REG_DECODE1(dsparb, 7, 7) - wms[PRI_A].fifo;
600 wms[PRI_C].fifo = totalsize - wms[PRI_B].fifo - wms[PRI_A].fifo - 1;
601
602 wms[PRI_A].wm = REG_DECODE1(fw1, 0, 7);
603 wms[PRI_B].wm = REG_DECODE1(fw1, 8, 7);
604 wms[CUR_B].wm = REG_DECODE1(fw1, 16, 6);
605 wms[PRI_SR].wm = REG_DECODE1(fw1, 23, 9);
606
607 wms[CUR_A].wm = REG_DECODE1(fw2, 8, 6);
608 wms[PRI_C].wm = REG_DECODE1(fw2, 0, 7);
609
610 wms[CUR_SR].wm = REG_DECODE1(fw3, 24, 6);
611 wms[CUR_HPLL_SR].wm = REG_DECODE1(fw3, 16, 6);
612 wms[PRI_HPLL_SR].wm = REG_DECODE1(fw3, 0, 9);
613
614 for (i = 0; i < ARRAY_SIZE(wms); i++) {
615 if (!wms[i].valid)
616 continue;
617 printf("%s: WM = %d, FIFO = %d\n",
618 plane_name[i], wms[i].wm, wms[i].fifo);
619 }
620 printf("CxSR = %s\n",
621 endis(REG_DECODE1(mi_display_power_down, 15, 1)));
622 printf("HPLL SR enable = %s\n",
623 endis(REG_DECODE1(fw3, 31, 1)));
624 printf("Trickle feed = %s\n",
625 endis(!REG_DECODE1(mi_arb_state, 2, 1)));
626 printf("Primary display = %c\n",
627 REG_DECODE1(mi_arb_state, 0, 1) + 'A');
628}
629
630static void pnv_wm_dump(void)
631{
632 int i;
633 int totalsize = 96; /* FIXME? */
634 uint32_t dsparb;
635 uint32_t fw1, fw2, fw3;
636 uint32_t mi_display_power_down;
637 uint32_t mi_arb_state;
638 uint32_t cbr;
639 struct gmch_wm wms[MAX_PLANE] = {};
640
641 intel_register_access_init(intel_get_pci_device(), 0);
642
643 dsparb = read_reg(0x70030);
644 fw1 = read_reg(0x70034);
645 fw2 = read_reg(0x70038);
646 fw3 = read_reg(0x7003c);
647 cbr = read_reg(0x70400);
648 mi_display_power_down = read_reg(0x20e0);
649 mi_arb_state = read_reg(0x20e4);
650
651 intel_register_access_fini();
652
653 printf(" DSPARB = 0x%08x\n", dsparb);
654 printf(" FW1 = 0x%08x\n", fw1);
655 printf(" FW2 = 0x%08x\n", fw2);
656 printf(" FW3 = 0x%08x\n", fw3);
657 printf(" CBR = 0x%08x\n", cbr);
658 printf("MI_DISPLAY_POWER_DOWN = 0x%08x\n", mi_display_power_down);
659 printf(" MI_ARB_STATE = 0x%08x\n", mi_arb_state);
660
661 wms[PRI_A].valid = true;
662 wms[PRI_B].valid = true;
663 wms[PRI_C].valid = true;
664 wms[CUR_A].valid = true;
665 wms[CUR_B].valid = true;
666 wms[PRI_SR].valid = true;
667 wms[CUR_SR].valid = true;
668 wms[PRI_HPLL_SR].valid = true;
669 wms[CUR_HPLL_SR].valid = true;
670
671 wms[PRI_A].fifo = REG_DECODE1(dsparb, 0, 7) - 0;
672 wms[PRI_B].fifo = REG_DECODE1(dsparb, 7, 7) - wms[PRI_A].fifo;
673 wms[PRI_C].fifo = totalsize - wms[PRI_B].fifo - wms[PRI_A].fifo - 1;
674
675 wms[PRI_A].wm = REG_DECODE1(fw1, 0, 7);
676 wms[PRI_B].wm = REG_DECODE1(fw1, 8, 7);
677 wms[CUR_B].wm = REG_DECODE1(fw1, 16, 6);
678 wms[PRI_SR].wm = REG_DECODE1(fw1, 23, 9);
679
680 wms[CUR_A].wm = REG_DECODE1(fw2, 8, 6);
681 wms[PRI_C].wm = REG_DECODE1(fw2, 0, 7);
682
683 switch ((REG_DECODE1(cbr, 30, 1) << 1) | REG_DECODE1(cbr, 25, 1)) {
684 case 3:
685 case 2:
686 wms[PRI_SR].fifo = 8 * 1024 / 64;
687 break;
688 case 1:
689 wms[PRI_SR].fifo = 16 * 1024 / 64;
690 break;
691 case 0:
692 wms[PRI_SR].fifo = 32 * 1024 / 64;
693 break;
694 }
695
696 wms[CUR_SR].wm = REG_DECODE1(fw3, 24, 6);
697 wms[CUR_HPLL_SR].wm = REG_DECODE1(fw3, 16, 6);
698 wms[PRI_HPLL_SR].wm = REG_DECODE1(fw3, 0, 9);
699
700 for (i = 0; i < ARRAY_SIZE(wms); i++) {
701 if (!wms[i].valid)
702 continue;
703 printf("%s: WM = %d, FIFO = %d\n",
704 plane_name[i], wms[i].wm, wms[i].fifo);
705 }
706 printf("CxSR enable = %s\n",
707 endis(REG_DECODE1(fw3, 30, 1)));
708 printf("HPLL SR enable = %s\n",
709 endis(REG_DECODE1(fw3, 31, 1)));
710 printf("Trickle feed = %s\n",
711 endis(!REG_DECODE1(mi_arb_state, 2, 1)));
712 printf("Primary display = %c\n",
713 REG_DECODE1(mi_arb_state, 0, 1) + 'A');
714 printf("Display plane A throttling = %s\n",
715 endis(!REG_DECODE1(cbr, 0, 1)));
716 printf("Display plane B throttling = %s\n",
717 endis(!REG_DECODE1(cbr, 1, 1)));
718}
719
720static void gen3_wm_dump(void)
721{
722 int i;
723 int totalsize = IS_945GM(devid) ? 128 : 96; /* FIXME? */
724 uint32_t dsparb;
725 uint32_t instpm;
726 uint64_t fw_blc;
727 uint32_t fw_blc_self;
728 uint32_t mi_arb_state;
729 struct gmch_wm wms[MAX_PLANE] = {};
730
731 intel_register_access_init(intel_get_pci_device(), 0);
732
733 dsparb = read_reg(0x70030);
734 instpm = read_reg(0x20c0);
735 fw_blc = read_reg(0x20d8) | ((uint64_t)read_reg(0x20dc) << 32);
736 fw_blc_self = read_reg(0x20e0);
737 mi_arb_state = read_reg(0x20e4);
738
739 intel_register_access_fini();
740
741 printf(" DSPARB = 0x%08x\n", dsparb);
742 printf(" FW_BLC = 0x%016" PRIx64 "\n", fw_blc);
743 printf(" FW_BLC_SELF = 0x%08x\n", fw_blc_self);
744 printf("MI_ARB_STATE = 0x%08x\n", mi_arb_state);
745
746 wms[PRI_A].valid = true;
747 wms[PRI_B].valid = true;
748 wms[PRI_C].valid = true;
749 wms[PRI_SR].valid = true;
750
751 wms[PRI_SR].wm = REG_DECODE1(fw_blc_self, 0, 8);
752
753 wms[PRI_C].burst = (REG_DECODE1(fw_blc, 40, 2) + 1) * 4;
754 wms[PRI_C].wm = REG_DECODE1(fw_blc, 32, 8);
755
756 wms[PRI_B].burst = (REG_DECODE1(fw_blc, 24, 2) + 1) * 4;
757 wms[PRI_B].wm = REG_DECODE1(fw_blc, 16, 8);
758
759 wms[PRI_A].burst = (REG_DECODE1(fw_blc, 8, 2) + 1) * 4;
760 wms[PRI_A].wm = REG_DECODE1(fw_blc, 0, 8);
761
762 wms[PRI_A].fifo = REG_DECODE1(dsparb, 0, 7) - 0;
763 wms[PRI_B].fifo = REG_DECODE1(dsparb, 7, 7) - wms[PRI_A].fifo;
764 wms[PRI_C].fifo = totalsize - wms[PRI_B].fifo - wms[PRI_A].fifo - 1;
765
766 for (i = 0; i < ARRAY_SIZE(wms); i++) {
767 if (!wms[i].valid)
768 continue;
769 printf("%s: WM = %d, FIFO = %d, burst = %d\n",
770 plane_name[i], wms[i].wm, wms[i].fifo, wms[i].burst);
771 }
772 /* FIXME G33 too perhaps? */
773 if (devid == PCI_CHIP_I945_G || devid == PCI_CHIP_I945_GM ||
774 devid == PCI_CHIP_I945_GME) {
775 printf("CxSR = %s\n",
776 endis(REG_DECODE1(fw_blc_self, 15, 1)));
777 } else if (devid == PCI_CHIP_I915_GM) {
778 printf("CxSR = %s\n",
779 endis(REG_DECODE1(instpm, 12, 1)));
780 }
781 printf("Trickle feed = %s\n",
782 endis(!REG_DECODE1(mi_arb_state, 2, 1)));
783 printf("Primary display = %c\n",
784 REG_DECODE1(mi_arb_state, 0, 1) + 'A');
785 printf("Display plane capability = %d planes\n",
786 3 - REG_DECODE1(mi_arb_state, 12, 2));
787}
788
789static void gen2_wm_dump(void)
790{
791 int i;
792 int totalsize;
793 uint32_t dsparb;
794 uint32_t mem_mode;
795 uint64_t fw_blc;
796 uint32_t fw_blc_self;
797 uint32_t mi_state;
798 struct gmch_wm wms[MAX_PLANE] = {};
799
800 intel_register_access_init(intel_get_pci_device(), 0);
801
802 dsparb = read_reg(0x70030);
803 mem_mode = read_reg(0x20cc);
804 fw_blc = read_reg(0x20d8) | ((uint64_t)read_reg(0x20dc) << 32);
805 fw_blc_self = read_reg(0x20e0);
806 mi_state = read_reg(0x20e4);
807
808 intel_register_access_fini();
809
810 printf(" DSPARB = 0x%08x\n", dsparb);
811 printf(" MEM_MODE = 0x%08x\n", mem_mode);
812 printf(" FW_BLC = 0x%016" PRIx64 "\n", fw_blc);
813 printf("FW_BLC_SELF = 0x%08x\n", fw_blc_self);
814 printf(" MI_STATE = 0x%08x\n", mi_state);
815
816 wms[PRI_C].burst = (REG_DECODE1(fw_blc, 40, 2) + 1) * 4;
817 wms[PRI_C].wm = REG_DECODE1(fw_blc, 32, 8);
818
819 wms[PRI_B].burst = (REG_DECODE1(fw_blc, 24, 2) + 1) * 4;
820 wms[PRI_B].wm = REG_DECODE1(fw_blc, 16, 8);
821
822 wms[PRI_A].burst = (REG_DECODE1(fw_blc, 8, 2) + 1) * 4;
823 wms[PRI_A].wm = REG_DECODE1(fw_blc, 0, 8);
824
825 if (devid == PCI_CHIP_845_G || devid == PCI_CHIP_I865_G) {
826 wms[PRI_A].valid = true;
827 wms[PRI_C].valid = true;
828
829 totalsize = 96; /* FIXME? */
830 wms[PRI_A].fifo = REG_DECODE1(dsparb, 0, 7) - 0;
831 wms[PRI_C].fifo = totalsize - wms[PRI_A].fifo - 1;
832 } else {
833 wms[PRI_A].valid = true;
834 wms[PRI_B].valid = true;
835 wms[PRI_C].valid = true;
836
837 if (devid == PCI_CHIP_I830_M)
838 totalsize = 288;
839 else
840 totalsize = 256;
841 totalsize = (devid == PCI_CHIP_I855_GM) ? 256 : 288;
842 wms[PRI_A].fifo = REG_DECODE1(dsparb, 0, 9) - 0;
843 wms[PRI_B].fifo = REG_DECODE1(dsparb, 9, 9) - wms[PRI_A].fifo;
844 wms[PRI_C].fifo = totalsize - wms[PRI_B].fifo - wms[PRI_A].fifo - 1;
845 }
846
847 for (i = 0; i < ARRAY_SIZE(wms); i++) {
848 if (!wms[i].valid)
849 continue;
850 printf("%s: WM = %d, FIFO = %d, burst = %d\n",
851 plane_name[i], wms[i].wm, wms[i].fifo, wms[i].burst);
852 }
853 if (devid == PCI_CHIP_I855_GM || devid == PCI_CHIP_I854_G) {
854 printf("CxSR = %s (%d)\n",
855 endis(REG_DECODE1(mi_state, 3, 2)),
856 REG_DECODE1(mi_state, 3, 2));
857 printf("Trickle feed = %s\n",
858 endis(!REG_DECODE1(mem_mode, 2, 1)));
859 printf("Display round robin = %s\n",
860 endis(REG_DECODE1(mem_mode, 14, 1)));
861 printf("Primary display = %c\n",
862 REG_DECODE1(mem_mode, 15, 1) + 'A');
863 } else {
864 printf("Display A trickle feed = %s\n",
865 endis(!REG_DECODE1(mem_mode, 2, 1)));
866 printf("Display B trickle feed = %s\n",
867 endis(!REG_DECODE1(mem_mode, 3, 1)));
868 printf("Water mark fix = %s\n",
869 endis(!REG_DECODE1(mem_mode, 14, 1)));
870 }
871}
872
873int main(int argc, char *argv[])
874{
875 devid = intel_get_pci_device()->device_id;
876
877 if (HAS_PCH_SPLIT(devid)) {
878 ilk_wm_dump();
879 } else if (IS_VALLEYVIEW(devid) || IS_CHERRYVIEW(devid)) {
880 display_base = 0x180000;
881 vlv_wm_dump();
882 } else if (IS_G4X(devid)) {
883 g4x_wm_dump();
884 } else if (IS_GEN4(devid)) {
885 gen4_wm_dump();
886 } else if (IS_IGD(devid)) {
887 pnv_wm_dump();
888 } else if (IS_GEN3(devid)) {
889 gen3_wm_dump();
890 } else if (IS_GEN2(devid)) {
891 gen2_wm_dump();
892 } else {
893 printf("unknown chip 0x%x\n", devid);
894 return 1;
895 }
896
897 return 0;
898}