8 typedef struct Reg Reg;
9 typedef struct Dpll Dpll;
10 typedef struct Hdmi Hdmi;
12 typedef struct Fdi Fdi;
13 typedef struct Pfit Pfit;
14 typedef struct Curs Curs;
15 typedef struct Plane Plane;
16 typedef struct Trans Trans;
17 typedef struct Pipe Pipe;
25 TypeIVB, /* Ivy Bdige */
29 u32int a; /* address or 0 when invalid */
34 Reg ctrl; /* DPLLx_CTRL */
40 Reg dm[2]; /* pipe/trans DATAM */
41 Reg dn[2]; /* pipe/trans DATAN */
42 Reg lm[2]; /* pipe/trans LINKM */
43 Reg ln[2]; /* pipe/trans LINKN */
45 Reg ht; /* pipe/trans HTOTAL_x */
46 Reg hb; /* pipe/trans HBLANK_x */
47 Reg hs; /* pipe/trans HSYNC_x */
48 Reg vt; /* pipe/trans VTOTAL_x */
49 Reg vb; /* pipe/trans VBLANK_x */
50 Reg vs; /* pipe/trans VSYNC_x */
51 Reg vss; /* pipe/trans VSYNCSHIFT_x */
53 Reg conf; /* pipe/trans CONF_x */
54 Reg chicken; /* workarround register */
56 Dpll *dpll; /* this transcoders dpll */
73 Reg txctl; /* FDI_TX_CTL */
75 Reg rxctl; /* FDI_RX_CTL */
76 Reg rxmisc; /* FDI_RX_MISC */
77 Reg rxtu[2]; /* FDI_RX_TUSIZE */
79 Reg dpctl; /* TRANS_DP_CTL_x */
90 Reg cntr; /* DSPxCNTR */
91 Reg linoff; /* DSPxLINOFF */
92 Reg stride; /* DSPxSTRIDE */
93 Reg surf; /* DSPxSURF */
94 Reg tileoff; /* DSPxTILEOFF */
106 Reg src; /* PIPExSRC */
108 Fdi fdi[1]; /* fdi/dp transcoder */
110 Plane dsp[1]; /* display plane */
111 Curs cur[1]; /* hardware cursor */
113 Pfit *pfit; /* selected panel fitter */
116 typedef struct Igfx Igfx;
132 Reg dpllsel; /* DPLL_SEL */
133 Reg drefctl; /* DREF_CTL */
134 Reg rawclkfreq; /* RAWCLK_FREQ */
135 Reg ssc4params; /* SSC4_PARAMS */
155 rr(Igfx *igfx, u32int a)
159 assert((a & 3) == 0);
160 outportl(igfx->pio, a);
161 return inportl(igfx->pio + 4);
164 wr(Igfx *igfx, u32int a, u32int v)
166 if(a == 0) /* invalid */
169 assert((a & 3) == 0);
170 outportl(igfx->pio, a);
171 outportl(igfx->pio + 4, v);
174 csr(Igfx *igfx, u32int reg, u32int clr, u32int set)
176 wr(igfx, reg, (rr(igfx, reg) & ~clr) | set);
180 loadreg(Igfx *igfx, Reg r)
186 snarfreg(Igfx *igfx, u32int a)
196 snarftrans(Igfx *igfx, Trans *t, u32int o)
199 t->ht = snarfreg(igfx, o + 0x00000);
200 t->hb = snarfreg(igfx, o + 0x00004);
201 t->hs = snarfreg(igfx, o + 0x00008);
202 t->vt = snarfreg(igfx, o + 0x0000C);
203 t->vb = snarfreg(igfx, o + 0x00010);
204 t->vs = snarfreg(igfx, o + 0x00014);
205 t->vss = snarfreg(igfx, o + 0x00028);
207 t->conf = snarfreg(igfx, o + 0x10008);
211 if(t == &igfx->pipe[0]){ /* PIPEA */
212 t->dm[0] = snarfreg(igfx, 0x70050); /* GMCHDataM */
213 t->dn[0] = snarfreg(igfx, 0x70054); /* GMCHDataN */
214 t->lm[0] = snarfreg(igfx, 0x70060); /* DPLinkM */
215 t->ln[0] = snarfreg(igfx, 0x70064); /* DPLinkN */
219 t->dm[0] = snarfreg(igfx, o + 0x30);
220 t->dn[0] = snarfreg(igfx, o + 0x34);
221 t->dm[1] = snarfreg(igfx, o + 0x38);
222 t->dn[1] = snarfreg(igfx, o + 0x3c);
223 t->lm[0] = snarfreg(igfx, o + 0x40);
224 t->ln[0] = snarfreg(igfx, o + 0x44);
225 t->lm[1] = snarfreg(igfx, o + 0x48);
226 t->ln[1] = snarfreg(igfx, o + 0x4c);
232 snarfpipe(Igfx *igfx, int x)
239 o = 0x60000 | x*0x1000;
240 snarftrans(igfx, p, o);
242 p->src = snarfreg(igfx, o + 0x0001C);
244 if(igfx->type == TypeIVB) {
245 p->fdi->txctl = snarfreg(igfx, o + 0x100);
247 o = 0xE0000 | x*0x1000;
248 snarftrans(igfx, p->fdi, o);
250 p->fdi->dpctl = snarfreg(igfx, o + 0x300);
252 p->fdi->rxctl = snarfreg(igfx, o + 0x1000c);
253 p->fdi->rxmisc = snarfreg(igfx, o + 0x10010);
254 p->fdi->rxtu[0] = snarfreg(igfx, o + 0x10030);
255 p->fdi->rxtu[1] = snarfreg(igfx, o + 0x10038);
257 p->fdi->chicken = snarfreg(igfx, o + 0x10064);
259 p->fdi->dpll = &igfx->dpll[(igfx->dpllsel.v>>(x*4)) & 1];
262 p->dpll = &igfx->dpll[x & 1];
266 p->dsp->cntr = snarfreg(igfx, 0x70180 | x*0x1000);
267 p->dsp->linoff = snarfreg(igfx, 0x70184 | x*0x1000);
268 p->dsp->stride = snarfreg(igfx, 0x70188 | x*0x1000);
269 p->dsp->tileoff = snarfreg(igfx, 0x701A4 | x*0x1000);
270 p->dsp->surf = snarfreg(igfx, 0x7019C | x*0x1000);
275 p->cur->cntr = snarfreg(igfx, 0x70080 | x*0x1000);
276 p->cur->base = snarfreg(igfx, 0x70084 | x*0x1000);
277 p->cur->pos = snarfreg(igfx, 0x70088 | x*0x1000);
280 p->cur->cntr = snarfreg(igfx, 0x70080 | x*0x40);
281 p->cur->base = snarfreg(igfx, 0x70084 | x*0x40);
282 p->cur->pos = snarfreg(igfx, 0x7008C | x*0x40);
290 if(igfx->pci->vid != 0x8086)
292 switch(igfx->pci->did){
293 case 0x0166: /* X230 */
296 case 0x2a42: /* X200s */
303 snarf(Vga* vga, Ctlr* ctlr)
310 igfx = alloc(sizeof(Igfx));
312 igfx->pci = vga->pci;
313 if(igfx->pci == nil){
314 error("%s: no pci device\n", ctlr->name);
317 igfx->type = devtype(igfx);
319 error("%s: unrecognized device\n", ctlr->name);
322 if((igfx->pci->mem[4].bar & 1) == 0){
323 error("%s: no pio bar\n", ctlr->name);
326 igfx->pio = igfx->pci->mem[4].bar & ~1;
332 igfx->npipe = 2; /* A,B */
334 igfx->dpll[0].ctrl = snarfreg(igfx, 0x06014);
335 igfx->dpll[0].fp0 = snarfreg(igfx, 0x06040);
336 igfx->dpll[0].fp1 = snarfreg(igfx, 0x06044);
337 igfx->dpll[1].ctrl = snarfreg(igfx, 0x06018);
338 igfx->dpll[1].fp0 = snarfreg(igfx, 0x06048);
339 igfx->dpll[1].fp1 = snarfreg(igfx, 0x0604c);
341 igfx->adpa = snarfreg(igfx, 0x061100);
342 igfx->lvds = snarfreg(igfx, 0x061180);
343 igfx->sdvob = snarfreg(igfx, 0x061140);
344 igfx->sdvoc = snarfreg(igfx, 0x061160);
346 igfx->pfit[0].ctrl = snarfreg(igfx, 0x061230);
347 y = (igfx->pfit[0].ctrl.v >> 29) & 3;
348 if(igfx->pipe[y].pfit == nil)
349 igfx->pipe[y].pfit = &igfx->pfit[0];
351 igfx->vgacntrl = snarfreg(igfx, 0x071400);
355 igfx->npipe = 3; /* A,B,C */
357 igfx->dpll[0].ctrl = snarfreg(igfx, 0xC6014);
358 igfx->dpll[0].fp0 = snarfreg(igfx, 0xC6040);
359 igfx->dpll[0].fp1 = snarfreg(igfx, 0xC6044);
360 igfx->dpll[1].ctrl = snarfreg(igfx, 0xC6018);
361 igfx->dpll[1].fp0 = snarfreg(igfx, 0xC6048);
362 igfx->dpll[1].fp1 = snarfreg(igfx, 0xC604c);
364 igfx->dpllsel = snarfreg(igfx, 0xC7000);
366 igfx->drefctl = snarfreg(igfx, 0xC6200);
367 igfx->rawclkfreq = snarfreg(igfx, 0xC6204);
368 igfx->ssc4params = snarfreg(igfx, 0xC6210);
370 /* cpu displayport A*/
371 igfx->dp[0].ctl = snarfreg(igfx, 0x64000);
372 igfx->dp[0].auxctl = snarfreg(igfx, 0x64010);
373 igfx->dp[0].auxdat[0] = snarfreg(igfx, 0x64014);
374 igfx->dp[0].auxdat[1] = snarfreg(igfx, 0x64018);
375 igfx->dp[0].auxdat[2] = snarfreg(igfx, 0x6401C);
376 igfx->dp[0].auxdat[3] = snarfreg(igfx, 0x64020);
377 igfx->dp[0].auxdat[4] = snarfreg(igfx, 0x64024);
379 /* pch displayport B,C,D */
381 igfx->dp[x].ctl = snarfreg(igfx, 0xE4000 + 0x100*x);
382 igfx->dp[x].auxctl = snarfreg(igfx, 0xE4010 + 0x100*x);
383 igfx->dp[x].auxdat[0] = snarfreg(igfx, 0xE4014 + 0x100*x);
384 igfx->dp[x].auxdat[1] = snarfreg(igfx, 0xE4018 + 0x100*x);
385 igfx->dp[x].auxdat[2] = snarfreg(igfx, 0xE401C + 0x100*x);
386 igfx->dp[x].auxdat[3] = snarfreg(igfx, 0xE4020 + 0x100*x);
387 igfx->dp[x].auxdat[4] = snarfreg(igfx, 0xE4024 + 0x100*x);
391 igfx->pfit[x].pwrgate = snarfreg(igfx, 0x68060 + 0x800*x);
392 igfx->pfit[x].winpos = snarfreg(igfx, 0x68070 + 0x800*x);
393 igfx->pfit[x].winsize = snarfreg(igfx, 0x68074 + 0x800*x);
394 igfx->pfit[x].ctrl = snarfreg(igfx, 0x68080 + 0x800*x);
396 y = (igfx->pfit[x].ctrl.v >> 29) & 3;
397 if(igfx->pipe[y].pfit == nil)
398 igfx->pipe[y].pfit = &igfx->pfit[x];
400 igfx->ppstatus = snarfreg(igfx, 0xC7200);
401 igfx->ppcontrol = snarfreg(igfx, 0xC7204);
403 igfx->hdmi[1].ctl = snarfreg(igfx, 0x0E1140); /* HDMI_CTL_B */
404 igfx->hdmi[1].bufctl[0] = snarfreg(igfx, 0x0FC810); /* HTMI_BUF_CTL_0 */
405 igfx->hdmi[1].bufctl[1] = snarfreg(igfx, 0x0FC81C); /* HTMI_BUF_CTL_1 */
406 igfx->hdmi[1].bufctl[2] = snarfreg(igfx, 0x0FC828); /* HTMI_BUF_CTL_2 */
407 igfx->hdmi[1].bufctl[3] = snarfreg(igfx, 0x0FC834); /* HTMI_BUF_CTL_3 */
409 igfx->hdmi[2].ctl = snarfreg(igfx, 0x0E1150); /* HDMI_CTL_C */
410 igfx->hdmi[2].bufctl[0] = snarfreg(igfx, 0x0FCC00); /* HTMI_BUF_CTL_4 */
411 igfx->hdmi[2].bufctl[1] = snarfreg(igfx, 0x0FCC0C); /* HTMI_BUF_CTL_5 */
412 igfx->hdmi[2].bufctl[2] = snarfreg(igfx, 0x0FCC18); /* HTMI_BUF_CTL_6 */
413 igfx->hdmi[2].bufctl[3] = snarfreg(igfx, 0x0FCC24); /* HTMI_BUF_CTL_7 */
415 igfx->hdmi[3].ctl = snarfreg(igfx, 0x0E1160); /* HDMI_CTL_D */
416 igfx->hdmi[3].bufctl[0] = snarfreg(igfx, 0x0FD000); /* HTMI_BUF_CTL_8 */
417 igfx->hdmi[3].bufctl[1] = snarfreg(igfx, 0x0FD00C); /* HTMI_BUF_CTL_9 */
418 igfx->hdmi[3].bufctl[2] = snarfreg(igfx, 0x0FD018); /* HTMI_BUF_CTL_10 */
419 igfx->hdmi[3].bufctl[3] = snarfreg(igfx, 0x0FD024); /* HTMI_BUF_CTL_11 */
421 igfx->adpa = snarfreg(igfx, 0x0E1100); /* DAC_CTL */
422 igfx->lvds = snarfreg(igfx, 0x0E1180); /* LVDS_CTL */
424 igfx->vgacntrl = snarfreg(igfx, 0x041000);
428 for(x=0; x<igfx->npipe; x++)
431 ctlr->flag |= Fsnarf;
435 options(Vga* vga, Ctlr* ctlr)
438 ctlr->flag |= Hlinear|Ulinear|Foptions;
442 genpll(int freq, int cref, int P2, int *m1, int *m2, int *n, int *p1)
444 int M1, M2, M, N, P, P1;
450 for(M2=5; M2<=9; M2++)
451 for(M1=10; M1<=20; M1++){
452 M = 5*(M1+2) + (M2+2);
453 if(M < 70 || M > 120)
455 for(P1=1; P1<=8; P1++){
463 if(a < 20*MHz || a > 400*MHz)
469 if(best < 0 || error < best){
482 initdpll(Igfx *igfx, int x, int freq, int islvds, int ishdmi)
484 int cref, m1, m2, n, p1, p2;
489 /* PLL Reference Input Select */
490 dpll = igfx->pipe[x].dpll;
491 dpll->ctrl.v &= ~(3<<13);
492 dpll->ctrl.v |= (islvds ? 2 : 0) << 13;
493 cref = islvds ? 100*MHz : 96*MHz;
496 /* transcoder dpll enable */
497 igfx->dpllsel.v |= 8<<(x*4);
498 /* program rawclock to 125MHz */
499 igfx->rawclkfreq.v = 125;
501 /* 120MHz SSC integrated source enable */
502 igfx->drefctl.v &= ~(3<<11);
503 igfx->drefctl.v |= 2<<11;
505 /* 120MHz SSC4 modulation en */
506 igfx->drefctl.v |= 2;
509 * PLL Reference Input Select:
510 * 000 DREFCLK (default is 120 MHz) for DAC/HDMI/DVI/DP
511 * 001 Super SSC 120MHz super-spread clock
512 * 011 SSC Spread spectrum input clock (120MHz default) for LVDS/DP
514 dpll = igfx->pipe[x].fdi->dpll;
515 dpll->ctrl.v &= ~(7<<13);
516 dpll->ctrl.v |= (islvds ? 3 : 0) << 13;
523 /* Dpll Mode select */
524 dpll->ctrl.v &= ~(3<<26);
525 dpll->ctrl.v |= (islvds ? 2 : 1)<<26;
527 /* P2 Clock Divide */
528 dpll->ctrl.v &= ~(3<<24);
531 if(genpll(freq, cref, p2, &m1, &m2, &n, &p1) < 0)
537 dpll->ctrl.v |= (1<<24);
539 if(genpll(freq, cref, p2, &m1, &m2, &n, &p1) < 0)
543 /* Dpll VCO Enable */
544 dpll->ctrl.v |= (1<<31);
546 /* Dpll Serial DVO High Speed IO clock Enable */
548 dpll->ctrl.v |= (1<<30);
550 dpll->ctrl.v &= ~(1<<30);
552 /* VGA Mode Disable */
553 dpll->ctrl.v |= (1<<28);
555 /* P1 Post Divisor */
556 dpll->ctrl.v &= ~0xFF00FF;
557 dpll->ctrl.v |= 0x10001<<(p1-1);
559 dpll->fp0.v &= ~(0x3f<<16);
560 dpll->fp0.v |= n << 16;
561 dpll->fp0.v &= ~(0x3f<<8);
562 dpll->fp0.v |= m1 << 8;
563 dpll->fp0.v &= ~(0x3f<<0);
564 dpll->fp0.v |= m2 << 0;
566 dpll->fp1.v = dpll->fp0.v;
572 initdatalinkmn(Trans *t, int freq, int lsclk, int lanes, int tu, int bpp)
577 m = (n * ((freq * bpp)/8)) / (lsclk * lanes);
578 t->dm[0].v = (tu-1)<<25 | m;
582 m = (n * freq) / lsclk;
586 t->dm[1].v = t->dm[0].v;
587 t->dn[1].v = t->dn[0].v;
588 t->lm[1].v = t->lm[0].v;
589 t->ln[1].v = t->ln[0].v;
593 inittrans(Trans *t, Mode *m)
595 /* clear all but 27:28 frame start delay (initialized by bios) */
598 /* tans/pipe enable */
601 /* trans/pipe timing */
602 t->ht.v = (m->ht - 1)<<16 | (m->x - 1);
604 t->hs.v = (m->ehs - 1)<<16 | (m->shs - 1);
605 t->vt.v = (m->vt - 1)<<16 | (m->y - 1);
607 t->vs.v = (m->vre - 1)<<16 | (m->vrs - 1);
612 initpipe(Pipe *p, Mode *m)
614 static uchar bpctab[4] = { 8, 10, 6, 12 };
615 int i, tu, bpc, lanes;
618 /* source image size */
619 p->src.v = (m->x - 1)<<16 | (m->y - 1);
622 /* panel fitter enable, hardcoded coefficients */
623 p->pfit->ctrl.v = 1<<31 | 1<<23;
624 p->pfit->winpos.v = 0;
625 p->pfit->winsize.v = (m->x << 16) | m->y;
628 /* enable and set monitor timings for cpu pipe */
631 /* default for displayport */
637 if(fdi->rxctl.a != 0){
638 /* enable and set monitor timings for transcoder */
643 * we do not program fdi in load(), so use
644 * snarfed bios initialized values for now.
646 if(fdi->rxctl.v & (1<<31)){
647 tu = 1+(fdi->rxtu[0].v >> 25);
648 bpc = bpctab[(fdi->rxctl.v >> 16) & 3];
649 lanes = 1+((fdi->rxctl.v >> 19) & 7);
653 fdi->txctl.v |= (1<<31);
654 /* tx port width selection */
655 fdi->txctl.v &= ~(7<<19);
656 fdi->txctl.v |= (lanes-1)<<19;
657 /* tx fdi pll enable */
658 fdi->txctl.v |= (1<<14);
659 /* clear auto training bits */
660 fdi->txctl.v &= ~(7<<8 | 1);
663 fdi->rxctl.v |= (1<<31);
664 /* rx port width selection */
665 fdi->rxctl.v &= ~(7<<19);
666 fdi->rxctl.v |= (lanes-1)<<19;
667 /* bits per color for transcoder */
668 for(i=0; i<nelem(bpctab); i++){
669 if(bpctab[i] == bpc){
670 fdi->rxctl.v &= ~(7<<16);
671 fdi->rxctl.v |= i<<16;
672 fdi->dpctl.v &= ~(7<<9);
673 fdi->dpctl.v |= i<<9;
677 /* rx fdi pll enable */
678 fdi->rxctl.v |= (1<<13);
679 /* rx fdi rawclk to pcdclk selection */
680 fdi->rxctl.v |= (1<<4);
683 fdi->rxtu[0].v = (tu-1)<<25;
684 fdi->rxtu[1].v = (tu-1)<<25;
685 initdatalinkmn(fdi, m->frequency, 270*MHz, lanes, tu, 3*bpc);
688 /* bits per color for cpu pipe */
689 for(i=0; i<nelem(bpctab); i++){
690 if(bpctab[i] == bpc){
691 p->conf.v &= ~(7<<5);
696 initdatalinkmn(p, m->frequency, 270*MHz, lanes, tu, 3*bpc);
700 init(Vga* vga, Ctlr* ctlr)
710 error("%s: unsupported color depth %d\n", ctlr->name, m->z);
715 igfx->vgacntrl.v |= (1<<31);
719 if((val = dbattr(m->attr, "lcd")) != nil && atoi(val) != 0){
723 x = (igfx->lvds.v >> 29) & 3;
725 x = (igfx->lvds.v >> 30) & 1;
726 igfx->lvds.v |= (1<<31);
728 igfx->ppcontrol.v &= ~0xFFFF0000;
729 igfx->ppcontrol.v |= 5;
733 /* plane enable, 32bpp and assign pipe */
734 p->dsp->cntr.v = (1<<31) | (6<<26) | (x<<24);
736 /* stride must be 64 byte aligned */
737 p->dsp->stride.v = m->x * (m->z / 8);
738 p->dsp->stride.v += 63;
739 p->dsp->stride.v &= ~63;
741 /* virtual width in pixels */
742 vga->virtx = p->dsp->stride.v / (m->z / 8);
745 p->dsp->linoff.v = 0;
746 p->dsp->tileoff.v = 0;
748 /* cursor plane off */
749 p->cur->cntr.v = x<<28;
753 if(initdpll(igfx, x, m->frequency, islvds, 0) < 0)
754 error("%s: frequency %d out of range\n", ctlr->name, m->frequency);
762 loadtrans(Igfx *igfx, Trans *t)
766 /* program trans/pipe timings */
767 loadreg(igfx, t->ht);
768 loadreg(igfx, t->hb);
769 loadreg(igfx, t->hs);
770 loadreg(igfx, t->vt);
771 loadreg(igfx, t->vb);
772 loadreg(igfx, t->vs);
773 loadreg(igfx, t->vss);
775 loadreg(igfx, t->dm[0]);
776 loadreg(igfx, t->dn[0]);
777 loadreg(igfx, t->lm[0]);
778 loadreg(igfx, t->ln[0]);
779 loadreg(igfx, t->dm[1]);
780 loadreg(igfx, t->dn[1]);
781 loadreg(igfx, t->lm[1]);
782 loadreg(igfx, t->ln[1]);
786 t->dpll->ctrl.v &= ~(1<<31);
787 loadreg(igfx, t->dpll->ctrl);
788 loadreg(igfx, t->dpll->fp0);
789 loadreg(igfx, t->dpll->fp1);
792 t->dpll->ctrl.v |= (1<<31);
793 loadreg(igfx, t->dpll->ctrl);
797 /* workarround: set timing override bit */
798 csr(igfx, t->chicken.a, 0, 1<<31);
800 /* enable trans/pipe */
801 t->conf.v |= (1<<31);
802 t->conf.v &= ~(1<<30);
803 loadreg(igfx, t->conf);
804 for(i=0; i<100; i++){
806 if(rr(igfx, t->conf.a) & (1<<30))
812 enablepipe(Igfx *igfx, int x)
817 if((p->conf.v & (1<<31)) == 0)
818 return; /* pipe is disabled, done */
821 p->fdi->rxctl.v &= ~(1<<31);
822 loadreg(igfx, p->fdi->rxctl);
824 p->fdi->txctl.v &= ~(1<<31);
825 loadreg(igfx, p->fdi->txctl);
829 /* image size (vga needs to be off) */
830 loadreg(igfx, p->src);
832 /* set panel fitter as needed */
834 loadreg(igfx, p->pfit->ctrl);
835 loadreg(igfx, p->pfit->winpos);
836 loadreg(igfx, p->pfit->winsize); /* arm */
839 /* enable cpu pipe */
843 loadreg(igfx, p->dsp->cntr);
844 loadreg(igfx, p->dsp->linoff);
845 loadreg(igfx, p->dsp->stride);
846 loadreg(igfx, p->dsp->tileoff);
847 loadreg(igfx, p->dsp->surf); /* arm */
850 loadreg(igfx, p->cur->cntr);
851 loadreg(igfx, p->cur->pos);
852 loadreg(igfx, p->cur->base); /* arm */
856 loadreg(igfx, p->fdi->rxtu[1]);
857 loadreg(igfx, p->fdi->rxtu[0]);
858 loadreg(igfx, p->fdi->rxmisc);
859 p->fdi->rxctl.v &= ~(3<<8 | 1<<10 | 3);
860 p->fdi->rxctl.v |= (1<<31);
861 loadreg(igfx, p->fdi->rxctl);
863 p->fdi->txctl.v &= ~(3<<8 | 1<<10 | 2);
864 p->fdi->txctl.v |= (1<<31);
865 loadreg(igfx, p->fdi->txctl);
868 /* enable the transcoder */
869 loadtrans(igfx, p->fdi);
873 disabletrans(Igfx *igfx, Trans *t)
877 /* the front fell off on x230 */
878 if(igfx->type == TypeIVB && t == &igfx->pipe[0])
881 /* disable transcoder / pipe */
882 csr(igfx, t->conf.a, 1<<31, 0);
883 for(i=0; i<100; i++){
885 if((rr(igfx, t->conf.a) & (1<<30)) == 0)
888 /* workarround: clear timing override bit */
889 csr(igfx, t->chicken.a, 1<<31, 0);
894 csr(igfx, t->dpll->ctrl.a, 1<<31, 0);
898 disablepipe(Igfx *igfx, int x)
905 csr(igfx, p->dsp->cntr.a, 1<<31, 0);
906 csr(igfx, p->dsp->surf.a, ~0, 0); /* arm */
908 csr(igfx, p->cur->cntr.a, 1<<5 | 7, 0);
909 csr(igfx, p->cur->base.a, ~0, 0); /* arm */
911 /* disable cpu pipe */
912 disabletrans(igfx, p);
914 /* disable panel fitter */
916 csr(igfx, p->pfit->ctrl.a, 1<<31, 0);
919 /* disable fdi transmitter and receiver */
920 csr(igfx, p->fdi->txctl.a, 1<<31 | 1<<10, 0);
921 csr(igfx, p->fdi->rxctl.a, 1<<31 | 1<<10, 0);
924 /* disable displayport transcoder */
925 csr(igfx, p->fdi->dpctl.a, 1<<31, 3<<29);
927 /* disable pch transcoder */
928 disabletrans(igfx, p->fdi);
930 /* disable pch dpll enable bit */
931 csr(igfx, igfx->dpllsel.a, 8<<(x*4), 0);
935 load(Vga* vga, Ctlr* ctlr)
943 if(igfx->ppcontrol.a != 0){
944 csr(igfx, igfx->ppcontrol.a, 0xFFFF0005, 0xABCD0000);
945 for(x=0; x<5000; x++){
947 if((rr(igfx, igfx->ppstatus.a) & (1<<31)) == 0)
953 csr(igfx, igfx->sdvob.a, (1<<29) | (1<<31), 0);
954 csr(igfx, igfx->sdvoc.a, (1<<29) | (1<<31), 0);
955 csr(igfx, igfx->adpa.a, 1<<31, 0);
956 csr(igfx, igfx->lvds.a, 1<<31, 0);
957 for(x = 0; x < nelem(igfx->dp); x++)
958 csr(igfx, igfx->dp[x].ctl.a, 1<<31, 0);
959 for(x = 0; x < nelem(igfx->hdmi); x++)
960 csr(igfx, igfx->hdmi[x].ctl.a, 1<<31, 0);
962 /* disable vga plane */
963 csr(igfx, igfx->vgacntrl.a, 0, 1<<31);
965 /* turn off all pipes */
966 for(x = 0; x < igfx->npipe; x++)
967 disablepipe(igfx, x);
969 /* program new clock sources */
970 loadreg(igfx, igfx->rawclkfreq);
971 loadreg(igfx, igfx->drefctl);
974 /* set lvds before enabling dpll */
975 loadreg(igfx, igfx->lvds);
977 /* new dpll setting */
978 loadreg(igfx, igfx->dpllsel);
980 /* program all pipes */
981 for(x = 0; x < igfx->npipe; x++)
984 /* program vga plane */
985 loadreg(igfx, igfx->vgacntrl);
988 loadreg(igfx, igfx->adpa);
989 loadreg(igfx, igfx->sdvob);
990 loadreg(igfx, igfx->sdvoc);
991 for(x = 0; x < nelem(igfx->dp); x++)
992 loadreg(igfx, igfx->dp[x].ctl);
993 for(x=0; x<nelem(igfx->hdmi); x++){
994 loadreg(igfx, igfx->hdmi[x].bufctl[0]);
995 loadreg(igfx, igfx->hdmi[x].bufctl[1]);
996 loadreg(igfx, igfx->hdmi[x].bufctl[2]);
997 loadreg(igfx, igfx->hdmi[x].bufctl[3]);
998 loadreg(igfx, igfx->hdmi[x].ctl);
1001 /* program lcd power */
1002 loadreg(igfx, igfx->ppcontrol);
1004 ctlr->flag |= Fload;
1008 dumpreg(char *name, char *item, Reg r)
1013 printitem(name, item);
1014 Bprint(&stdout, " [%.8ux] = %.8ux\n", r.a, r.v);
1018 dumptiming(char *name, Trans *t)
1022 if(t->dm[0].a != 0 && t->dm[0].v != 0){
1023 tu = (t->dm[0].v >> 25)+1;
1024 printitem(name, "dm1 tu");
1025 Bprint(&stdout, " %d\n", tu);
1027 m = t->dm[0].v & 0xffffff;
1030 printitem(name, "dm1/dn1");
1031 Bprint(&stdout, " %f\n", (double)m / (double)n);
1037 printitem(name, "lm1/ln1");
1038 Bprint(&stdout, " %f\n", (double)m / (double)n);
1044 dumptrans(char *name, Trans *t)
1046 dumpreg(name, "conf", t->conf);
1048 dumpreg(name, "dm1", t->dm[0]);
1049 dumpreg(name, "dn1", t->dn[0]);
1050 dumpreg(name, "lm1", t->lm[0]);
1051 dumpreg(name, "ln1", t->ln[0]);
1052 dumpreg(name, "dm2", t->dm[1]);
1053 dumpreg(name, "dn2", t->dn[1]);
1054 dumpreg(name, "lm2", t->lm[1]);
1055 dumpreg(name, "ln2", t->ln[1]);
1057 dumptiming(name, t);
1059 dumpreg(name, "ht", t->ht);
1060 dumpreg(name, "hb", t->hb);
1061 dumpreg(name, "hs", t->hs);
1063 dumpreg(name, "vt", t->vt);
1064 dumpreg(name, "vb", t->vb);
1065 dumpreg(name, "vs", t->vs);
1066 dumpreg(name, "vss", t->vss);
1070 dumppipe(Igfx *igfx, int x)
1077 snprint(name, sizeof(name), "%s pipe %c", igfx->ctlr->name, 'a'+x);
1078 dumpreg(name, "src", p->src);
1081 snprint(name, sizeof(name), "%s fdi %c", igfx->ctlr->name, 'a'+x);
1082 dumptrans(name, p->fdi);
1083 dumpreg(name, "txctl", p->fdi->txctl);
1084 dumpreg(name, "rxctl", p->fdi->rxctl);
1085 dumpreg(name, "rxmisc", p->fdi->rxmisc);
1086 dumpreg(name, "rxtu1", p->fdi->rxtu[0]);
1087 dumpreg(name, "rxtu2", p->fdi->rxtu[1]);
1088 dumpreg(name, "dpctl", p->fdi->dpctl);
1090 snprint(name, sizeof(name), "%s dsp %c", igfx->ctlr->name, 'a'+x);
1091 dumpreg(name, "cntr", p->dsp->cntr);
1092 dumpreg(name, "linoff", p->dsp->linoff);
1093 dumpreg(name, "stride", p->dsp->stride);
1094 dumpreg(name, "surf", p->dsp->surf);
1095 dumpreg(name, "tileoff", p->dsp->tileoff);
1097 snprint(name, sizeof(name), "%s cur %c", igfx->ctlr->name, 'a'+x);
1098 dumpreg(name, "cntr", p->cur->cntr);
1099 dumpreg(name, "base", p->cur->base);
1100 dumpreg(name, "pos", p->cur->pos);
1104 dump(Vga* vga, Ctlr* ctlr)
1110 if((igfx = vga->private) == nil)
1113 for(x=0; x<igfx->npipe; x++)
1116 for(x=0; x<nelem(igfx->dpll); x++){
1117 snprint(name, sizeof(name), "%s dpll %c", ctlr->name, 'a'+x);
1118 dumpreg(name, "ctrl", igfx->dpll[x].ctrl);
1119 dumpreg(name, "fp0", igfx->dpll[x].fp0);
1120 dumpreg(name, "fp1", igfx->dpll[x].fp1);
1123 dumpreg(ctlr->name, "dpllsel", igfx->dpllsel);
1125 dumpreg(ctlr->name, "drefctl", igfx->drefctl);
1126 dumpreg(ctlr->name, "rawclkfreq", igfx->rawclkfreq);
1127 dumpreg(ctlr->name, "ssc4params", igfx->ssc4params);
1129 for(x=0; x<nelem(igfx->dp); x++){
1130 snprint(name, sizeof(name), "%s dp %c", ctlr->name, 'a'+x);
1131 dumpreg(name, "ctl", igfx->dp[x].ctl);
1133 for(x=0; x<nelem(igfx->hdmi); x++){
1134 snprint(name, sizeof(name), "%s hdmi %c", ctlr->name, 'a'+x);
1135 dumpreg(name, "ctl", igfx->hdmi[x].ctl);
1138 for(x=0; x<nelem(igfx->pfit); x++){
1139 snprint(name, sizeof(name), "%s pfit %c", ctlr->name, 'a'+x);
1140 dumpreg(name, "ctrl", igfx->pfit[x].ctrl);
1141 dumpreg(name, "winpos", igfx->pfit[x].winpos);
1142 dumpreg(name, "winsize", igfx->pfit[x].winsize);
1143 dumpreg(name, "pwrgate", igfx->pfit[x].pwrgate);
1146 dumpreg(ctlr->name, "ppcontrol", igfx->ppcontrol);
1147 dumpreg(ctlr->name, "ppstatus", igfx->ppstatus);
1149 dumpreg(ctlr->name, "adpa", igfx->adpa);
1150 dumpreg(ctlr->name, "lvds", igfx->lvds);
1151 dumpreg(ctlr->name, "sdvob", igfx->sdvob);
1152 dumpreg(ctlr->name, "sdvoc", igfx->sdvoc);
1154 dumpreg(ctlr->name, "vgacntrl", igfx->vgacntrl);
1160 options, /* options */