drivers/gpu/drm/openchrome/openchrome_drv.h | 2 drivers/gpu/drm/openchrome/openchrome_fb.c | 884 ------------------------- drivers/gpu/drm/openchrome/openchrome_init.c | 939 +++++++++++++++++++++++++++ 3 files changed, 940 insertions(+), 885 deletions(-)
New commits: commit fba2aa548c6ff9cadd3e3b3fa0e23447cdb07768 Author: Kevin Brace <kevinbr...@gmx.com> Date: Tue Mar 19 11:15:19 2019 -0700 drm/openchrome: Move VRAM size detection code The code was transferred to openchrome_init.c since the code runs only once during initialization. Signed-off-by: Kevin Brace <kevinbr...@gmx.com> diff --git a/drivers/gpu/drm/openchrome/openchrome_drv.h b/drivers/gpu/drm/openchrome/openchrome_drv.h index 99f1a0a17ef4..cb4306d204c6 100644 --- a/drivers/gpu/drm/openchrome/openchrome_drv.h +++ b/drivers/gpu/drm/openchrome/openchrome_drv.h @@ -260,6 +260,7 @@ extern int via_hdmi_audio; extern struct ttm_bo_driver openchrome_bo_driver; +int openchrome_vram_detect(struct openchrome_drm_private *dev_private); int openchrome_mmio_init(struct openchrome_drm_private *dev_private); void openchrome_mmio_fini(struct openchrome_drm_private *dev_private); void openchrome_graphics_unlock( @@ -273,7 +274,6 @@ extern void via_engine_init(struct drm_device *dev); int openchrome_dev_pm_ops_suspend(struct device *dev); int openchrome_dev_pm_ops_resume(struct device *dev); -int openchrome_vram_detect(struct openchrome_drm_private *dev_private); extern int openchrome_vram_init( struct openchrome_drm_private *dev_private); extern void openchrome_vram_fini( diff --git a/drivers/gpu/drm/openchrome/openchrome_fb.c b/drivers/gpu/drm/openchrome/openchrome_fb.c index 22072669b4b3..420a49cadc48 100644 --- a/drivers/gpu/drm/openchrome/openchrome_fb.c +++ b/drivers/gpu/drm/openchrome/openchrome_fb.c @@ -28,890 +28,6 @@ #include "openchrome_drv.h" -static int cle266_mem_type(struct openchrome_drm_private *dev_private, - struct pci_dev *bridge) -{ - u8 type, fsb, freq; - int ret; - - ret = pci_read_config_byte(bridge, 0x54, &fsb); - if (ret) - return ret; - ret = pci_read_config_byte(bridge, 0x69, &freq); - if (ret) - return ret; - - freq >>= 6; - fsb >>= 6; - - /* FSB frequency */ - switch (fsb) { - case 0x01: /* 100MHz */ - switch (freq) { - case 0x00: - freq = 100; - break; - case 0x01: - freq = 133; - break; - case 0x02: - freq = 66; - break; - default: - freq = 0; - break; - } - break; - - case 0x02: /* 133 MHz */ - case 0x03: - switch (freq) { - case 0x00: - freq = 133; - break; - case 0x02: - freq = 100; - break; - default: - freq = 0; - break; - } - break; - default: - freq = 0; - break; - } - - ret = pci_read_config_byte(bridge, 0x60, &fsb); - if (ret) - return ret; - ret = pci_read_config_byte(bridge, 0xE3, &type); - if (ret) - return ret; - - /* On bank 2/3 */ - if (type & 0x02) - fsb >>= 2; - - /* Memory type */ - switch (fsb & 0x03) { - case 0x00: /* SDR */ - switch (freq) { - case 66: - dev_private->vram_type = VIA_MEM_SDR66; - break; - case 100: - dev_private->vram_type = VIA_MEM_SDR100; - break; - case 133: - dev_private->vram_type = VIA_MEM_SDR133; - default: - break; - } - break; - - case 0x02: /* DDR */ - switch (freq) { - case 100: - dev_private->vram_type = VIA_MEM_DDR_200; - break; - case 133: - dev_private->vram_type = VIA_MEM_DDR_266; - default: - break; - } - default: - break; - } - return ret; -} - -static int km400_mem_type(struct openchrome_drm_private *dev_private, - struct pci_dev *bridge) -{ - u8 fsb, freq, rev; - int ret; - - ret = pci_read_config_byte(bridge, 0xF6, &rev); - if (ret) - return ret; - ret = pci_read_config_byte(bridge, 0x54, &fsb); - if (ret) - return ret; - ret = pci_read_config_byte(bridge, 0x69, &freq); - if (ret) - return ret; - - freq >>= 6; - fsb >>= 6; - - /* KM400 */ - if (rev < 0x80) { - /* FSB frequency */ - switch (fsb) { - case 0x00: - switch (freq) { - case 0x00: - dev_private->vram_type = VIA_MEM_DDR_200; - break; - case 0x01: - dev_private->vram_type = VIA_MEM_DDR_266; - break; - case 0x02: - dev_private->vram_type = VIA_MEM_DDR_400; - break; - case 0x03: - dev_private->vram_type = VIA_MEM_DDR_333; - default: - break; - } - break; - - case 0x01: - switch (freq) { - case 0x00: - dev_private->vram_type = VIA_MEM_DDR_266; - break; - case 0x01: - dev_private->vram_type = VIA_MEM_DDR_333; - break; - case 0x02: - dev_private->vram_type = VIA_MEM_DDR_400; - default: - break; - } - break; - - case 0x02: - case 0x03: - switch (freq) { - case 0x00: - dev_private->vram_type = VIA_MEM_DDR_333; - break; - case 0x02: - dev_private->vram_type = VIA_MEM_DDR_400; - break; - case 0x03: - dev_private->vram_type = VIA_MEM_DDR_266; - default: - break; - } - default: - break; - } - } else { - /* KM400A */ - ret = pci_read_config_byte(bridge, 0x67, &rev); - if (ret) - return ret; - if (rev & 0x80) - freq |= 0x04; - - switch (fsb) { - case 0x00: - switch (freq) { - case 0x00: - dev_private->vram_type = VIA_MEM_DDR_200; - break; - case 0x01: - dev_private->vram_type = VIA_MEM_DDR_266; - break; - case 0x03: - dev_private->vram_type = VIA_MEM_DDR_333; - break; - case 0x07: - dev_private->vram_type = VIA_MEM_DDR_400; - break; - default: - dev_private->vram_type = VIA_MEM_NONE; - break; - } - break; - - case 0x01: - switch (freq) { - case 0x00: - dev_private->vram_type = VIA_MEM_DDR_266; - break; - case 0x01: - dev_private->vram_type = VIA_MEM_DDR_333; - break; - case 0x03: - dev_private->vram_type = VIA_MEM_DDR_400; - default: - break; - } - break; - - case 0x02: - switch (freq) { - case 0x00: - dev_private->vram_type = VIA_MEM_DDR_400; - break; - case 0x04: - dev_private->vram_type = VIA_MEM_DDR_333; - break; - case 0x06: - dev_private->vram_type = VIA_MEM_DDR_266; - default: - break; - } - break; - - case 0x03: - switch (freq) { - case 0x00: - dev_private->vram_type = VIA_MEM_DDR_333; - break; - case 0x01: - dev_private->vram_type = VIA_MEM_DDR_400; - break; - case 0x04: - dev_private->vram_type = VIA_MEM_DDR_266; - default: - break; - } - default: - break; - } - } - return ret; -} - -static int p4m800_mem_type(struct openchrome_drm_private *dev_private, - struct pci_bus *bus, - struct pci_dev *fn3) -{ - struct pci_dev *fn4 = pci_get_slot(bus, PCI_DEVFN(0, 4)); - int ret, freq = 0; - u8 type, fsb; - - /* VIA Scratch region */ - ret = pci_read_config_byte(fn4, 0xF3, &fsb); - if (ret) { - pci_dev_put(fn4); - return ret; - } - - switch (fsb >> 5) { - case 0: - freq = 3; /* 100 MHz */ - break; - case 1: - freq = 4; /* 133 MHz */ - break; - case 3: - freq = 5; /* 166 MHz */ - break; - case 2: - freq = 6; /* 200 MHz */ - break; - case 4: - freq = 7; /* 233 MHz */ - default: - break; - } - pci_dev_put(fn4); - - ret = pci_read_config_byte(fn3, 0x68, &type); - if (ret) - return ret; - type &= 0x0f; - - if (type & 0x02) - freq -= type >> 2; - else { - freq += type >> 2; - if (type & 0x01) - freq++; - } - - switch (freq) { - case 0x03: - dev_private->vram_type = VIA_MEM_DDR_200; - break; - case 0x04: - dev_private->vram_type = VIA_MEM_DDR_266; - break; - case 0x05: - dev_private->vram_type = VIA_MEM_DDR_333; - break; - case 0x06: - dev_private->vram_type = VIA_MEM_DDR_400; - default: - break; - } - return ret; -} - -static int km8xx_mem_type(struct openchrome_drm_private *dev_private) -{ - struct pci_dev *dram, *misc = NULL; - int ret = -ENXIO; - u8 type, tmp; - - dram = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL, NULL); - if (dram) { - misc = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_K8_NB_MISC, NULL); - - ret = pci_read_config_byte(misc, 0xFD, &type); - if (type) { - pci_read_config_byte(dram, 0x94, &type); - switch (type & 0x03) { - case 0x00: - dev_private->vram_type = VIA_MEM_DDR2_400; - break; - case 0x01: - dev_private->vram_type = VIA_MEM_DDR2_533; - break; - case 0x02: - dev_private->vram_type = VIA_MEM_DDR2_667; - break; - case 0x03: - dev_private->vram_type = VIA_MEM_DDR2_800; - default: - break; - } - } else { - ret = pci_read_config_byte(dram, 0x96, &type); - if (ret) - return ret; - type >>= 4; - type &= 0x07; - - switch (type) { - case 0x00: - dev_private->vram_type = VIA_MEM_DDR_200; - break; - case 0x02: - dev_private->vram_type = VIA_MEM_DDR_266; - break; - case 0x05: - dev_private->vram_type = VIA_MEM_DDR_333; - break; - case 0x07: - dev_private->vram_type = VIA_MEM_DDR_400; - default: - break; - } - } - } - - /* AMD 10h DRAM Controller */ - dram = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_DRAM, NULL); - if (dram) { - ret = pci_read_config_byte(misc, 0x94, &tmp); - if (ret) - return ret; - ret = pci_read_config_byte(misc, 0x95, &type); - if (ret) - return ret; - - if (type & 0x01) { /* DDR3 */ - switch (tmp & 0x07) { - case 0x03: - dev_private->vram_type = VIA_MEM_DDR3_800; - break; - case 0x04: - dev_private->vram_type = VIA_MEM_DDR3_1066; - break; - case 0x05: - dev_private->vram_type = VIA_MEM_DDR3_1333; - break; - case 0x06: - dev_private->vram_type = VIA_MEM_DDR3_1600; - default: - break; - } - } else { /* DDR2 */ - switch (tmp & 0x07) { - case 0x00: - dev_private->vram_type = VIA_MEM_DDR2_400; - break; - case 0x01: - dev_private->vram_type = VIA_MEM_DDR2_533; - break; - case 0x02: - dev_private->vram_type = VIA_MEM_DDR2_667; - break; - case 0x03: - dev_private->vram_type = VIA_MEM_DDR2_800; - break; - case 0x04: - dev_private->vram_type = VIA_MEM_DDR2_1066; - default: - break; - } - } - } - - /* AMD 11h DRAM Controller */ - dram = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_11H_NB_DRAM, NULL); - if (dram) { - ret = pci_read_config_byte(misc, 0x94, &type); - if (ret) - return ret; - - switch (tmp & 0x07) { - case 0x01: - dev_private->vram_type = VIA_MEM_DDR2_533; - break; - case 0x02: - dev_private->vram_type = VIA_MEM_DDR2_667; - break; - case 0x03: - dev_private->vram_type = VIA_MEM_DDR2_800; - default: - break; - } - } - return ret; -} - -static int cn400_mem_type(struct openchrome_drm_private *dev_private, - struct pci_bus *bus, - struct pci_dev *fn3) -{ - struct pci_dev *fn2 = pci_get_slot(bus, PCI_DEVFN(0, 2)); - int ret, freq = 0; - u8 type, fsb; - - ret = pci_read_config_byte(fn2, 0x54, &fsb); - if (ret) { - pci_dev_put(fn2); - return ret; - } - - switch (fsb >> 5) { - case 0: - freq = 3; /* 100 MHz */ - break; - case 1: - freq = 4; /* 133 MHz */ - break; - case 3: - freq = 5; /* 166 MHz */ - break; - case 2: - freq = 6; /* 200 MHz */ - break; - case 4: - freq = 7; /* 233 MHz */ - default: - break; - } - pci_dev_put(fn2); - - ret = pci_read_config_byte(fn3, 0x68, &type); - if (ret) - return ret; - type &= 0x0f; - - if (type & 0x01) - freq += 1 + (type >> 2); - else - freq -= 1 + (type >> 2); - - switch (freq) { - case 0x03: - dev_private->vram_type = VIA_MEM_DDR_200; - break; - case 0x04: - dev_private->vram_type = VIA_MEM_DDR_266; - break; - case 0x05: - dev_private->vram_type = VIA_MEM_DDR_333; - break; - case 0x06: - dev_private->vram_type = VIA_MEM_DDR_400; - default: - break; - } - return ret; -} - -static int cn700_mem_type(struct openchrome_drm_private *dev_private, - struct pci_dev *fn3) -{ - int ret; - u8 tmp; - - ret = pci_read_config_byte(fn3, 0x90, &tmp); - if (!ret) { - switch (tmp & 0x07) { - case 0x00: - dev_private->vram_type = VIA_MEM_DDR_200; - break; - case 0x01: - dev_private->vram_type = VIA_MEM_DDR_266; - break; - case 0x02: - dev_private->vram_type = VIA_MEM_DDR_333; - break; - case 0x03: - dev_private->vram_type = VIA_MEM_DDR_400; - break; - case 0x04: - dev_private->vram_type = VIA_MEM_DDR2_400; - break; - case 0x05: - dev_private->vram_type = VIA_MEM_DDR2_533; - default: - break; - } - } - return ret; -} - -static int cx700_mem_type(struct openchrome_drm_private *dev_private, - struct pci_dev *fn3) -{ - u8 type, clock; - int ret; - - ret = pci_read_config_byte(fn3, 0x90, &clock); - if (ret) - return ret; - ret = pci_read_config_byte(fn3, 0x6C, &type); - if (ret) - return ret; - type &= 0x40; - type >>= 6; - - switch (type) { - case 0: - switch (clock & 0x07) { - case 0: - dev_private->vram_type = VIA_MEM_DDR_200; - break; - case 1: - dev_private->vram_type = VIA_MEM_DDR_266; - break; - case 2: - dev_private->vram_type = VIA_MEM_DDR_333; - break; - case 3: - dev_private->vram_type = VIA_MEM_DDR_400; - default: - break; - } - break; - - case 1: - switch (clock & 0x07) { - case 3: - dev_private->vram_type = VIA_MEM_DDR2_400; - break; - case 4: - dev_private->vram_type = VIA_MEM_DDR2_533; - break; - case 5: - dev_private->vram_type = VIA_MEM_DDR2_667; - break; - case 6: - dev_private->vram_type = VIA_MEM_DDR2_800; - default: - break; - } - default: - break; - } - return ret; -} - -static int vx900_mem_type(struct openchrome_drm_private *dev_private, - struct pci_dev *fn3) -{ - int ret; - u8 clock, type, volt; - - ret = pci_read_config_byte(fn3, 0x90, &clock); - if (ret) - return ret; - ret = pci_read_config_byte(fn3, 0x6C, &type); - if (ret) - return ret; - volt = type; - type &= 0xC0; - type >>= 6; - volt &= 0x20; - volt >>= 5; - - switch (type) { - case 1: - switch (clock & 0x0F) { - case 0: - if (volt) - dev_private->vram_type = VIA_MEM_DDR2_800; - else - dev_private->vram_type = VIA_MEM_DDR2_533; - break; - case 4: - dev_private->vram_type = VIA_MEM_DDR2_533; - break; - case 5: - dev_private->vram_type = VIA_MEM_DDR2_667; - break; - case 6: - dev_private->vram_type = VIA_MEM_DDR2_800; - break; - case 7: - dev_private->vram_type = VIA_MEM_DDR2_1066; - default: - break; - } - break; - case 2: - switch (clock & 0x0F) { - case 0: - if (volt) - dev_private->vram_type = VIA_MEM_DDR3_800; - else - dev_private->vram_type = VIA_MEM_DDR3_533; - break; - case 4: - dev_private->vram_type = VIA_MEM_DDR3_533; - break; - case 5: - dev_private->vram_type = VIA_MEM_DDR3_667; - break; - case 6: - dev_private->vram_type = VIA_MEM_DDR3_800; - break; - case 7: - dev_private->vram_type = VIA_MEM_DDR3_1066; - default: - break; - } - break; - } - return ret; -} - -int openchrome_vram_detect(struct openchrome_drm_private *dev_private) -{ - struct drm_device *dev = dev_private->dev; - struct pci_dev *bridge = NULL; - struct pci_dev *fn3 = NULL; - char *name = "unknown"; - struct pci_bus *bus; - u8 size; - int ret = 0; - - DRM_DEBUG_KMS("Entered %s.\n", __func__); - - bus = pci_find_bus(0, 0); - if (bus == NULL) { - ret = -EINVAL; - goto out_err; - } - - bridge = pci_get_slot(bus, PCI_DEVFN(0, 0)); - fn3 = pci_get_slot(bus, PCI_DEVFN(0, 3)); - - if (!bridge) { - ret = -EINVAL; - DRM_ERROR("No host bridge found...\n"); - goto out_err; - } - - if (!fn3 && dev->pdev->device != PCI_DEVICE_ID_VIA_CLE266 - && dev->pdev->device != PCI_DEVICE_ID_VIA_KM400) { - ret = -EINVAL; - DRM_ERROR("No function 3 on host bridge...\n"); - goto out_err; - } - dev_private->vram_start = pci_resource_start(dev->pdev, 0); - - switch (bridge->device) { - - /* CLE266 */ - case PCI_DEVICE_ID_VIA_862X_0: - ret = cle266_mem_type(dev_private, bridge); - if (ret) - goto out_err; - - ret = pci_read_config_byte(bridge, 0xE1, &size); - if (ret) - goto out_err; - dev_private->vram_size = (1 << ((size & 0x70) >> 4)) << 20; - break; - - /* KM400 / KN400 / KM400A / KN400A */ - case PCI_DEVICE_ID_VIA_8378_0: - ret = km400_mem_type(dev_private, bridge); - - ret = pci_read_config_byte(bridge, 0xE1, &size); - if (ret) - goto out_err; - dev_private->vram_size = (1 << ((size & 0x70) >> 4)) << 20; - break; - - /* P4M800 */ - case PCI_DEVICE_ID_VIA_3296_0: - ret = p4m800_mem_type(dev_private, bus, fn3); - - ret = pci_read_config_byte(fn3, 0xA1, &size); - if (ret) - goto out_err; - dev_private->vram_size = (1 << ((size & 0x70) >> 4)) << 20; - break; - - /* K8M800 / K8N800 */ - case PCI_DEVICE_ID_VIA_8380_0: - /* K8M890 */ - case PCI_DEVICE_ID_VIA_VT3336: - ret = pci_read_config_byte(fn3, 0xA1, &size); - if (ret) - goto out_err; - dev_private->vram_size = (1 << ((size & 0x70) >> 4)) << 20; - - if (bridge->device == PCI_DEVICE_ID_VIA_VT3336) - dev_private->vram_size <<= 2; - - ret = km8xx_mem_type(dev_private); - if (ret) - goto out_err; - break; - - /* CN400 / PM800 / PM880 */ - case PCI_DEVICE_ID_VIA_PX8X0_0: - ret = pci_read_config_byte(fn3, 0xA1, &size); - if (ret) - goto out_err; - dev_private->vram_size = (1 << ((size & 0x70) >> 4)) << 20; - - ret = cn400_mem_type(dev_private, bus, fn3); - if (ret) - goto out_err; - break; - - /* P4M800CE / P4M800 Pro / VN800 / CN700 */ - case PCI_DEVICE_ID_VIA_P4M800CE: - /* P4M900 / VN896 / CN896 */ - case PCI_DEVICE_ID_VIA_VT3364: - ret = pci_read_config_byte(fn3, 0xA1, &size); - if (ret) - goto out_err; - dev_private->vram_size = (1 << ((size & 0x70) >> 4)) << 20; - - if (bridge->device != PCI_DEVICE_ID_VIA_P4M800CE) - dev_private->vram_size <<= 2; - - ret = cn700_mem_type(dev_private, fn3); - if (ret) - goto out_err; - break; - - /* CX700 / VX700 */ - case PCI_DEVICE_ID_VIA_VT3324: - /* P4M890 / VN890 */ - case PCI_DEVICE_ID_VIA_P4M890: - /* VX800 / VX820 */ - case PCI_DEVICE_ID_VIA_VT3353: - /* VX855 / VX875 */ - case PCI_DEVICE_ID_VIA_VT3409: - ret = pci_read_config_byte(fn3, 0xA1, &size); - if (ret) - goto out_err; - dev_private->vram_size = (1 << ((size & 0x70) >> 4)) << 22; - - ret = cx700_mem_type(dev_private, fn3); - if (ret) - goto out_err; - break; - - /* VX900 */ - case PCI_DEVICE_ID_VIA_VT3410: - dev_private->vram_start = pci_resource_start(dev->pdev, 2); - - ret = pci_read_config_byte(fn3, 0xA1, &size); - if (ret) - goto out_err; - dev_private->vram_size = (1 << ((size & 0x70) >> 4)) << 22; - - ret = vx900_mem_type(dev_private, fn3); - if (ret) - goto out_err; - break; - - default: - DRM_ERROR("Unknown north bridge device: 0x%04x\n", bridge->device); - goto out_err; - } - - switch (dev_private->vram_type) { - case VIA_MEM_SDR66: - name = "SDR 66"; - break; - case VIA_MEM_SDR100: - name = "SDR 100"; - break; - case VIA_MEM_SDR133: - name = "SDR 133"; - break; - case VIA_MEM_DDR_200: - name = "DDR 200"; - break; - case VIA_MEM_DDR_266: - name = "DDR 266"; - break; - case VIA_MEM_DDR_333: - name = "DDR 333"; - break; - case VIA_MEM_DDR_400: - name = "DDR 400"; - break; - case VIA_MEM_DDR2_400: - name = "DDR2 400"; - break; - case VIA_MEM_DDR2_533: - name = "DDR2 533"; - break; - case VIA_MEM_DDR2_667: - name = "DDR2 667"; - break; - case VIA_MEM_DDR2_800: - name = "DDR2 800"; - break; - case VIA_MEM_DDR2_1066: - name = "DDR2 1066"; - break; - case VIA_MEM_DDR3_533: - name = "DDR3 533"; - break; - case VIA_MEM_DDR3_667: - name = "DDR3 667"; - break; - case VIA_MEM_DDR3_800: - name = "DDR3 800"; - break; - case VIA_MEM_DDR3_1066: - name = "DDR3 1066"; - break; - case VIA_MEM_DDR3_1333: - name = "DDR3 1333"; - break; - case VIA_MEM_DDR3_1600: - name = "DDR3 1600"; - break; - default: - break; - } - - DRM_INFO("Found %s video RAM.\n", - name); -out_err: - if (bridge) - pci_dev_put(bridge); - if (fn3) - pci_dev_put(fn3); - - DRM_DEBUG_KMS("Exiting %s.\n", __func__); - return ret; -} - int openchrome_vram_init(struct openchrome_drm_private *dev_private) { int ret = 0; diff --git a/drivers/gpu/drm/openchrome/openchrome_init.c b/drivers/gpu/drm/openchrome/openchrome_init.c index 861cdaa4ea89..35a5423ea8cd 100644 --- a/drivers/gpu/drm/openchrome/openchrome_init.c +++ b/drivers/gpu/drm/openchrome/openchrome_init.c @@ -30,6 +30,945 @@ #include "openchrome_drv.h" +static int cle266_mem_type(struct openchrome_drm_private *dev_private, + struct pci_dev *bridge) +{ + u8 type, fsb, freq; + int ret; + + ret = pci_read_config_byte(bridge, 0x54, &fsb); + if (ret) + return ret; + ret = pci_read_config_byte(bridge, 0x69, &freq); + if (ret) + return ret; + + freq >>= 6; + fsb >>= 6; + + /* FSB frequency */ + switch (fsb) { + case 0x01: /* 100MHz */ + switch (freq) { + case 0x00: + freq = 100; + break; + case 0x01: + freq = 133; + break; + case 0x02: + freq = 66; + break; + default: + freq = 0; + break; + } + break; + + case 0x02: /* 133 MHz */ + case 0x03: + switch (freq) { + case 0x00: + freq = 133; + break; + case 0x02: + freq = 100; + break; + default: + freq = 0; + break; + } + break; + default: + freq = 0; + break; + } + + ret = pci_read_config_byte(bridge, 0x60, &fsb); + if (ret) + return ret; + ret = pci_read_config_byte(bridge, 0xE3, &type); + if (ret) + return ret; + + /* On bank 2/3 */ + if (type & 0x02) + fsb >>= 2; + + /* Memory type */ + switch (fsb & 0x03) { + case 0x00: /* SDR */ + switch (freq) { + case 66: + dev_private->vram_type = VIA_MEM_SDR66; + break; + case 100: + dev_private->vram_type = VIA_MEM_SDR100; + break; + case 133: + dev_private->vram_type = VIA_MEM_SDR133; + default: + break; + } + break; + + case 0x02: /* DDR */ + switch (freq) { + case 100: + dev_private->vram_type = VIA_MEM_DDR_200; + break; + case 133: + dev_private->vram_type = VIA_MEM_DDR_266; + default: + break; + } + default: + break; + } + return ret; +} + +static int km400_mem_type(struct openchrome_drm_private *dev_private, + struct pci_dev *bridge) +{ + u8 fsb, freq, rev; + int ret; + + ret = pci_read_config_byte(bridge, 0xF6, &rev); + if (ret) + return ret; + ret = pci_read_config_byte(bridge, 0x54, &fsb); + if (ret) + return ret; + ret = pci_read_config_byte(bridge, 0x69, &freq); + if (ret) + return ret; + + freq >>= 6; + fsb >>= 6; + + /* KM400 */ + if (rev < 0x80) { + /* FSB frequency */ + switch (fsb) { + case 0x00: + switch (freq) { + case 0x00: + dev_private->vram_type = + VIA_MEM_DDR_200; + break; + case 0x01: + dev_private->vram_type = + VIA_MEM_DDR_266; + break; + case 0x02: + dev_private->vram_type = + VIA_MEM_DDR_400; + break; + case 0x03: + dev_private->vram_type = + VIA_MEM_DDR_333; + default: + break; + } + break; + + case 0x01: + switch (freq) { + case 0x00: + dev_private->vram_type = + VIA_MEM_DDR_266; + break; + case 0x01: + dev_private->vram_type = + VIA_MEM_DDR_333; + break; + case 0x02: + dev_private->vram_type = + VIA_MEM_DDR_400; + default: + break; + } + break; + + case 0x02: + case 0x03: + switch (freq) { + case 0x00: + dev_private->vram_type = VIA_MEM_DDR_333; + break; + case 0x02: + dev_private->vram_type = + VIA_MEM_DDR_400; + break; + case 0x03: + dev_private->vram_type = + VIA_MEM_DDR_266; + default: + break; + } + default: + break; + } + } else { + /* KM400A */ + ret = pci_read_config_byte(bridge, 0x67, &rev); + if (ret) + return ret; + if (rev & 0x80) + freq |= 0x04; + + switch (fsb) { + case 0x00: + switch (freq) { + case 0x00: + dev_private->vram_type = + VIA_MEM_DDR_200; + break; + case 0x01: + dev_private->vram_type = + VIA_MEM_DDR_266; + break; + case 0x03: + dev_private->vram_type = + VIA_MEM_DDR_333; + break; + case 0x07: + dev_private->vram_type = + VIA_MEM_DDR_400; + break; + default: + dev_private->vram_type = VIA_MEM_NONE; + break; + } + break; + + case 0x01: + switch (freq) { + case 0x00: + dev_private->vram_type = + VIA_MEM_DDR_266; + break; + case 0x01: + dev_private->vram_type = + VIA_MEM_DDR_333; + break; + case 0x03: + dev_private->vram_type = + VIA_MEM_DDR_400; + default: + break; + } + break; + + case 0x02: + switch (freq) { + case 0x00: + dev_private->vram_type = + VIA_MEM_DDR_400; + break; + case 0x04: + dev_private->vram_type = + VIA_MEM_DDR_333; + break; + case 0x06: + dev_private->vram_type = + VIA_MEM_DDR_266; + default: + break; + } + break; + + case 0x03: + switch (freq) { + case 0x00: + dev_private->vram_type = + VIA_MEM_DDR_333; + break; + case 0x01: + dev_private->vram_type = + VIA_MEM_DDR_400; + break; + case 0x04: + dev_private->vram_type = + VIA_MEM_DDR_266; + default: + break; + } + default: + break; + } + } + return ret; +} + +static int p4m800_mem_type(struct openchrome_drm_private *dev_private, + struct pci_bus *bus, + struct pci_dev *fn3) +{ + struct pci_dev *fn4 = pci_get_slot(bus, PCI_DEVFN(0, 4)); + int ret, freq = 0; + u8 type, fsb; + + /* VIA Scratch region */ + ret = pci_read_config_byte(fn4, 0xF3, &fsb); + if (ret) { + pci_dev_put(fn4); + return ret; + } + + switch (fsb >> 5) { + case 0: + freq = 3; /* 100 MHz */ + break; + case 1: + freq = 4; /* 133 MHz */ + break; + case 3: + freq = 5; /* 166 MHz */ + break; + case 2: + freq = 6; /* 200 MHz */ + break; + case 4: + freq = 7; /* 233 MHz */ + default: + break; + } + pci_dev_put(fn4); + + ret = pci_read_config_byte(fn3, 0x68, &type); + if (ret) + return ret; + type &= 0x0f; + + if (type & 0x02) + freq -= type >> 2; + else { + freq += type >> 2; + if (type & 0x01) + freq++; + } + + switch (freq) { + case 0x03: + dev_private->vram_type = VIA_MEM_DDR_200; + break; + case 0x04: + dev_private->vram_type = VIA_MEM_DDR_266; + break; + case 0x05: + dev_private->vram_type = VIA_MEM_DDR_333; + break; + case 0x06: + dev_private->vram_type = VIA_MEM_DDR_400; + default: + break; + } + return ret; +} + +static int km8xx_mem_type(struct openchrome_drm_private *dev_private) +{ + struct pci_dev *dram, *misc = NULL; + int ret = -ENXIO; + u8 type, tmp; + + dram = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_K8_NB_MEMCTL, NULL); + if (dram) { + misc = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_K8_NB_MISC, NULL); + + ret = pci_read_config_byte(misc, 0xFD, &type); + if (type) { + pci_read_config_byte(dram, 0x94, &type); + switch (type & 0x03) { + case 0x00: + dev_private->vram_type = + VIA_MEM_DDR2_400; + break; + case 0x01: + dev_private->vram_type = + VIA_MEM_DDR2_533; + break; + case 0x02: + dev_private->vram_type = + VIA_MEM_DDR2_667; + break; + case 0x03: + dev_private->vram_type = + VIA_MEM_DDR2_800; + default: + break; + } + } else { + ret = pci_read_config_byte(dram, 0x96, &type); + if (ret) + return ret; + type >>= 4; + type &= 0x07; + + switch (type) { + case 0x00: + dev_private->vram_type = + VIA_MEM_DDR_200; + break; + case 0x02: + dev_private->vram_type = + VIA_MEM_DDR_266; + break; + case 0x05: + dev_private->vram_type = + VIA_MEM_DDR_333; + break; + case 0x07: + dev_private->vram_type = + VIA_MEM_DDR_400; + default: + break; + } + } + } + + /* AMD 10h DRAM Controller */ + dram = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_10H_NB_DRAM, NULL); + if (dram) { + ret = pci_read_config_byte(misc, 0x94, &tmp); + if (ret) + return ret; + ret = pci_read_config_byte(misc, 0x95, &type); + if (ret) + return ret; + + if (type & 0x01) { /* DDR3 */ + switch (tmp & 0x07) { + case 0x03: + dev_private->vram_type = + VIA_MEM_DDR3_800; + break; + case 0x04: + dev_private->vram_type = + VIA_MEM_DDR3_1066; + break; + case 0x05: + dev_private->vram_type = + VIA_MEM_DDR3_1333; + break; + case 0x06: + dev_private->vram_type = + VIA_MEM_DDR3_1600; + default: + break; + } + } else { /* DDR2 */ + switch (tmp & 0x07) { + case 0x00: + dev_private->vram_type = + VIA_MEM_DDR2_400; + break; + case 0x01: + dev_private->vram_type = + VIA_MEM_DDR2_533; + break; + case 0x02: + dev_private->vram_type = + VIA_MEM_DDR2_667; + break; + case 0x03: + dev_private->vram_type = + VIA_MEM_DDR2_800; + break; + case 0x04: + dev_private->vram_type = + VIA_MEM_DDR2_1066; + default: + break; + } + } + } + + /* AMD 11h DRAM Controller */ + dram = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_11H_NB_DRAM, NULL); + if (dram) { + ret = pci_read_config_byte(misc, 0x94, &type); + if (ret) + return ret; + + switch (tmp & 0x07) { + case 0x01: + dev_private->vram_type = VIA_MEM_DDR2_533; + break; + case 0x02: + dev_private->vram_type = VIA_MEM_DDR2_667; + break; + case 0x03: + dev_private->vram_type = VIA_MEM_DDR2_800; + default: + break; + } + } + return ret; +} + +static int cn400_mem_type(struct openchrome_drm_private *dev_private, + struct pci_bus *bus, + struct pci_dev *fn3) +{ + struct pci_dev *fn2 = pci_get_slot(bus, PCI_DEVFN(0, 2)); + int ret, freq = 0; + u8 type, fsb; + + ret = pci_read_config_byte(fn2, 0x54, &fsb); + if (ret) { + pci_dev_put(fn2); + return ret; + } + + switch (fsb >> 5) { + case 0: + freq = 3; /* 100 MHz */ + break; + case 1: + freq = 4; /* 133 MHz */ + break; + case 3: + freq = 5; /* 166 MHz */ + break; + case 2: + freq = 6; /* 200 MHz */ + break; + case 4: + freq = 7; /* 233 MHz */ + default: + break; + } + pci_dev_put(fn2); + + ret = pci_read_config_byte(fn3, 0x68, &type); + if (ret) + return ret; + type &= 0x0f; + + if (type & 0x01) + freq += 1 + (type >> 2); + else + freq -= 1 + (type >> 2); + + switch (freq) { + case 0x03: + dev_private->vram_type = VIA_MEM_DDR_200; + break; + case 0x04: + dev_private->vram_type = VIA_MEM_DDR_266; + break; + case 0x05: + dev_private->vram_type = VIA_MEM_DDR_333; + break; + case 0x06: + dev_private->vram_type = VIA_MEM_DDR_400; + default: + break; + } + return ret; +} + +static int cn700_mem_type(struct openchrome_drm_private *dev_private, + struct pci_dev *fn3) +{ + int ret; + u8 tmp; + + ret = pci_read_config_byte(fn3, 0x90, &tmp); + if (!ret) { + switch (tmp & 0x07) { + case 0x00: + dev_private->vram_type = VIA_MEM_DDR_200; + break; + case 0x01: + dev_private->vram_type = VIA_MEM_DDR_266; + break; + case 0x02: + dev_private->vram_type = VIA_MEM_DDR_333; + break; + case 0x03: + dev_private->vram_type = VIA_MEM_DDR_400; + break; + case 0x04: + dev_private->vram_type = VIA_MEM_DDR2_400; + break; + case 0x05: + dev_private->vram_type = VIA_MEM_DDR2_533; + default: + break; + } + } + return ret; +} + +static int cx700_mem_type(struct openchrome_drm_private *dev_private, + struct pci_dev *fn3) +{ + u8 type, clock; + int ret; + + ret = pci_read_config_byte(fn3, 0x90, &clock); + if (ret) + return ret; + ret = pci_read_config_byte(fn3, 0x6C, &type); + if (ret) + return ret; + type &= 0x40; + type >>= 6; + + switch (type) { + case 0: + switch (clock & 0x07) { + case 0: + dev_private->vram_type = VIA_MEM_DDR_200; + break; + case 1: + dev_private->vram_type = VIA_MEM_DDR_266; + break; + case 2: + dev_private->vram_type = VIA_MEM_DDR_333; + break; + case 3: + dev_private->vram_type = VIA_MEM_DDR_400; + default: + break; + } + break; + + case 1: + switch (clock & 0x07) { + case 3: + dev_private->vram_type = VIA_MEM_DDR2_400; + break; + case 4: + dev_private->vram_type = VIA_MEM_DDR2_533; + break; + case 5: + dev_private->vram_type = VIA_MEM_DDR2_667; + break; + case 6: + dev_private->vram_type = VIA_MEM_DDR2_800; + default: + break; + } + default: + break; + } + return ret; +} + +static int vx900_mem_type(struct openchrome_drm_private *dev_private, + struct pci_dev *fn3) +{ + int ret; + u8 clock, type, volt; + + ret = pci_read_config_byte(fn3, 0x90, &clock); + if (ret) + return ret; + ret = pci_read_config_byte(fn3, 0x6C, &type); + if (ret) + return ret; + volt = type; + type &= 0xC0; + type >>= 6; + volt &= 0x20; + volt >>= 5; + + switch (type) { + case 1: + switch (clock & 0x0F) { + case 0: + if (volt) + dev_private->vram_type = + VIA_MEM_DDR2_800; + else + dev_private->vram_type = + VIA_MEM_DDR2_533; + break; + case 4: + dev_private->vram_type = VIA_MEM_DDR2_533; + break; + case 5: + dev_private->vram_type = VIA_MEM_DDR2_667; + break; + case 6: + dev_private->vram_type = VIA_MEM_DDR2_800; + break; + case 7: + dev_private->vram_type = VIA_MEM_DDR2_1066; + default: + break; + } + break; + case 2: + switch (clock & 0x0F) { + case 0: + if (volt) + dev_private->vram_type = + VIA_MEM_DDR3_800; + else + dev_private->vram_type = + VIA_MEM_DDR3_533; + break; + case 4: + dev_private->vram_type = VIA_MEM_DDR3_533; + break; + case 5: + dev_private->vram_type = VIA_MEM_DDR3_667; + break; + case 6: + dev_private->vram_type = VIA_MEM_DDR3_800; + break; + case 7: + dev_private->vram_type = VIA_MEM_DDR3_1066; + default: + break; + } + break; + } + return ret; +} + +int openchrome_vram_detect(struct openchrome_drm_private *dev_private) +{ + struct drm_device *dev = dev_private->dev; + struct pci_dev *bridge = NULL; + struct pci_dev *fn3 = NULL; + char *name = "unknown"; + struct pci_bus *bus; + u8 size; + int ret = 0; + + DRM_DEBUG_KMS("Entered %s.\n", __func__); + + bus = pci_find_bus(0, 0); + if (bus == NULL) { + ret = -EINVAL; + goto out_err; + } + + bridge = pci_get_slot(bus, PCI_DEVFN(0, 0)); + fn3 = pci_get_slot(bus, PCI_DEVFN(0, 3)); + + if (!bridge) { + ret = -EINVAL; + DRM_ERROR("No host bridge found...\n"); + goto out_err; + } + + if (!fn3 && dev->pdev->device != PCI_DEVICE_ID_VIA_CLE266 + && dev->pdev->device != PCI_DEVICE_ID_VIA_KM400) { + ret = -EINVAL; + DRM_ERROR("No function 3 on host bridge...\n"); + goto out_err; + } + dev_private->vram_start = pci_resource_start(dev->pdev, 0); + + switch (bridge->device) { + + /* CLE266 */ + case PCI_DEVICE_ID_VIA_862X_0: + ret = cle266_mem_type(dev_private, bridge); + if (ret) + goto out_err; + + ret = pci_read_config_byte(bridge, 0xE1, &size); + if (ret) + goto out_err; + dev_private->vram_size = + (1 << ((size & 0x70) >> 4)) << 20; + break; + + /* KM400 / KN400 / KM400A / KN400A */ + case PCI_DEVICE_ID_VIA_8378_0: + ret = km400_mem_type(dev_private, bridge); + + ret = pci_read_config_byte(bridge, 0xE1, &size); + if (ret) + goto out_err; + dev_private->vram_size = + (1 << ((size & 0x70) >> 4)) << 20; + break; + + /* P4M800 */ + case PCI_DEVICE_ID_VIA_3296_0: + ret = p4m800_mem_type(dev_private, bus, fn3); + + ret = pci_read_config_byte(fn3, 0xA1, &size); + if (ret) + goto out_err; + dev_private->vram_size = + (1 << ((size & 0x70) >> 4)) << 20; + break; + + /* K8M800 / K8N800 */ + case PCI_DEVICE_ID_VIA_8380_0: + /* K8M890 */ + case PCI_DEVICE_ID_VIA_VT3336: + ret = pci_read_config_byte(fn3, 0xA1, &size); + if (ret) + goto out_err; + dev_private->vram_size = + (1 << ((size & 0x70) >> 4)) << 20; + + if (bridge->device == PCI_DEVICE_ID_VIA_VT3336) + dev_private->vram_size <<= 2; + + ret = km8xx_mem_type(dev_private); + if (ret) + goto out_err; + break; + + /* CN400 / PM800 / PM880 */ + case PCI_DEVICE_ID_VIA_PX8X0_0: + ret = pci_read_config_byte(fn3, 0xA1, &size); + if (ret) + goto out_err; + dev_private->vram_size = + (1 << ((size & 0x70) >> 4)) << 20; + + ret = cn400_mem_type(dev_private, bus, fn3); + if (ret) + goto out_err; + break; + + /* P4M800CE / P4M800 Pro / VN800 / CN700 */ + case PCI_DEVICE_ID_VIA_P4M800CE: + /* P4M900 / VN896 / CN896 */ + case PCI_DEVICE_ID_VIA_VT3364: + ret = pci_read_config_byte(fn3, 0xA1, &size); + if (ret) + goto out_err; + dev_private->vram_size = + (1 << ((size & 0x70) >> 4)) << 20; + + if (bridge->device != PCI_DEVICE_ID_VIA_P4M800CE) + dev_private->vram_size <<= 2; + + ret = cn700_mem_type(dev_private, fn3); + if (ret) + goto out_err; + break; + + /* CX700 / VX700 */ + case PCI_DEVICE_ID_VIA_VT3324: + /* P4M890 / VN890 */ + case PCI_DEVICE_ID_VIA_P4M890: + /* VX800 / VX820 */ + case PCI_DEVICE_ID_VIA_VT3353: + /* VX855 / VX875 */ + case PCI_DEVICE_ID_VIA_VT3409: + ret = pci_read_config_byte(fn3, 0xA1, &size); + if (ret) + goto out_err; + dev_private->vram_size = + (1 << ((size & 0x70) >> 4)) << 22; + + ret = cx700_mem_type(dev_private, fn3); + if (ret) + goto out_err; + break; + + /* VX900 */ + case PCI_DEVICE_ID_VIA_VT3410: + dev_private->vram_start = + pci_resource_start(dev->pdev, 2); + + ret = pci_read_config_byte(fn3, 0xA1, &size); + if (ret) + goto out_err; + dev_private->vram_size = + (1 << ((size & 0x70) >> 4)) << 22; + + ret = vx900_mem_type(dev_private, fn3); + if (ret) + goto out_err; + break; + + default: + DRM_ERROR("Unknown north bridge device: 0x%04x\n", + bridge->device); + goto out_err; + } + + switch (dev_private->vram_type) { + case VIA_MEM_SDR66: + name = "SDR 66"; + break; + case VIA_MEM_SDR100: + name = "SDR 100"; + break; + case VIA_MEM_SDR133: + name = "SDR 133"; + break; + case VIA_MEM_DDR_200: + name = "DDR 200"; + break; + case VIA_MEM_DDR_266: + name = "DDR 266"; + break; + case VIA_MEM_DDR_333: + name = "DDR 333"; + break; + case VIA_MEM_DDR_400: + name = "DDR 400"; + break; + case VIA_MEM_DDR2_400: + name = "DDR2 400"; + break; + case VIA_MEM_DDR2_533: + name = "DDR2 533"; + break; + case VIA_MEM_DDR2_667: + name = "DDR2 667"; + break; + case VIA_MEM_DDR2_800: + name = "DDR2 800"; + break; + case VIA_MEM_DDR2_1066: + name = "DDR2 1066"; + break; + case VIA_MEM_DDR3_533: + name = "DDR3 533"; + break; + case VIA_MEM_DDR3_667: + name = "DDR3 667"; + break; + case VIA_MEM_DDR3_800: + name = "DDR3 800"; + break; + case VIA_MEM_DDR3_1066: + name = "DDR3 1066"; + break; + case VIA_MEM_DDR3_1333: + name = "DDR3 1333"; + break; + case VIA_MEM_DDR3_1600: + name = "DDR3 1600"; + break; + default: + break; + } + + DRM_INFO("Found %s video RAM.\n", name); +out_err: + if (bridge) + pci_dev_put(bridge); + if (fn3) + pci_dev_put(fn3); + + DRM_DEBUG_KMS("Exiting %s.\n", __func__); + return ret; +} + int openchrome_mmio_init( struct openchrome_drm_private *dev_private) { _______________________________________________ openchrome-devel mailing list openchrome-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/openchrome-devel