shithub: riscv

Download patch

ref: 51f76ae999813bdbf33b06bb4e6c6c8b00f4aec8
parent: db7d1ed2b11cf17c3fc110eeede13ceba17fef33
parent: 540373b9f603825f27f853a441c6c046a04a0972
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Aug 20 14:51:07 EDT 2016

merge

--- a/sys/src/cmd/aux/vga/igfx.c
+++ b/sys/src/cmd/aux/vga/igfx.c
@@ -89,6 +89,8 @@
 
 	Reg	rxctl;		/* FDI_RX_CTL */
 	Reg	rxmisc;		/* FDI_RX_MISC */
+	Reg	rxiir;		/* FDI_RX_IIR */
+	Reg	rximr;		/* FDI_RX_IMR */
 	Reg	rxtu[2];	/* FDI_RX_TUSIZE */
 };
 
@@ -276,6 +278,10 @@
 
 		p->fdi->rxctl = snarfreg(igfx, o + 0x1000c);
 		p->fdi->rxmisc = snarfreg(igfx, o + 0x10010);
+
+		p->fdi->rxiir = snarfreg(igfx, o + 0x10014);
+		p->fdi->rximr = snarfreg(igfx, o + 0x10018);
+
 		p->fdi->rxtu[0] = snarfreg(igfx, o + 0x10030);
 		p->fdi->rxtu[1] = snarfreg(igfx, o + 0x10038);
 
@@ -297,7 +303,6 @@
 	/* cursor plane */
 	switch(igfx->type){
 	case TypeIVB:
-	case TypeSNB:
 		p->cur->cntr	= snarfreg(igfx, 0x70080 + x*0x1000);
 		p->cur->base	= snarfreg(igfx, 0x70084 + x*0x1000);
 		p->cur->pos	= snarfreg(igfx, 0x70088 + x*0x1000);
@@ -305,7 +310,8 @@
 	case TypeG45:
 		p->dsp->pos	= snarfreg(igfx, 0x7018C + x*0x1000);
 		p->dsp->size	= snarfreg(igfx, 0x70190 + x*0x1000);
-
+		/* wet floor */
+	case TypeSNB:
 		p->cur->cntr	= snarfreg(igfx, 0x70080 + x*0x40);
 		p->cur->base	= snarfreg(igfx, 0x70084 + x*0x40);
 		p->cur->pos	= snarfreg(igfx, 0x70088 + x*0x40);
@@ -320,10 +326,13 @@
 		return -1;
 	switch(igfx->pci->did){
 	case 0x0166:	/* 3rd Gen Core - ThinkPad X230 */
+	case 0x0152:	/* 2nd/3rd Gen Core - Core-i3 */
 		return TypeIVB;
+	case 0x0102:	/* Dell Optiplex 790 */
 	case 0x0126:	/* Thinkpad X220 */
 		return TypeSNB;
 	case 0x27a2:	/* GM945/82940GML - ThinkPad X60 Tablet */
+	case 0x29a2:	/* 82P965/G965 HECI desktop */
 	case 0x2a02:	/* GM965/GL960/X3100 - ThinkPad X61 Tablet */
 	case 0x2a42:	/* 4 Series Mobile - ThinkPad X200 */
 		return TypeG45;
@@ -689,6 +698,18 @@
 	return 0;
 }
 
+static int
+needlanes(int freq, int lsclk, int bpp)
+{
+	vlong v;
+	int n;
+
+	v = ((vlong)freq * bpp) / 8;
+	for(n=1; n<4 && v>lsclk; n<<=1, v>>=1)
+		;
+	return n;
+}
+
 static void
 initdatalinkmn(Trans *t, int freq, int lsclk, int lanes, int tu, int bpp)
 {
@@ -734,10 +755,10 @@
 }
 
 static void
-initpipe(Pipe *p, Mode *m)
+initpipe(Pipe *p, Mode *m, int bpc)
 {
 	static uchar bpctab[4] = { 8, 10, 6, 12 };
-	int i, tu, bpc, lanes;
+	int i, tu, lanes;
 	Fdi *fdi;
 
 	/* source image size */
@@ -754,9 +775,8 @@
 	inittrans(p, m);
 
 	/* default for displayport */
+	lanes = needlanes(m->frequency, 270*MHz, 3*bpc);
 	tu = 64;
-	bpc = 6;	/* why */
-	lanes = 1;
 
 	fdi = p->fdi;
 	if(fdi->rxctl.a != 0){
@@ -805,7 +825,7 @@
 static void
 init(Vga* vga, Ctlr* ctlr)
 {
-	int x, port;
+	int x, port, bpc;
 	char *val;
 	Igfx *igfx;
 	Pipe *p;
@@ -816,6 +836,8 @@
 	if(m->z != 32)
 		error("%s: unsupported color depth %d\n", ctlr->name, m->z);
 
+	bpc = 8;	/* bits per color channel */
+
 	igfx = vga->private;
 
 	/* disable vga */
@@ -858,10 +880,10 @@
 		break;
 
 	case PortVGA:
-		if(igfx->npipe > 2)
-			x = (igfx->adpa.v >> 29) & 3;
-		else
+		if(igfx->type == TypeG45)
 			x = (igfx->adpa.v >> 30) & 1;
+		else
+			x = (igfx->adpa.v >> 29) & 3;
 		igfx->adpa.v |= (1<<31);
 		if(igfx->type == TypeG45){
 			igfx->adpa.v &= ~(3<<10);	/* Monitor DPMS: on */
@@ -876,10 +898,10 @@
 		break;
 
 	case PortLCD:
-		if(igfx->npipe > 2)
-			x = (igfx->lvds.v >> 29) & 3;
-		else
+		if(igfx->type == TypeG45)
 			x = (igfx->lvds.v >> 30) & 1;
+		else
+			x = (igfx->lvds.v >> 29) & 3;
 		igfx->lvds.v |= (1<<31);
 		igfx->ppcontrol.v |= 5;
 
@@ -905,8 +927,9 @@
 			goto Badport;
 		/* port enable */
 		r->v |= 1<<31;
-		/* port width selection: x1 Mode */
+		/* port width selection */
 		r->v &= ~(7<<19);
+		r->v |= needlanes(m->frequency, 270*MHz, 3*bpc)-1 << 19;
 
 		/* port reversal: off */
 		r->v &= ~(1<<15);
@@ -975,7 +998,7 @@
 	if(initdpll(igfx, x, m->frequency, port) < 0)
 		error("%s: frequency %d out of range\n", ctlr->name, m->frequency);
 
-	initpipe(p, m);
+	initpipe(p, m, bpc);
 
 	ctlr->flag |= Finit;
 }
@@ -1053,8 +1076,8 @@
 		loadreg(igfx, p->fdi->rxctl);
 		sleep(5);
 		p->fdi->txctl.v &= ~(7<<8 | 1);	/* clear auto training bits */
-		p->fdi->txctl.v &= ~(1<<31);
-		p->fdi->rxctl.v |= (1<<14);	/* enable pll */
+		p->fdi->txctl.v &= ~(1<<31);	/* disable */
+		p->fdi->txctl.v |= (1<<14);	/* enable pll */
 		loadreg(igfx, p->fdi->txctl);
 		sleep(5);
 	}
@@ -1102,21 +1125,61 @@
 		loadreg(igfx, p->fdi->rxtu[0]);
 		loadreg(igfx, p->fdi->rxmisc);
 
-		p->fdi->rxctl.v &= ~(3<<8);	/* link train pattern 00 */
-		p->fdi->rxctl.v |= 1<<10;	/* auto train enable */
-		p->fdi->rxctl.v |= 1<<31;	/* enable */
-		loadreg(igfx, p->fdi->rxctl);
+		if(igfx->type == TypeSNB){
+			/* unmask bit lock and symbol lock bits */
+			csr(igfx, p->fdi->rximr.a, 3<<8, 0);
 
-		p->fdi->txctl.v &= ~(3<<8);	/* link train pattern 00 */
-		p->fdi->txctl.v |= 1<<10;	/* auto train enable */
-		p->fdi->txctl.v |= 1<<31;	/* enable */
-		loadreg(igfx, p->fdi->txctl);
+			p->fdi->rxctl.v &= ~(3<<8);	/* link train pattern1 */
+			p->fdi->rxctl.v |= 1<<31;	/* enable */
+			loadreg(igfx, p->fdi->rxctl);
 
-		/* wait for link training done */
-		for(i=0; i<200; i++){
+			p->fdi->txctl.v &= ~(3<<8);	/* link train pattern1 */
+			p->fdi->txctl.v |= 1<<31;	/* enable */
+			loadreg(igfx, p->fdi->txctl);
+
+			/* wait for bit lock */
+			for(i=0; i<10; i++){
+				sleep(1);
+				if(rr(igfx, p->fdi->rxiir.a) & (1<<8))
+					break;
+			}
+			csr(igfx, p->fdi->rxiir.a, 0, 1<<8);
+	
+			/* switch to link train pattern2 */
+			csr(igfx, p->fdi->rxctl.a, 3<<8, 1<<8);
+			csr(igfx, p->fdi->txctl.a, 3<<8, 1<<8);
+
+			/* wait for symbol lock */
+			for(i=0; i<10; i++){
+				sleep(1);
+				if(rr(igfx, p->fdi->rxiir.a) & (1<<9))
+					break;
+			}
+			csr(igfx, p->fdi->rxiir.a, 0, 1<<9);
+
+			/* switch to link train normal */
+			csr(igfx, p->fdi->rxctl.a, 0, 3<<8);
+			csr(igfx, p->fdi->txctl.a, 0, 3<<8);
+
+			/* wait idle pattern time */
 			sleep(5);
-			if(rr(igfx, p->fdi->txctl.a) & 2)
-				break;
+		} else {
+			p->fdi->rxctl.v &= ~(3<<8);	/* link train pattern 00 */
+			p->fdi->rxctl.v |= 1<<10;	/* auto train enable */
+			p->fdi->rxctl.v |= 1<<31;	/* enable */
+			loadreg(igfx, p->fdi->rxctl);
+
+			p->fdi->txctl.v &= ~(3<<8);	/* link train pattern 00 */
+			p->fdi->txctl.v |= 1<<10;	/* auto train enable */
+			p->fdi->txctl.v |= 1<<31;	/* enable */
+			loadreg(igfx, p->fdi->txctl);
+
+			/* wait for link training done */
+			for(i=0; i<200; i++){
+				sleep(5);
+				if(rr(igfx, p->fdi->txctl.a) & 2)
+					break;
+			}
 		}
 	}
 
@@ -1626,8 +1689,8 @@
 		return 0;
 
 	/* Link configuration */
-	wdpaux(igfx, dp, 0x100, 0x0A);	/* 270Mhz */
-	wdpaux(igfx, dp, 0x101, 0x01);	/* one lane */
+	wdpaux(igfx, dp, 0x100, (270*MHz) / 27000000);
+	wdpaux(igfx, dp, 0x101, ((dp->ctl.v>>19)&7)+1);
 
 	r = 0;