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