Patchwork Integrated graphics controller on second bus?

login
register
about
Submitter Rudolf Marek
Date 2010-01-03 21:15:33
Message ID <4B4108F5.5070209@assembler.cz>
Download mbox | patch
Permalink /patch/728/
State Superseded
Headers show

Comments

Rudolf Marek - 2010-01-03 21:15:33
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

I think I can help you. It looks to me that bit 7 at offset 0xe1 is not set as
default anymore (otherwise the code never worked?). You would need to set it
early so VGA gets visible in "enable" phase. The patch fixes that. Also I
disabled the direct access FB because it was hardcoded. I forgotten what is for,
maybe libv will know. It looks like the code sets VGA framebuffer size to 32MB
(this is hardcoded elsewhere check the comments)

Please try the attached patch I think it could fix it.

Thanks,

Rudolf

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAktBCPUACgkQ3J9wPJqZRNWwZwCgoip1UCnykf0c62eEqpu2Ka6Y
KLwAoNBXRYN90nI+M4S4p3SlnwPZSrf3
=waUq
-----END PGP SIGNATURE-----
Luc Verhaegen - 2010-01-03 21:45:57
On Sun, Jan 03, 2010 at 10:15:33PM +0100, Rudolf Marek wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Hi,
> 
> I think I can help you. It looks to me that bit 7 at offset 0xe1 is not set as
> default anymore (otherwise the code never worked?). You would need to set it
> early so VGA gets visible in "enable" phase. The patch fixes that. Also I
> disabled the direct access FB because it was hardcoded. I forgotten what is for,
> maybe libv will know. It looks like the code sets VGA framebuffer size to 32MB
> (this is hardcoded elsewhere check the comments)
> 
> Please try the attached patch I think it could fix it.
> 
> Thanks,
> 
> Rudolf

> Index: northbridge.c
> ===================================================================
> --- northbridge.c	(revision 4978)
> +++ northbridge.c	(working copy)
> @@ -41,32 +41,32 @@
>  	pci_write_config16(dev, 0x80, 0x610f);
>  	pci_write_config32(dev, 0x88, 0x00000002);
>  	
> +	/* dont know if this is right ID fix it */
>  	fb_dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x3122, 0);
>  	if (fb_dev) {

This is just a quick way of checking whether the unichrome was enabled 
at all, so yes, right id.

> -		/* Fixup GART and framebuffer addresses properly.
> -		 * First setup frame buffer properly.
> -		 */
> -		//fb = pci_read_config32(dev, 0x10);       /* Base addres of framebuffer */
> -		fb = 0xd0000000;
> -		printk_debug("Frame buffer at %8x\n",fb);
> -
> -		c = pci_read_config8(dev, 0xe1) & 0xf0;  /* size of vga */
> -		c |= fb>>28;  /* upper nibble of frame buffer address */
> -		c = 0xdd;
> -		pci_write_config8(dev, 0xe1, c);
> -		c = 0x81;                                /* enable framebuffer */
> -		pci_write_config8(dev, 0xe0, c);
> +		/* step 1 enable  */
> +		pci_write_config8(dev, 0xe1, 0x80);
> +		/* step 2 enable the VGA without the direct access framebuffer - TOPMEM-32MB must get reserved */
> +		pci_write_config8(dev, 0xe1, 0xd0);
>  		pci_write_config8(dev, 0xe2, 0x42);      /* 'cos award does */
>  	}
>  }
>  
>  static void nullfunc(){}
>  
> +static void vga_en(struct device *dev)
> +{
> +	/* enable VGA, so the bridges gets VGA_EN and resources are set */
> +	pci_write_config8(dev, 0xe1, 0x80);
> +}
> +
> +
>  static struct device_operations northbridge_operations = {
>  	.read_resources   = nullfunc,
>  	.set_resources    = pci_dev_set_resources,
>  	.enable_resources = pci_dev_enable_resources,
> -	.init             = northbridge_init
> +	.init             = northbridge_init,
> +	.enable           = vga_en,
>  };
>  
>  static const struct pci_driver northbridge_driver __pci_driver = {
> @@ -108,11 +108,15 @@
>  	msr_t clocks1,clocks2,instructions,setup;
>  
>  	printk_debug("VGA random fixup ...\n");
> +
> +
> +	// why it does not rely on std resource system? 
> +/*
>  	pci_write_config8(dev, 0x04, 0x07);
>  	pci_write_config8(dev, 0x0d, 0x20);
>  	pci_write_config32(dev,0x10,0xd8000008);
>  	pci_write_config32(dev,0x14,0xdc000000);
> -
> +*/

History.

>  	// set up performnce counters for debugging vga init sequence
>  	//setup.lo = 0x1c0; // count instructions
>  	//wrmsr(0x187,setup);
> @@ -254,6 +258,7 @@
>  					ramregs[i]);
>  		}
>  		printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*16*1024);
> +//it looks like one set 32MB of VGA?
>  		tomk = rambits*16*1024 - 32768;
>  		/* Compute the top of Low memory */
>  		tolmk = pci_tolm >> 10;

Anything else than 32mb and it dies a horrible death later on when linux 
tries to use the disks.

Direct fb access allows any access to the framebuffer on the unichrome 
to be intercepted by the memory controller. Unichrome and memory 
controller are on the same die here, and since the unichrome uses part 
of main ram for its memory, any access to the unichrome memory would 
mean requests being made from the unichrome to the memory controller. 
Without direct fb access, a lot of on chip bandwidth is effectively 
thrown away sending fb accesses back and forth.

Luc Verhaegen.
Rudolf Marek - 2010-01-03 22:55:36
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

>> +/*
>>  	pci_write_config8(dev, 0x04, 0x07);
>>  	pci_write_config8(dev, 0x0d, 0x20);
>>  	pci_write_config32(dev,0x10,0xd8000008);
>>  	pci_write_config32(dev,0x14,0xdc000000);
>> -
>> +*/
> 
> History.

Aha and in raminit.c it looks like some hardcoded bars too :/


>>  	// set up performnce counters for debugging vga init sequence
>>  	//setup.lo = 0x1c0; // count instructions
>>  	//wrmsr(0x187,setup);
>> @@ -254,6 +258,7 @@
>>  					ramregs[i]);
>>  		}
>>  		printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*16*1024);
>> +//it looks like one set 32MB of VGA?
>>  		tomk = rambits*16*1024 - 32768;
>>  		/* Compute the top of Low memory */
>>  		tolmk = pci_tolm >> 10;
> 
> Anything else than 32mb and it dies a horrible death later on when linux 
> tries to use the disks.

Hm looks familiar to me. Maybe it dies when the DMA is done to the buffer which
is located in low mem in the 0xA0000 - 0xF0000 region? Maybe the framebuffer
will just change where the DMA buffers gets allocated... Or it is some other bug
;) Does your linux use 640-1MB region as normal RAM?

> Direct fb access allows any access to the framebuffer on the unichrome 
> to be intercepted by the memory controller. Unichrome and memory 
> controller are on the same die here, and since the unichrome uses part 
> of main ram for its memory, any access to the unichrome memory would 
> mean requests being made from the unichrome to the memory controller. 
> Without direct fb access, a lot of on chip bandwidth is effectively 
> thrown away sending fb accesses back and forth.

Ok, so we can live without it for now and then re-enable it later maybe with
some intelligent resource handling.

Thank you,
Rudolf
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAktBIGgACgkQ3J9wPJqZRNVslQCdFG5yhBXQ/2Q8Y1EPYU39YlD1
PTIAn3qycXh//BHP9RKxGE7KrsTnror2
=wIcG
-----END PGP SIGNATURE-----
Andrej Skirn - 2010-01-06 03:35:20
Rudolf Marek wrote:
> I think I can help you. It looks to me that bit 7 at offset 0xe1 is not set as
> default anymore (otherwise the code never worked?). You would need to set it
> early so VGA gets visible in "enable" phase. The patch fixes that.
Thanks, that bit does solve the problem with finding the video device. I 
discovered it indepently about the time you sent the e-mail; it's fairly 
well hidden in the actual datasheet, but BIOS porting guide for another 
VIA chipset I have mentions it. It also appears to be enabled on a 
commented-out line in raminit.c of all places; maybe this was commented 
out later? The other bits of the register set in the commented-out line 
don't seem to make sense.

Sadly, just enabling the vide device hasn't solved the legacy VGA-bios 
problem (although I suppose it would allow Linux to use it). Nothing 
comes on-screen from coreboot alone, and cb complains about various 
unimplemented interrupts. Appears that SeaBios vgahooks are needed to 
get the display adapter to initialize at all, and nothing comes 
on-screen until SeaBios runs the legacy VGA bios - apparently second 
time. Disabling either initialization, nothing comes on screen again. I 
don't see any mention of needing SeaBios to get the VGA working on the 
Wiki, although Peter Stuge suggested it. This poses a problem though, 
since I'd like to have the screen working as early as possible, and I'm 
not certain it's a good idea to initialize it twice in any case. I don't 
even see why it would work as it does, since coreboot seems to call the 
legacy VGA BIOS before it has initialized SeaBios, yet it would seem to 
be running the vgahooks from SeaBios at that point already.

Also vga_enable_console() will hang most of the time; cn700 for example 
has that call commented out with a remark of "VGA seems to work without 
this, but crash & burn with it". Disabling it seems to have no ill 
effects, so far.

>  Also I
> disabled the direct access FB because it was hardcoded. I forgotten what is for,
> maybe libv will know. It looks like the code sets VGA framebuffer size to 32MB
> (this is hardcoded elsewhere check the comments)
>   
On the board I'm testing this, if the Direct Access FB is disabled, it 
won't work at all. In fact, it only boots to screen if direct access 
framebuffer size is 16M (which the factory BIOS sets it to) and enabled. 
Usually it seems to hang right after SeaBios has ran the calibration 
loop in timer_setup().

Unfortunately it is hard to tell as the legacy VGA-bios will 
occassionally start doing random stuff (hang, print garbage on serial, 
report various random interrupts etc.) until the system is power-cycled. 
I don't normally do that as it confuses my USB serial-adapter and just 
do a PCI reset instead, making it hard to always tell what part is 
bugging. On http://www.coreboot.org/The_EPIA-M/MII section "Legacy VGA 
BIOS" it mentions something that is relevant to this (Legacy VGA BIOS 
enabling hardware interrupts, which it does, but interrut controller not 
being initialized). Unfortunately I can't find the patch it talks about, 
and it doesn't seem to be in the source tree.

Additionally, commenting out this section causes only garbage to come up 
on screen:

>  	printk_debug("VGA random fixup ...\n");
> > +
> > +
> > +	// why it does not rely on std resource system? 
> > +/*
> >  	pci_write_config8(dev, 0x04, 0x07);
> >  	pci_write_config8(dev, 0x0d, 0x20);
> >  	pci_write_config32(dev,0x10,0xd8000008);
> >  	pci_write_config32(dev,0x14,0xdc000000);
> > -
> > +*/

> Please try the attached patch I think it could fix it.
>
>   
Enabling the display device works. The rest of the patch doesn't work 
for me. So IF the Direct Access Framebuffer is set to 16M and enabled, 
the VGA resource registers are left hardcoded, vga_enable_console is not 
called, the Legacy VGA BIOS is initialized in both coreboot and SeaBios 
and the Legacy VGA BIOS doesn't bomb on random interrupt vector or 
something else bizarre, the SeaBios version string comes up on screen 
but then SeaBios hangs in do_boot, after printing B of "Booting from". 
Without VGA BIOS it gets past this point and starts loading the OS. 
(Without display I can't tell exactly how successful it is at this, though).

I'm presently in progress of verifying the resource settings for 
overlaps and other errors. I'd appreciate any pointers to examples or 
discussion of the "std resource system" and in particular how the 
resource allocation is supposed to be done in coreboot presently. The 
patch http://www.coreboot.org/The_EPIA-M/MII speaks about would also be 
helpful. Or any insight into the coreboot/SeaBios legacy VGA BIOS 
inter-operation.

Patch

Index: northbridge.c
===================================================================
--- northbridge.c	(revision 4978)
+++ northbridge.c	(working copy)
@@ -41,32 +41,32 @@ 
 	pci_write_config16(dev, 0x80, 0x610f);
 	pci_write_config32(dev, 0x88, 0x00000002);
 	
+	/* dont know if this is right ID fix it */
 	fb_dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x3122, 0);
 	if (fb_dev) {
-		/* Fixup GART and framebuffer addresses properly.
-		 * First setup frame buffer properly.
-		 */
-		//fb = pci_read_config32(dev, 0x10);       /* Base addres of framebuffer */
-		fb = 0xd0000000;
-		printk_debug("Frame buffer at %8x\n",fb);
-
-		c = pci_read_config8(dev, 0xe1) & 0xf0;  /* size of vga */
-		c |= fb>>28;  /* upper nibble of frame buffer address */
-		c = 0xdd;
-		pci_write_config8(dev, 0xe1, c);
-		c = 0x81;                                /* enable framebuffer */
-		pci_write_config8(dev, 0xe0, c);
+		/* step 1 enable  */
+		pci_write_config8(dev, 0xe1, 0x80);
+		/* step 2 enable the VGA without the direct access framebuffer - TOPMEM-32MB must get reserved */
+		pci_write_config8(dev, 0xe1, 0xd0);
 		pci_write_config8(dev, 0xe2, 0x42);      /* 'cos award does */
 	}
 }
 
 static void nullfunc(){}
 
+static void vga_en(struct device *dev)
+{
+	/* enable VGA, so the bridges gets VGA_EN and resources are set */
+	pci_write_config8(dev, 0xe1, 0x80);
+}
+
+
 static struct device_operations northbridge_operations = {
 	.read_resources   = nullfunc,
 	.set_resources    = pci_dev_set_resources,
 	.enable_resources = pci_dev_enable_resources,
-	.init             = northbridge_init
+	.init             = northbridge_init,
+	.enable           = vga_en,
 };
 
 static const struct pci_driver northbridge_driver __pci_driver = {
@@ -108,11 +108,15 @@ 
 	msr_t clocks1,clocks2,instructions,setup;
 
 	printk_debug("VGA random fixup ...\n");
+
+
+	// why it does not rely on std resource system? 
+/*
 	pci_write_config8(dev, 0x04, 0x07);
 	pci_write_config8(dev, 0x0d, 0x20);
 	pci_write_config32(dev,0x10,0xd8000008);
 	pci_write_config32(dev,0x14,0xdc000000);
-
+*/
 	// set up performnce counters for debugging vga init sequence
 	//setup.lo = 0x1c0; // count instructions
 	//wrmsr(0x187,setup);
@@ -254,6 +258,7 @@ 
 					ramregs[i]);
 		}
 		printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*16*1024);
+//it looks like one set 32MB of VGA?
 		tomk = rambits*16*1024 - 32768;
 		/* Compute the top of Low memory */
 		tolmk = pci_tolm >> 10;