changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: igfx: vga support on x230, fix fdi link setup, LG Flatron L1730P vgadb entry

changeset 4200: 4867c8979fa0
parent 4199: c2c45e4bdbfb
child 4201: 6e74137cd05c
author: cinap_lenrek@felloff.net
date: Mon, 12 Jan 2015 01:51:51 +0100
files: lib/vgadb sys/src/cmd/aux/vga/igfx.c
description: igfx: vga support on x230, fix fdi link setup, LG Flatron L1730P vgadb entry
     1.1--- a/lib/vgadb
     1.2+++ b/lib/vgadb
     1.3@@ -1707,3 +1707,12 @@ x200s=1280x800		# 60Hz
     1.4 	vrs=802 vre=804 vt=830
     1.5 	hsync=- vsync=-
     1.6 	lcd=1
     1.7+
     1.8+#
     1.9+# LG Flatron L1730P
    1.10+#
    1.11+l1730p=1280x1024		# 60Hz
    1.12+	clock=108
    1.13+	shb=1320 ehb=1440 ht=1688
    1.14+	vrs=1025 vre=1028 vt=1066
    1.15+	hsync=+ vsync=+
     2.1--- a/sys/src/cmd/aux/vga/igfx.c
     2.2+++ b/sys/src/cmd/aux/vga/igfx.c
     2.3@@ -16,6 +16,7 @@ typedef struct Curs Curs;
     2.4 typedef struct Plane Plane;
     2.5 typedef struct Trans Trans;
     2.6 typedef struct Pipe Pipe;
     2.7+typedef struct Igfx Igfx;
     2.8 
     2.9 enum {
    2.10 	MHz = 1000000,
    2.11@@ -114,7 +115,6 @@ struct Pipe {
    2.12 	Pfit	*pfit;		/* selected panel fitter */
    2.13 };
    2.14 
    2.15-typedef struct Igfx Igfx;
    2.16 struct Igfx {
    2.17 	Ctlr	*ctlr;
    2.18 	Pcidev	*pci;
    2.19@@ -151,9 +151,11 @@ struct Igfx {
    2.20 	/* common */
    2.21 	Reg	adpa;
    2.22 	Reg	lvds;
    2.23-	Edid	*lvdsedid;
    2.24 
    2.25 	Reg	vgacntrl;
    2.26+
    2.27+	Edid	*adpaedid;
    2.28+	Edid	*lvdsedid;
    2.29 };
    2.30 
    2.31 static u32int
    2.32@@ -309,7 +311,7 @@ devtype(Igfx *igfx)
    2.33 	return -1;
    2.34 }
    2.35 
    2.36-static void snarfedid(Igfx*);
    2.37+static Edid* snarfedid(Igfx*, int port, int addr);
    2.38 
    2.39 static void
    2.40 snarf(Vga* vga, Ctlr* ctlr)
    2.41@@ -370,6 +372,9 @@ snarf(Vga* vga, Ctlr* ctlr)
    2.42 		if(igfx->pipe[y].pfit == nil)
    2.43 			igfx->pipe[y].pfit = &igfx->pfit[0];
    2.44 
    2.45+		igfx->ppstatus		= snarfreg(igfx, 0x61200);
    2.46+		igfx->ppcontrol		= snarfreg(igfx, 0x61204);
    2.47+
    2.48 		igfx->vgacntrl		= snarfreg(igfx, 0x071400);
    2.49 		break;
    2.50 
    2.51@@ -389,7 +394,7 @@ snarf(Vga* vga, Ctlr* ctlr)
    2.52 		igfx->rawclkfreq	= snarfreg(igfx, 0xC6204);
    2.53 		igfx->ssc4params	= snarfreg(igfx, 0xC6210);
    2.54 
    2.55-		/* cpu displayport A*/
    2.56+		/* cpu displayport A */
    2.57 		igfx->dp[0].ctl		= snarfreg(igfx, 0x64000);
    2.58 		igfx->dp[0].auxctl	= snarfreg(igfx, 0x64010);
    2.59 		igfx->dp[0].auxdat[0]	= snarfreg(igfx, 0x64014);
    2.60@@ -454,7 +459,8 @@ snarf(Vga* vga, Ctlr* ctlr)
    2.61 	for(x=0; x<igfx->npipe; x++)
    2.62 		snarfpipe(igfx, x);
    2.63 
    2.64-	snarfedid(igfx);
    2.65+	igfx->adpaedid = snarfedid(igfx, 2, 0x50);
    2.66+	igfx->lvdsedid = snarfedid(igfx, 3, 0x50);
    2.67 
    2.68 	ctlr->flag |= Fsnarf;
    2.69 }
    2.70@@ -476,13 +482,16 @@ genpll(int freq, int cref, int P2, int *
    2.71 	best = -1;
    2.72 	for(N=3; N<=8; N++)
    2.73 	for(M2=5; M2<=9; M2++)
    2.74-	for(M1=10; M1<=20; M1++){
    2.75+//	for(M1=10; M1<=20; M1++){
    2.76+	for(M1=12; M1<=22; M1++){
    2.77 		M = 5*(M1+2) + (M2+2);
    2.78-		if(M < 70 || M > 120)
    2.79+		if(M < 79 || M > 127)
    2.80+//		if(M < 70 || M > 120)
    2.81 			continue;
    2.82 		for(P1=1; P1<=8; P1++){
    2.83 			P = P1 * P2;
    2.84-			if(P < 4 || P > 98)
    2.85+			if(P < 5 || P > 98)
    2.86+//			if(P < 4 || P > 98)
    2.87 				continue;
    2.88 			a = cref;
    2.89 			a *= M;
    2.90@@ -507,6 +516,20 @@ genpll(int freq, int cref, int P2, int *
    2.91 }
    2.92 
    2.93 static int
    2.94+getcref(Igfx *igfx, int x)
    2.95+{
    2.96+	Dpll *dpll;
    2.97+
    2.98+	dpll = &igfx->dpll[x];
    2.99+	if(igfx->type == TypeG45){
   2.100+		if(((dpll->ctrl.v >> 13) & 3) == 3)
   2.101+			return 100*MHz;
   2.102+		return 96*MHz;
   2.103+	}
   2.104+	return 120*MHz;
   2.105+}
   2.106+
   2.107+static int
   2.108 initdpll(Igfx *igfx, int x, int freq, int islvds, int ishdmi)
   2.109 {
   2.110 	int cref, m1, m2, n, p1, p2;
   2.111@@ -517,22 +540,27 @@ initdpll(Igfx *igfx, int x, int freq, in
   2.112 		/* PLL Reference Input Select */
   2.113 		dpll = igfx->pipe[x].dpll;
   2.114 		dpll->ctrl.v &= ~(3<<13);
   2.115-		dpll->ctrl.v |= (islvds ? 2 : 0) << 13;
   2.116-		cref = islvds ? 100*MHz : 96*MHz;
   2.117+		dpll->ctrl.v |= (islvds ? 3 : 0) << 13;
   2.118 		break;
   2.119 	case TypeIVB:
   2.120 		/* transcoder dpll enable */
   2.121 		igfx->dpllsel.v |= 8<<(x*4);
   2.122 		/* program rawclock to 125MHz */
   2.123 		igfx->rawclkfreq.v = 125;
   2.124+
   2.125+		igfx->drefctl.v &= ~(3<<13);
   2.126+		igfx->drefctl.v &= ~(3<<11);
   2.127+		igfx->drefctl.v &= ~(3<<9);
   2.128+		igfx->drefctl.v &= ~(3<<7);
   2.129+		igfx->drefctl.v &= ~3;
   2.130+
   2.131 		if(islvds){
   2.132-			/* 120MHz SSC integrated source enable */
   2.133-			igfx->drefctl.v &= ~(3<<11);
   2.134 			igfx->drefctl.v |= 2<<11;
   2.135+			igfx->drefctl.v |= 1;
   2.136+		} else {
   2.137+			igfx->drefctl.v |= 2<<9;
   2.138+		}
   2.139 
   2.140-			/* 120MHz SSC4 modulation en */	
   2.141-			igfx->drefctl.v |= 2;
   2.142-		}
   2.143 		/*
   2.144 		 * PLL Reference Input Select:
   2.145 		 * 000	DREFCLK		(default is 120 MHz) for DAC/HDMI/DVI/DP
   2.146@@ -542,11 +570,11 @@ initdpll(Igfx *igfx, int x, int freq, in
   2.147 		dpll = igfx->pipe[x].fdi->dpll;
   2.148 		dpll->ctrl.v &= ~(7<<13);
   2.149 		dpll->ctrl.v |= (islvds ? 3 : 0) << 13;
   2.150-		cref = 120*MHz;
   2.151 		break;
   2.152 	default:
   2.153 		return -1;
   2.154 	}
   2.155+	cref = getcref(igfx, x);
   2.156 
   2.157 	/* Dpll Mode select */
   2.158 	dpll->ctrl.v &= ~(3<<26);
   2.159@@ -603,11 +631,13 @@ initdatalinkmn(Trans *t, int freq, int l
   2.160 
   2.161 	n = 0x800000;
   2.162 	m = (n * ((freq * bpp)/8)) / (lsclk * lanes);
   2.163+
   2.164 	t->dm[0].v = (tu-1)<<25 | m;
   2.165 	t->dn[0].v = n;
   2.166 
   2.167 	n = 0x80000;
   2.168 	m = (n * freq) / lsclk;
   2.169+
   2.170 	t->lm[0].v = m;
   2.171 	t->ln[0].v = n;
   2.172 
   2.173@@ -628,11 +658,13 @@ inittrans(Trans *t, Mode *m)
   2.174 
   2.175 	/* trans/pipe timing */
   2.176 	t->ht.v = (m->ht - 1)<<16 | (m->x - 1);
   2.177-	t->hb.v = t->ht.v;
   2.178 	t->hs.v = (m->ehb - 1)<<16 | (m->shb - 1);
   2.179 	t->vt.v = (m->vt - 1)<<16 | (m->y - 1);
   2.180+	t->vs.v = (m->vre - 1)<<16 | (m->vrs - 1);
   2.181+
   2.182+	t->hb.v = t->ht.v;
   2.183 	t->vb.v = t->vt.v;
   2.184-	t->vs.v = (m->vre - 1)<<16 | (m->vrs - 1);
   2.185+
   2.186 	t->vss.v = 0;
   2.187 }
   2.188 
   2.189@@ -647,7 +679,7 @@ initpipe(Pipe *p, Mode *m)
   2.190 	p->src.v = (m->x - 1)<<16 | (m->y - 1);
   2.191 
   2.192 	if(p->pfit != nil){
   2.193-		/* panel fitter enable, hardcoded coefficients */
   2.194+		/* panel fitter on, hardcoded coefficients */
   2.195 		p->pfit->ctrl.v = 1<<31 | 1<<23;
   2.196 		p->pfit->winpos.v = 0;
   2.197 		p->pfit->winsize.v = (m->x << 16) | m->y;
   2.198@@ -658,7 +690,7 @@ initpipe(Pipe *p, Mode *m)
   2.199 
   2.200 	/* default for displayport */
   2.201 	tu = 64;
   2.202-	bpc = 8;
   2.203+	bpc = 6;	/* why */
   2.204 	lanes = 1;
   2.205 
   2.206 	fdi = p->fdi;
   2.207@@ -666,29 +698,10 @@ initpipe(Pipe *p, Mode *m)
   2.208 		/* enable and set monitor timings for transcoder */
   2.209 		inittrans(fdi, m);
   2.210 
   2.211-		/*
   2.212-		 * hack:
   2.213-		 * we do not program fdi in load(), so use
   2.214-		 * snarfed bios initialized values for now.
   2.215-		 */
   2.216-		if(fdi->rxctl.v & (1<<31)){
   2.217-			tu = 1+(fdi->rxtu[0].v >> 25);
   2.218-			bpc = bpctab[(fdi->rxctl.v >> 16) & 3];
   2.219-			lanes = 1+((fdi->rxctl.v >> 19) & 7);
   2.220-		}
   2.221-
   2.222-		/* fdi tx enable */
   2.223-		fdi->txctl.v |= (1<<31);
   2.224 		/* tx port width selection */
   2.225 		fdi->txctl.v &= ~(7<<19);
   2.226 		fdi->txctl.v |= (lanes-1)<<19;
   2.227-		/* tx fdi pll enable */
   2.228-		fdi->txctl.v |= (1<<14);
   2.229-		/* clear auto training bits */
   2.230-		fdi->txctl.v &= ~(7<<8 | 1);
   2.231 
   2.232-		/* fdi rx enable */
   2.233-		fdi->rxctl.v |= (1<<31);
   2.234 		/* rx port width selection */
   2.235 		fdi->rxctl.v &= ~(7<<19);
   2.236 		fdi->rxctl.v |= (lanes-1)<<19;
   2.237@@ -702,10 +715,10 @@ initpipe(Pipe *p, Mode *m)
   2.238 				break;
   2.239 			}
   2.240 		}
   2.241-		/* rx fdi pll enable */
   2.242-		fdi->rxctl.v |= (1<<13);
   2.243-		/* rx fdi rawclk to pcdclk selection */
   2.244-		fdi->rxctl.v |= (1<<4);
   2.245+
   2.246+		/* enhanced framing on */
   2.247+		fdi->rxctl.v |= (1<<6);
   2.248+		fdi->txctl.v |= (1<<18);
   2.249 
   2.250 		/* tusize 1 and 2 */
   2.251 		fdi->rxtu[0].v = (tu-1)<<25;
   2.252@@ -742,7 +755,14 @@ init(Vga* vga, Ctlr* ctlr)
   2.253 	/* disable vga */
   2.254 	igfx->vgacntrl.v |= (1<<31);
   2.255 
   2.256-	x = 0;
   2.257+	/* disable all pipes adpa and lvds */
   2.258+	igfx->ppcontrol.v &= 0xFFFF;
   2.259+	igfx->ppcontrol.v &= ~5;
   2.260+	igfx->lvds.v &= ~(1<<31);
   2.261+	igfx->adpa.v &= ~(1<<31);
   2.262+	for(x=0; x<igfx->npipe; x++)
   2.263+		igfx->pipe[x].conf.v &= ~(1<<31);
   2.264+
   2.265 	islvds = 0;
   2.266 	if((val = dbattr(m->attr, "lcd")) != nil && atoi(val) != 0){
   2.267 		islvds = 1;
   2.268@@ -752,14 +772,18 @@ init(Vga* vga, Ctlr* ctlr)
   2.269 		else
   2.270 			x = (igfx->lvds.v >> 30) & 1;
   2.271 		igfx->lvds.v |= (1<<31);
   2.272-
   2.273-		igfx->ppcontrol.v &= ~0xFFFF0000;
   2.274 		igfx->ppcontrol.v |= 5;
   2.275+	} else {
   2.276+		if(igfx->npipe > 2)
   2.277+			x = (igfx->adpa.v >> 29) & 3;
   2.278+		else
   2.279+			x = (igfx->adpa.v >> 30) & 1;
   2.280+		igfx->adpa.v |= (1<<31);
   2.281 	}
   2.282 	p = &igfx->pipe[x];
   2.283 
   2.284-	/* plane enable, 32bpp and assign pipe */
   2.285-	p->dsp->cntr.v = (1<<31) | (6<<26) | (x<<24);
   2.286+	/* plane enable, 32bpp */
   2.287+	p->dsp->cntr.v = (1<<31) | (6<<26);
   2.288 
   2.289 	/* stride must be 64 byte aligned */
   2.290 	p->dsp->stride.v = m->x * (m->z / 8);
   2.291@@ -839,17 +863,25 @@ loadtrans(Igfx *igfx, Trans *t)
   2.292 static void
   2.293 enablepipe(Igfx *igfx, int x)
   2.294 {
   2.295+	int i;
   2.296 	Pipe *p;
   2.297 
   2.298 	p = &igfx->pipe[x];
   2.299 	if((p->conf.v & (1<<31)) == 0)
   2.300 		return;	/* pipe is disabled, done */
   2.301 
   2.302-	if(0){
   2.303+	if(p->fdi->rxctl.a != 0){
   2.304 		p->fdi->rxctl.v &= ~(1<<31);
   2.305+		p->fdi->rxctl.v &= ~(1<<4);	/* rawclk */
   2.306+		p->fdi->rxctl.v |= (1<<13);	/* enable pll */
   2.307 		loadreg(igfx, p->fdi->rxctl);
   2.308 		sleep(5);
   2.309+		p->fdi->rxctl.v |= (1<<4);	/* pcdclk */
   2.310+		loadreg(igfx, p->fdi->rxctl);
   2.311+		sleep(5);
   2.312+		p->fdi->txctl.v &= ~(7<<8 | 1);	/* clear auto training bits */
   2.313 		p->fdi->txctl.v &= ~(1<<31);
   2.314+		p->fdi->rxctl.v |= (1<<14);	/* enable pll */
   2.315 		loadreg(igfx, p->fdi->txctl);
   2.316 		sleep(5);
   2.317 	}
   2.318@@ -879,18 +911,28 @@ enablepipe(Igfx *igfx, int x)
   2.319 	loadreg(igfx, p->cur->pos);
   2.320 	loadreg(igfx, p->cur->base);	/* arm */
   2.321 
   2.322-	if(0){
   2.323+	if(p->fdi->rxctl.a != 0){
   2.324 		/* enable fdi */
   2.325 		loadreg(igfx, p->fdi->rxtu[1]);
   2.326 		loadreg(igfx, p->fdi->rxtu[0]);
   2.327 		loadreg(igfx, p->fdi->rxmisc);
   2.328-		p->fdi->rxctl.v &= ~(3<<8 | 1<<10 | 3);
   2.329-		p->fdi->rxctl.v |= (1<<31);
   2.330+
   2.331+		p->fdi->rxctl.v &= ~(3<<8);	/* link train pattern 00 */
   2.332+		p->fdi->rxctl.v |= 1<<10;	/* auto train enable */
   2.333+		p->fdi->rxctl.v |= 1<<31;	/* enable */
   2.334 		loadreg(igfx, p->fdi->rxctl);
   2.335 
   2.336-		p->fdi->txctl.v &= ~(3<<8 | 1<<10 | 2);
   2.337-		p->fdi->txctl.v |= (1<<31);
   2.338+		p->fdi->txctl.v &= ~(3<<8);	/* link train pattern 00 */
   2.339+		p->fdi->txctl.v |= 1<<10;	/* auto train enable */
   2.340+		p->fdi->txctl.v |= 1<<31;	/* enable */
   2.341 		loadreg(igfx, p->fdi->txctl);
   2.342+
   2.343+		/* wait for link training done */
   2.344+		for(i=0; i<200; i++){
   2.345+			sleep(5);
   2.346+			if(rr(igfx, p->fdi->txctl.a) & 2)
   2.347+				break;
   2.348+		}
   2.349 	}
   2.350 
   2.351 	/* enable the transcoder */
   2.352@@ -902,10 +944,6 @@ disabletrans(Igfx *igfx, Trans *t)
   2.353 {
   2.354 	int i;
   2.355 
   2.356-	/* the front fell off on x230 */
   2.357-	if(igfx->type == TypeIVB && t == &igfx->pipe[0])
   2.358-		goto skippipe;
   2.359-
   2.360 	/* disable transcoder / pipe */
   2.361 	csr(igfx, t->conf.a, 1<<31, 0);
   2.362 	for(i=0; i<100; i++){
   2.363@@ -916,7 +954,6 @@ disabletrans(Igfx *igfx, Trans *t)
   2.364 	/* workarround: clear timing override bit */
   2.365 	csr(igfx, t->chicken.a, 1<<31, 0);
   2.366 
   2.367-skippipe:
   2.368 	/* disable dpll  */
   2.369 	if(t->dpll != nil)
   2.370 		csr(igfx, t->dpll->ctrl.a, 1<<31, 0);
   2.371@@ -943,11 +980,9 @@ disablepipe(Igfx *igfx, int x)
   2.372 	if(p->pfit != nil)
   2.373 		csr(igfx, p->pfit->ctrl.a, 1<<31, 0);
   2.374 
   2.375-	if(0){
   2.376-		/* disable fdi transmitter and receiver */
   2.377-		csr(igfx, p->fdi->txctl.a, 1<<31 | 1<<10, 0);
   2.378-		csr(igfx, p->fdi->rxctl.a, 1<<31 | 1<<10, 0);
   2.379-	}
   2.380+	/* disable fdi transmitter and receiver */
   2.381+	csr(igfx, p->fdi->txctl.a, 1<<31 | 1<<10, 0);
   2.382+	csr(igfx, p->fdi->rxctl.a, 1<<31 | 1<<10, 0);
   2.383 
   2.384 	/* disable displayport transcoder */
   2.385 	csr(igfx, p->fdi->dpctl.a, 1<<31, 3<<29);
   2.386@@ -1048,7 +1083,7 @@ dumptiming(char *name, Trans *t)
   2.387 	int tu, m, n;
   2.388 
   2.389 	if(t->dm[0].a != 0 && t->dm[0].v != 0){
   2.390-		tu = (t->dm[0].v >> 25)+1;
   2.391+		tu = 1+((t->dm[0].v >> 25) & 0x3f);
   2.392 		printitem(name, "dm1 tu");
   2.393 		Bprint(&stdout, " %d\n", tu);
   2.394 
   2.395@@ -1129,6 +1164,54 @@ dumppipe(Igfx *igfx, int x)
   2.396 }
   2.397 
   2.398 static void
   2.399+dumpdpll(Igfx *igfx, int x)
   2.400+{
   2.401+	int cref, m1, m2, n, p1, p2;
   2.402+	uvlong freq;
   2.403+	char name[32];
   2.404+	Dpll *dpll;
   2.405+	u32int m;
   2.406+
   2.407+	dpll = &igfx->dpll[x];
   2.408+	snprint(name, sizeof(name), "%s dpll %c", igfx->ctlr->name, 'a'+x);
   2.409+
   2.410+	dumpreg(name, "ctrl", dpll->ctrl);
   2.411+	dumpreg(name, "fp0", dpll->fp0);
   2.412+	dumpreg(name, "fp1", dpll->fp1);
   2.413+
   2.414+	p2 = ((dpll->ctrl.v >> 13) & 3) == 3 ? 14 : 10;
   2.415+	if(((dpll->ctrl.v >> 24) & 3) == 1)
   2.416+		p2 >>= 1;
   2.417+	m = (dpll->ctrl.v >> 16) & 0xFF;
   2.418+	for(p1 = 1; p1 <= 8; p1++)
   2.419+		if(m & (1<<(p1-1)))
   2.420+			break;
   2.421+	printitem(name, "ctrl p1");
   2.422+	Bprint(&stdout, " %d\n", p1);
   2.423+	printitem(name, "ctrl p2");
   2.424+	Bprint(&stdout, " %d\n", p2);
   2.425+
   2.426+	n = (dpll->fp0.v >> 16) & 0x3f;
   2.427+	m1 = (dpll->fp0.v >> 8) & 0x3f;
   2.428+	m2 = (dpll->fp0.v >> 0) & 0x3f;
   2.429+
   2.430+	cref = getcref(igfx, x);
   2.431+	freq = ((uvlong)cref * (5*(m1+2) + (m2+2)) / (n+2)) / (p1 * p2);
   2.432+
   2.433+	printitem(name, "fp0 m1");
   2.434+	Bprint(&stdout, " %d\n", m1);
   2.435+	printitem(name, "fp0 m2");
   2.436+	Bprint(&stdout, " %d\n", m2);
   2.437+	printitem(name, "fp0 n");
   2.438+	Bprint(&stdout, " %d\n", n);
   2.439+
   2.440+	printitem(name, "cref");
   2.441+	Bprint(&stdout, " %d\n", cref);
   2.442+	printitem(name, "fp0 freq");
   2.443+	Bprint(&stdout, " %lld\n", freq);
   2.444+}
   2.445+
   2.446+static void
   2.447 dump(Vga* vga, Ctlr* ctlr)
   2.448 {
   2.449 	char name[32];
   2.450@@ -1141,12 +1224,8 @@ dump(Vga* vga, Ctlr* ctlr)
   2.451 	for(x=0; x<igfx->npipe; x++)
   2.452 		dumppipe(igfx, x);
   2.453 
   2.454-	for(x=0; x<nelem(igfx->dpll); x++){
   2.455-		snprint(name, sizeof(name), "%s dpll %c", ctlr->name, 'a'+x);
   2.456-		dumpreg(name, "ctrl", igfx->dpll[x].ctrl);
   2.457-		dumpreg(name, "fp0", igfx->dpll[x].fp0);
   2.458-		dumpreg(name, "fp1", igfx->dpll[x].fp1);
   2.459-	}
   2.460+	for(x=0; x<nelem(igfx->dpll); x++)
   2.461+		dumpdpll(igfx, x);
   2.462 
   2.463 	dumpreg(ctlr->name, "dpllsel", igfx->dpllsel);
   2.464 
   2.465@@ -1181,8 +1260,14 @@ dump(Vga* vga, Ctlr* ctlr)
   2.466 
   2.467 	dumpreg(ctlr->name, "vgacntrl", igfx->vgacntrl);
   2.468 
   2.469-	if(igfx->lvdsedid != nil)
   2.470+	if(igfx->adpaedid != nil){
   2.471+		Bprint(&stdout, "edid adpa\n");
   2.472+		printedid(igfx->adpaedid);
   2.473+	}
   2.474+	if(igfx->lvdsedid != nil){
   2.475+		Bprint(&stdout, "edid lvds\n");
   2.476 		printedid(igfx->lvdsedid);
   2.477+	}
   2.478 }
   2.479 
   2.480 enum {
   2.481@@ -1195,7 +1280,7 @@ enum {
   2.482 };
   2.483 	
   2.484 static int
   2.485-gmbusread(Igfx *igfx, int portsel, int addr, uchar *data, int len)
   2.486+gmbusread(Igfx *igfx, int port, int addr, uchar *data, int len)
   2.487 {
   2.488 	u32int x, y;
   2.489 	int n, t;
   2.490@@ -1203,7 +1288,7 @@ gmbusread(Igfx *igfx, int portsel, int a
   2.491 	if(igfx->gmbus[GMBUSCP].a == 0)
   2.492 		return -1;
   2.493 
   2.494-	wr(igfx, igfx->gmbus[GMBUSCP].a, portsel);
   2.495+	wr(igfx, igfx->gmbus[GMBUSCP].a, port);
   2.496 	wr(igfx, igfx->gmbus[GMBUSIX].a, 0);
   2.497 
   2.498 	/* bus cycle without index and stop, byte count, slave address, read */
   2.499@@ -1238,21 +1323,41 @@ gmbusread(Igfx *igfx, int portsel, int a
   2.500 			data[n++] = y & 0xff;
   2.501 		}
   2.502 	}
   2.503+
   2.504 	return n;
   2.505 }
   2.506 
   2.507-static void
   2.508-snarfedid(Igfx *igfx)
   2.509+static Edid*
   2.510+snarfedid(Igfx *igfx, int port, int addr)
   2.511 {
   2.512-	uchar buf[128];
   2.513+	uchar buf[256], tmp[256];
   2.514+	Edid *e;
   2.515+	int i;
   2.516+
   2.517+	/* read twice */
   2.518+	if(gmbusread(igfx, port, addr, buf, 128) != 128)
   2.519+		return nil;
   2.520+	if(gmbusread(igfx, port, addr, buf + 128, 128) != 128)
   2.521+		return nil;
   2.522 
   2.523-	if(gmbusread(igfx, 3, 0x50, buf, sizeof(buf)) != sizeof(buf))
   2.524-		return;
   2.525-	igfx->lvdsedid = malloc(sizeof(Edid));
   2.526-	if(parseedid128(igfx->lvdsedid, buf) != 0){
   2.527-		free(igfx->lvdsedid);
   2.528-		igfx->lvdsedid = nil;
   2.529+	/* shift if neccesary so edid block is at the start */
   2.530+	for(i=0; i<256-8; i++){
   2.531+		if(buf[i+0] == 0x00 && buf[i+1] == 0xFF && buf[i+2] == 0xFF && buf[i+3] == 0xFF
   2.532+		&& buf[i+4] == 0xFF && buf[i+5] == 0xFF && buf[i+6] == 0xFF && buf[i+7] == 0x00){
   2.533+			memmove(tmp, buf, i);
   2.534+			memmove(buf, buf + i, 256 - i);
   2.535+			memmove(buf + (256 - i), tmp, i);
   2.536+			break;
   2.537+		}
   2.538 	}
   2.539+
   2.540+	e = malloc(sizeof(Edid));
   2.541+	if(parseedid128(e, buf) != 0){
   2.542+		free(e);
   2.543+		return nil;
   2.544+	}
   2.545+
   2.546+	return e;
   2.547 }
   2.548 
   2.549 Ctlr igfx = {