ref: 1f46b5b9cd0d9688cb15d60c8f1a06e9471768a4
dir: /igfx-linktraining-fix/
diff 7ca997bf7efdca16416b22488ebc7b70c419fd44 uncommitted --- a/sys/src/cmd/aux/vga/igfx.c +++ b/sys/src/cmd/aux/vga/igfx.c @@ -1090,8 +1090,6 @@ 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 */ @@ -1133,12 +1131,11 @@ if((val = dbattr(m->attr, "display")) != nil){ port = atoi(val)-1; - if(igfx->type == TypeHSW && !igfx->dp[port-PortDPA].hdmi) - bpc = 6; }else if(dbattr(m->attr, "lcd") != nil) port = PortLCD; else port = PortVGA; + bpc = 8; /* bits per color channel */ trace("%s: display #%d\n", ctlr->name, port+1); @@ -1217,7 +1214,7 @@ /* displayport SST mode */ r->v &= ~(1<<27); /* link not in training, send normal pixels */ - r->v |= 3<<8; + r->v &= ~(7<<8); /* enable with pat1 armed */ if(igfx->dp[port-PortDPA].hdmi){ /* hdmi: do not configure displayport */ r->a = 0; @@ -1556,9 +1553,6 @@ { int i; - /* deselect pipe clock */ - csr(igfx, t->clksel.a, 7<<29, 0); - /* disable displayport transcoder */ if(igfx->type == TypeHSW){ csr(igfx, t->dpctl.a, 15<<28, 0); @@ -1582,6 +1576,9 @@ /* workaround: clear timing override bit */ csr(igfx, t->chicken.a, 1<<31, 0); + /* deselect pipe clock */ + csr(igfx, t->clksel.a, 7<<29, 0); + /* disable dpll */ if(igfx->type != TypeHSW && t->dpll != nil) csr(igfx, t->dpll->ctrl.a, 1<<31, 0); @@ -1766,6 +1763,9 @@ csr(igfx, igfx->dpll[x].ctrl.a, 1<<31, 0); } + /* program lcd power */ + loadreg(igfx, igfx->ppcontrol); + /* program new clock sources */ loadreg(igfx, igfx->rawclkfreq); loadreg(igfx, igfx->drefctl); @@ -1781,6 +1781,7 @@ /* new dpll setting */ for(x=0; x<nelem(igfx->dpllsel); x++) loadreg(igfx, igfx->dpllsel[x]); + sleep(10); /* program all pipes */ for(x = 0; x < igfx->npipe; x++) @@ -1794,16 +1795,25 @@ loadreg(igfx, igfx->sdvob); loadreg(igfx, igfx->sdvoc); for(x = 0; x < nelem(igfx->dp); x++){ + if((igfx->dp[x].ctl.a == 0 || (igfx->dp[x].ctl.v & 1<<31) == 0) && !igfx->dp[x].hdmi) + continue; + if(!igfx->dp[x].hdmi){ + igfx->dp[x].ctl.v &= ~(7<<8); /* arm pattern 1 */ + loadreg(igfx, igfx->dp[x].ctl); + } for(y=0; y<nelem(igfx->dp[x].buftrans); y++) loadreg(igfx, igfx->dp[x].buftrans[y]); + sleep(100); loadreg(igfx, igfx->dp[x].bufctl); + sleep(500); /* needs to take a breath before training */ if(enabledp(igfx, &igfx->dp[x]) < 0) ctlr->flag |= Ferror; + if(!igfx->dp[x].hdmi){ + igfx->dp[x].ctl.v |= 3<<8; /* send normal pixels */ + loadreg(igfx, igfx->dp[x].ctl); + } } - /* program lcd power */ - loadreg(igfx, igfx->ppcontrol); - ctlr->flag |= Fload; } @@ -2138,7 +2148,7 @@ buf[1] = addr >> 8; buf[2] = addr; buf[3] = len-1; - r = 3; + r = 3; if(data != nil && len > 0){ if((cmd & CmdRead) == 0) memmove(buf+4, data, len); @@ -2188,13 +2198,13 @@ if((dp->ctl.v & (1<<31)) == 0) return 0; - /* FIXME: always times out */ - if(igfx->type == TypeHSW && dp == &igfx->dp[0]) - goto Skip; - /* Link configuration */ - wdpaux(igfx, dp, 0x100, (270*MHz) / 27000000); - w = dp->ctl.v >> (igfx->type == TypeHSW ? 1 : 19) & 7; + for(try=0; try<30; try++) + if(wdpaux(igfx, dp, 0x100, (270*MHz) / 27000000) >= 0) + break; + if(try >= 30) + trace("can\'t start training\n"); + w = dp->bufctl.v >> (igfx->type == TypeHSW ? 1 : 19) & 7; wdpaux(igfx, dp, 0x101, w+1); r = 0; @@ -2244,11 +2254,8 @@ break; } } -Skip: + /* stop training */ - dp->ctl.v &= ~(7<<8); - dp->ctl.v |= 3<<8; - loadreg(igfx, dp->ctl); wdpaux(igfx, dp, 0x102, 0x00); return 1;