viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
}
+static u_int16_t via_function3[] = {
+ CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3,
+ CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3,
+ P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3,
+};
+
+/* Get the BIOS-configured framebuffer size from PCI configuration space
+ * of function 3 in the respective chipset */
int viafb_get_fb_size_from_pci(void)
{
- unsigned long configid, deviceid, FBSize = 0;
- int VideoMemSize;
- int DeviceFound = false;
-
- for (configid = 0x80000000; configid < 0x80010800; configid += 0x100) {
- outl(configid, (unsigned long)0xCF8);
- deviceid = (inl((unsigned long)0xCFC) >> 16) & 0xffff;
-
- switch (deviceid) {
- case CLE266:
- case KM400:
- outl(configid + 0xE0, (unsigned long)0xCF8);
- FBSize = inl((unsigned long)0xCFC);
- DeviceFound = true; /* Found device id */
- break;
+ int i;
+ u_int8_t offset = 0;
+ u_int32_t FBSize;
+ u_int32_t VideoMemSize;
+
+ /* search for the "FUNCTION3" device in this chipset */
+ for (i = 0; i < ARRAY_SIZE(via_function3); i++) {
+ struct pci_dev *pdev;
+
+ pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i],
+ NULL);
+ if (!pdev)
+ continue;
+
+ DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device);
+ switch (pdev->device) {
+ case CLE266_FUNCTION3:
+ case KM400_FUNCTION3:
+ offset = 0xE0;
+ break;
case CN400_FUNCTION3:
case CN700_FUNCTION3:
case CX700_FUNCTION3:
case P4M900_FUNCTION3:
case VX800_FUNCTION3:
case VX855_FUNCTION3:
- /*case CN750_FUNCTION3: */
- outl(configid + 0xA0, (unsigned long)0xCF8);
- FBSize = inl((unsigned long)0xCFC);
- DeviceFound = true; /* Found device id */
- break;
-
- default:
+ /*case CN750_FUNCTION3: */
+ offset = 0xA0;
break;
}
- if (DeviceFound)
+ if (!offset)
break;
+
+ pci_read_config_dword(pdev, offset, &FBSize);
+ pci_dev_put(pdev);
}
- DEBUG_MSG(KERN_INFO "Device ID = %lx\n", deviceid);
+ if (!offset) {
+ printk(KERN_ERR "cannot determine framebuffer size\n");
+ return -EIO;
+ }
FBSize = FBSize & 0x00007000;
DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
viafb_init_chip_info(pdev, ent);
viaparinfo->fbmem = pci_resource_start(pdev, 0);
viaparinfo->memsize = viafb_get_fb_size_from_pci();
+ if (viaparinfo->memsize < 0) {
+ rc = viaparinfo->memsize;
+ goto out_delete_i2c;
+ }
viaparinfo->fbmem_free = viaparinfo->memsize;
viaparinfo->fbmem_used = 0;
viafbinfo->screen_base = ioremap_nocache(viaparinfo->fbmem,