|
@@ -7,6 +7,10 @@
|
|
|
|
|
|
/*
|
|
|
* Intel 81x chipset family.
|
|
|
+ * mem[0]: AGP aperture memory, 64MB for 810-DC100, from 0xF4000000
|
|
|
+ * mem[1]: GC Register mmio space, 512KB for 810-DC100, from 0xFF000000
|
|
|
+ * For the memory of David Hogan who wrote this driver first for LCD.
|
|
|
+ * August 28, 2003 Kenji Okamoto
|
|
|
*/
|
|
|
|
|
|
typedef struct {
|
|
@@ -33,14 +37,14 @@ snarf(Vga* vga, Ctlr* ctlr)
|
|
|
switch(p->did) {
|
|
|
default:
|
|
|
continue;
|
|
|
- case 0x7121:
|
|
|
- case 0x7123:
|
|
|
- case 0x7125:
|
|
|
- case 0x1102:
|
|
|
- case 0x1112:
|
|
|
- case 0x1132:
|
|
|
- case 0x3577: /* Intel 830M chipset (experimental) */
|
|
|
- vga->f[1] = 230000000;
|
|
|
+ case 0x7121: /* Vanilla 82810 */
|
|
|
+ case 0x7123: /* 810-DC100, DELL OptiPlex GX100 */
|
|
|
+ case 0x7125: /* 82810E */
|
|
|
+ case 0x1102: /* 82815 FSB limited to 100MHz */
|
|
|
+ case 0x1112: /* 82815 no AGP */
|
|
|
+ case 0x1132: /* 82815 fully featured Solano */
|
|
|
+ case 0x3577: /* IBM R31 uses intel 830M chipset */
|
|
|
+ vga->f[1] = 230000000; /* MAX speed of internal DAC (Hz)*/
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
@@ -53,7 +57,7 @@ snarf(Vga* vga, Ctlr* ctlr)
|
|
|
if(write(f, "type i81x", 9) != 9)
|
|
|
error("%s: can't set type\n", ctlr->name);
|
|
|
close(f);
|
|
|
-
|
|
|
+
|
|
|
if((m = segattach(0, "i81xmmio", 0, p->mem[1].size)) == -1)
|
|
|
error("%s: can't attach mmio segment\n", ctlr->name);
|
|
|
|
|
@@ -63,21 +67,29 @@ snarf(Vga* vga, Ctlr* ctlr)
|
|
|
}
|
|
|
i81x = vga->private;
|
|
|
|
|
|
+ /* must give aperture memory size for frame buffer memory
|
|
|
+ such as 64*1024*1024 */
|
|
|
vga->vma = vga->vmz = i81x->pci->mem[0].size;
|
|
|
+// vga->vmz = 8*1024*1024;
|
|
|
+ vga->apz = i81x->pci->mem[0].size;
|
|
|
ctlr->flag |= Hlinear;
|
|
|
|
|
|
- for(i = 0x30; i <= 0x82; i++)
|
|
|
+ vga->graphics[0x10] = vgaxi(Grx, 0x10);
|
|
|
+ vga->attribute[0x11] = vgaxi(Attrx, 0x11); /* overscan color */
|
|
|
+ for(i=0; i < 0x19; i++)
|
|
|
vga->crt[i] = vgaxi(Crtx, i);
|
|
|
- for(i = 0x10; i <= 0x1f; i++)
|
|
|
- vga->graphics[i] = vgaxi(Grx, i);
|
|
|
-
|
|
|
+ for(i=0x30; i <= 0x82; i++) /* set CRT Controller Register (CR) */
|
|
|
+ vga->crt[i] = vgaxi(Crtx, i);
|
|
|
+ /* 0x06000: Clock Control Register base address (3 VCO frequency control) */
|
|
|
rp = (ulong*)(i81x->mmio+0x06000);
|
|
|
for(i = 0; i < nelem(i81x->clk); i++)
|
|
|
i81x->clk[i] = *rp++;
|
|
|
+
|
|
|
+ /* i830 CRTC registers (A) */
|
|
|
rp = (ulong*)(i81x->mmio+0x60000);
|
|
|
for(i = 0; i < nelem(i81x->lcd); i++)
|
|
|
i81x->lcd[i] = *rp++;
|
|
|
- rp = (ulong*)(i81x->mmio+0x70008);
|
|
|
+ rp = (ulong*)(i81x->mmio+0x70008); /* Pixel Pipeline Control register A */
|
|
|
i81x->pixconf = *rp;
|
|
|
|
|
|
ctlr->flag |= Fsnarf;
|
|
@@ -89,51 +101,205 @@ options(Vga*, Ctlr* ctlr)
|
|
|
ctlr->flag |= Hlinear|Foptions;
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+i81xdclk(I81x *i81x, Vga *vga) /* freq = MHz */
|
|
|
+{
|
|
|
+ int m, n, post, mtp, ntp;
|
|
|
+ double md, freq, error=1.0;
|
|
|
+
|
|
|
+ freq = vga->mode->deffrequency/1000000.0;
|
|
|
+ post = log(600.0/freq)/log(2.0);
|
|
|
+
|
|
|
+ for(ntp=3;;ntp++) {
|
|
|
+ md = freq*(1<<post)/(24.0/(double)ntp)/4.0;
|
|
|
+ mtp = (int)(md+0.5);
|
|
|
+ if(mtp<3) mtp=3;
|
|
|
+ error = 1.0-freq/(md/(ntp*(1<<post))*4*24.0);
|
|
|
+ if((fabs(error) < 0.001) || ((ntp > 30) && (fabs(error) < 0.005)))
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ m = vga->m[1] = mtp-2;
|
|
|
+ n = vga->n[1] = ntp-2;
|
|
|
+ vga->r[1] = post;
|
|
|
+ i81x->clk[2] = ((n & 0x3FF)<<16) | (m & 0x3FF);
|
|
|
+ i81x->clk[4] = (i81x->clk[4] & ~0x700000) | ((post & 0x07)<<20);
|
|
|
+ vga->mode->frequency = (m+2)/((n+2)*(1<<post))*4*24*1000000;
|
|
|
+}
|
|
|
+
|
|
|
static void
|
|
|
init(Vga* vga, Ctlr* ctlr)
|
|
|
{
|
|
|
I81x *i81x;
|
|
|
+ int vt, vde, vrs, vre;
|
|
|
|
|
|
i81x = vga->private;
|
|
|
|
|
|
+ /* <<TODO>>
|
|
|
+ i81x->clk[3]: LCD_CLKD: 0x0600c~0x0600f, default=00030013h
|
|
|
+ (VCO N-divisor=03h, M-divisor=13h)
|
|
|
+ i81x->clk[4]: DCLK_0DS: 0x06010~0x06013, Post value, default=40404040h means
|
|
|
+ Post Divisor=16, VCO Loop divisor = 4xM for all clocks.
|
|
|
+ Display&LCD Clock Devisor Select Reg = 0x40404040 ==> (LCD)(Clock2)(Clock1)(Clock0)
|
|
|
+ */
|
|
|
+ i81x->clk[0] = 0x00030013;
|
|
|
+ i81x->clk[1] = 0x00100053;
|
|
|
+ i81x->clk[4] = 0x40404040;
|
|
|
+ vga->misc = vgai(MiscR);
|
|
|
+ switch(vga->virtx) {
|
|
|
+ case 640: /* 640x480 DCLK_0D 25.175MHz dot clock */
|
|
|
+ vga->misc &= ~0x0A;
|
|
|
+ break;
|
|
|
+ case 720: /* 720x480 DCLK_1D 28.322MHz dot clock */
|
|
|
+ vga->misc = (vga->misc & ~0x08) | (1<<2);
|
|
|
+ break;
|
|
|
+ case 800:
|
|
|
+ case 1024:
|
|
|
+ case 1152:
|
|
|
+ case 1280:
|
|
|
+ case 1376:
|
|
|
+ vga->misc = vga->misc | (2<<2) & ~0x02; /* prohibit to access frame buffer */
|
|
|
+ i81xdclk(i81x, vga);
|
|
|
+ break;
|
|
|
+ default: /* for other higher resolution DCLK_2D */
|
|
|
+ error("%s: Only 800, 1024, 1152, 1280, 1376 resolutions are supported\n", ctlr->name);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* <<TODO>>
|
|
|
+ i830 LCD Controller, at i81x->mmio+0x60000
|
|
|
+ i81x->lcd[0]: Horizontal Total Reg. 0x60000
|
|
|
+ i81x->lcd[1]: Horizontal Blanking Reg. 0x60004
|
|
|
+ i81x->lcd[2]: Horizontal Sync Reg. 0x60008
|
|
|
+ i81x->lcd[3]: Vertical Total Reg. 0x6000c
|
|
|
+ i81x->lcd[4]: Vertical Blanking Reg. 0x60010
|
|
|
+ i81x->lcd[5]: Vertical Sync Reg. 0x60014
|
|
|
+ i81x->lcd[6]: Pixel Pipeline A Sequencer Register Control(SRC,0~7) 0x6001c
|
|
|
+ i81x->lcd[7]: BCLRPAT_A 0x60020
|
|
|
+ i81x->lcd[8]: 0
|
|
|
+ */
|
|
|
/*
|
|
|
- * Pixel pipeline mode: 16/24bp bypasses palette,
|
|
|
- * hw cursor enabled, hi-res mode, depth.
|
|
|
- */
|
|
|
+ * Pixel pipeline control register 0x70008:
|
|
|
+ * 16/24bp bypasses palette,
|
|
|
+ * hw cursor enabled(1<<12), hi-res mode(1<<0), depth(16-19 bit)
|
|
|
+ * 8bit DAC enable (1<<15), don't wrap to 256kM memory of VGA(1<<1).
|
|
|
+ * enable extended palette addressing (1<<8)
|
|
|
+ */
|
|
|
i81x->pixconf = (1<<12)|(1<<0);
|
|
|
- switch(vga->mode->z) {
|
|
|
+ i81x->pixconf &= 0xFFFFFBFF; /* disable overscan color */
|
|
|
+ switch(vga->mode->z) { /* vga->mode->z: color depth */
|
|
|
case 8:
|
|
|
i81x->pixconf |= (2<<16);
|
|
|
break;
|
|
|
- case 16:
|
|
|
+ case 16: /* (5:6:5 bit) */
|
|
|
i81x->pixconf |= (5<<16);
|
|
|
break;
|
|
|
case 24:
|
|
|
i81x->pixconf |= (6<<16);
|
|
|
break;
|
|
|
- case 32:
|
|
|
+ case 32: /* not supported */
|
|
|
i81x->pixconf |= (7<<16);
|
|
|
break;
|
|
|
default:
|
|
|
error("%s: depth %d not supported\n", ctlr->name, vga->mode->z);
|
|
|
}
|
|
|
|
|
|
+ /* DON'T CARE of Sequencer Reg. */
|
|
|
+ /* DON'T CARE of Attribute registers other than this */
|
|
|
+ vga->attribute[0x11] = 0; /* over scancolor = black */
|
|
|
+ /* DON't CARE of graphics[1], [2], [3], [4], [5], [6], [7] and [8] value */
|
|
|
if(vga->linear && (ctlr->flag & Hlinear)) {
|
|
|
- vga->graphics[0x10] = 0x02; /* enable linear mapping */
|
|
|
+ /* enable linear mapping, no VGA memory and no page mapping */
|
|
|
+ vga->graphics[0x10] = 0x0A;
|
|
|
ctlr->flag |= Ulinear;
|
|
|
}
|
|
|
|
|
|
- /* always use extended vga mode */
|
|
|
- vga->crt[0x80] = 0x01;
|
|
|
- vga->crt[0x30] = ((vga->mode->vt-2)>>8) & 0x0F;
|
|
|
- vga->crt[0x31] = ((vga->mode->y-1)>>8)&0x0f;
|
|
|
- vga->crt[0x32] = (vga->mode->vrs>>8) & 0x0F;
|
|
|
- vga->crt[0x33] = (vga->mode->vrs>>8) & 0x0F;
|
|
|
- vga->crt[0x35] = (((vga->mode->ht>>3)-5)>>8) & 0x01;
|
|
|
- vga->crt[0x39] = (vga->mode->ehb>>9) & 0x01;
|
|
|
- vga->crt[0x41] = (vga->crt[0x13]>>8) & 0x0F;
|
|
|
- vga->crt[0x42] = 0x00;
|
|
|
- vga->crt[0x40] = 0x80;
|
|
|
+ vt = vga->mode->vt;
|
|
|
+ vde = vga->virty;
|
|
|
+ vrs = vga->mode->vrs;
|
|
|
+ vre = vga->mode->vre+6; /* shift 7 pixel up */
|
|
|
+
|
|
|
+ if(vga->mode->interlace == 'v') {
|
|
|
+ vt /= 2;
|
|
|
+ vde /= 2;
|
|
|
+ vrs /= 2;
|
|
|
+ vre /= 2;
|
|
|
+ }
|
|
|
+ /* Reset Row scan */
|
|
|
+ vga->crt[8] = 0;
|
|
|
+/* Line Compare, bit 6 of crt[9], bit 4 of crt[7] and crt[0x18], should be
|
|
|
+ * vga->crt[9] = vgaxi(Crtx, 9) | ((vde>>9 & 1)<<6) & 0x7F;
|
|
|
+ * vga->crt[7] = vgaxi(Crtx, 7) | ((vde>>8 & 1)<<4);
|
|
|
+ * vga->crt[0x18] = vde & 0xFF;
|
|
|
+ * However, above values don't work!! I don't know why. K.Okamoto
|
|
|
+ */
|
|
|
+ vga->crt[9] = 0; /* I don't know why ? */
|
|
|
+ vga->crt[7] = 0; /* I don't know why ? */
|
|
|
+ vga->crt[0x18] = 0; /* I don't know why ? */
|
|
|
+/* 32 bits Start Address of frame buffer (AGP aperture memory)
|
|
|
+ vga->crt[0x42] = MSB 8 bits of Start Address Register, extended high start address Reg.
|
|
|
+ vga->crt[0x40] = higer 6 bits in 0~5 bits, and the MSB = 1, extebded start address Reg.
|
|
|
+ vga->crt[0x0C] = Start Address High Register
|
|
|
+ vga->crt[0x0D] = Start Address Low Register
|
|
|
+ LSB 2 bits of Start Address are always 0
|
|
|
+ */
|
|
|
+ vga->crt[0x42] = vga->pci->mem[0].bar>>24 & 0xFF;
|
|
|
+ vga->crt[0x40] = vga->pci->mem[0].bar>>18 & 0x3F | 0x80;
|
|
|
+ /* Start Address High */
|
|
|
+ vga->crt[0x0C] = vga->pci->mem[0].bar>>10 & 0xFF;
|
|
|
+ /* Start Address Low */
|
|
|
+ vga->crt[0x0D] = (vga->pci->mem[0].bar >>2 + 1)& 0xFF;
|
|
|
+ /* Underline Location, Memory Mode, DON'T CARE THIS VALUE */
|
|
|
+ vga->crt[0x14] = 0x0;
|
|
|
+ /* CRT Mode Control */
|
|
|
+ vga->crt[0x17] = 0x80; /* CRT normal mode */
|
|
|
+ /* Frame buffer memory offset (memory amount for a line) */
|
|
|
+ /* vga->crt[0x13] = lower 8 bits of Offset Register
|
|
|
+ vga->crt[0x41] = MSB 4 bits, those value should be
|
|
|
+ vga->crt[0x13] = (vga->virtx*(vga->mode->z>>3)/4) & 0xFF;
|
|
|
+ vga->crt[0x41] = (vga->virtx*(vga->mode->z>>3)/4)>>8 & 0x0F;
|
|
|
+ However, those doesn't work properly K.Okamoto
|
|
|
+ */
|
|
|
+ vga->crt[0x41] = (vga->crt[0x13]>>8) & 0x0F; //dhog
|
|
|
+
|
|
|
+ /* Horizontal Total */
|
|
|
+ vga->crt[0] = ((vga->mode->ht>>3)-6) & 0xFF;
|
|
|
+ /* Extended Horizontal Total Time Reg (ht) */
|
|
|
+ vga->crt[0x35] = vga->mode->ht>>12 & 0x01;
|
|
|
+// vga->crt[0x35] = (((vga->mode->ht>>1)-5)>>8) & 0x01; //dhog
|
|
|
+ /* Horizontal Display Enable End == horizontal width */
|
|
|
+ vga->crt[1] = (vga->virtx-1)>>3 & 0xFF;
|
|
|
+ /* Horizontal Blanking Start */
|
|
|
+ vga->crt[2] = ((vga->mode->shb>>3)-1) & 0xFF;
|
|
|
+ /* Horizontal blanking End crt[39](0),crt[5](7),crt[3](4:0) */
|
|
|
+ vga->crt[3] = (vga->mode->shb - vga->virtx)>>3 & 0x1F;
|
|
|
+ vga->crt[5] = ((vga->mode->shb - vga->virtx)>>3 & 0x20) <<2;
|
|
|
+ vga->crt[0x39] = ((vga->mode->shb - vga->virtx)>>3 & 0x40) >>6;
|
|
|
+// vga->crt[0x39] = (vga->mode->ehb>>9) & 0x01; //dhog
|
|
|
+ /* Horizontal Sync Start */
|
|
|
+ vga->crt[4] = vga->mode->shb>>3 & 0xFF;
|
|
|
+ /* Horizontal Sync End */
|
|
|
+ vga->crt[5] |= vga->mode->ehb>>3 & 0x1F;
|
|
|
+ /* Extended Vertical Total (vt) */
|
|
|
+ vga->crt[6] = (vt - 2) & 0xFF;
|
|
|
+ vga->crt[0x30] = (vt - 2)>>8 & 0x0F;
|
|
|
+ /* Vertical Sync Period */
|
|
|
+ vga->crt[0x11] = (vre - vrs - 2) & 0x0F;
|
|
|
+ /* Vertical Blanking End */
|
|
|
+ vga->crt[0x16] = (vre - vrs) & 0xFF;
|
|
|
+ /* Extended Vertical Display End (y) */
|
|
|
+ vga->crt[0x12] = (vde-1) & 0xFF;
|
|
|
+ vga->crt[0x31] = (vde-1)>>8 & 0x0f;
|
|
|
+ /* Extended Vertical Sync Start (vrs) */
|
|
|
+ vga->crt[0x10] = (vrs-1) & 0xFF;
|
|
|
+ vga->crt[0x32] = (vrs-1)>>8 & 0x0F;
|
|
|
+ /* Extended Vertical Blanking Start (vrs) */
|
|
|
+ vga->crt[0x15] = vrs & 0xFF;
|
|
|
+ vga->crt[0x33] = vrs>>8 & 0x0F;
|
|
|
+
|
|
|
+ if(vga->mode->interlace == 'v')
|
|
|
+ vga->crt[0x70] = vrs | 0x80;
|
|
|
+ else
|
|
|
+ vga->crt[0x70] = 0;
|
|
|
+ vga->crt[0x80] = 1;
|
|
|
|
|
|
ctlr->flag |= Finit;
|
|
|
}
|
|
@@ -147,17 +313,25 @@ load(Vga* vga, Ctlr* ctlr)
|
|
|
|
|
|
i81x = vga->private;
|
|
|
|
|
|
+ vgaxo(Attrx, 0x11, vga->attribute[0x11]);
|
|
|
+ /* set the screen graphic mode */
|
|
|
+ vgaxo(Crtx, 0x80, vga->crt[0x80]);
|
|
|
vgaxo(Grx, 0x10, vga->graphics[0x10]);
|
|
|
- for(i = 0x30; i <= 0x82; i++)
|
|
|
+ vgao(MiscW, vga->misc);
|
|
|
+ for(i=0; i <= 0x18; i++)
|
|
|
vgaxo(Crtx, i, vga->crt[i]);
|
|
|
- vgaxo(Crtx, 0x13, vga->crt[0x13]);
|
|
|
-
|
|
|
+ for(i=0x30; i <= 0x82; i++)
|
|
|
+ vgaxo(Crtx, i, vga->crt[i]);
|
|
|
+ vga->crt[0x40] |= 0x80; /* set CR40, then set the MSB bit of it */
|
|
|
+ vgaxo(Crtx, 0x40, vga->crt[0x40]);
|
|
|
+ /* 0x06000 = offset of Vertical Clock Devisor VGA0 */
|
|
|
rp = (ulong*)(i81x->mmio+0x06000);
|
|
|
- for(i = 0; i < nelem(i81x->clk); i++)
|
|
|
+ for(i=0; i < nelem(i81x->clk); i++)
|
|
|
*rp++ = i81x->clk[i];
|
|
|
rp = (ulong*)(i81x->mmio+0x60000);
|
|
|
for(i = 0; i < nelem(i81x->lcd); i++)
|
|
|
*rp++ = i81x->lcd[i];
|
|
|
+ /* set cursor, graphic mode */
|
|
|
rp = (ulong*)(i81x->mmio+0x70008);
|
|
|
*rp = i81x->pixconf;
|
|
|
|