/* * A simple tool trys to get current switchable graphics feature status. * * zhenyu.z.wang@intel.com */ #include #include #include #include #define GPIO_BASE_MASK 0xffc0 #define GPIO_DGPU_SELECT (52-32) #define GPIO_USE_SEL_32 0x0 #define GPIO_IO_SEL_32 0x4 #define GPIO_LVL_32 0xc #define GPIO_USE_SEL_64 0x30 #define GPIO_IO_SEL_64 0x34 #define GPIO_LVL_64 0x38 int main() { struct pci_device *pdev = NULL; uint16_t gpio_base; uint8_t gpio_ctl; uint8_t gpio_len; int i; uint32_t use_sel2; uint32_t io_sel2; uint32_t level_sel2; pci_system_init(); pdev = pci_device_find_by_slot (0, 0, 31, 0); if (!pdev) { fprintf(stderr, "Can't open LPC device.\n"); exit(1); } pci_device_cfg_read_u16(pdev, &gpio_base, 0x48); /* Desktop has 64 bytes, but Mobile has 128 bytes */ /* Check base address is not right to determine size of IO range, always default to 64 bytes. */ #if 0 if (gpio_base & (1 << 6)) gpio_len = 64; else gpio_len = 128; #endif gpio_len = 64; gpio_base &= GPIO_BASE_MASK; printf("GPIO Base address: 0x%x , Length: %d bytes\n", gpio_base, gpio_len); pci_device_cfg_read_u8(pdev, &gpio_ctl, 0x4c); if ((gpio_ctl & (1 << 4)) == 0) { fprintf(stderr, "GPIO I/O range is disabled, try to enable it...\n"); pci_device_cfg_write_u8(pdev, (gpio_ctl | (1 << 4)), 0x4c); } if (iopl(3) != 0) { fprintf(stderr, "Can't get ioperm.\n"); exit(1); } #if 0 printf("GPIO I/O space dump:\n"); for (i = 0; i < gpio_len; i += 4) printf("0x%x: 0x%08x\n", i, inl(gpio_base+i)); #endif use_sel2 = inl(gpio_base + GPIO_USE_SEL_64); if ((use_sel2 & (1 << GPIO_DGPU_SELECT)) == 0) { fprintf(stderr, "GPIO52 (dGPU_select) is used for native function instead of GPIO...\n"); exit(1); } io_sel2 = inl(gpio_base + GPIO_IO_SEL_64); if ((io_sel2 & (1 << GPIO_DGPU_SELECT)) != 0) { printf("GPIO52 (dGPU_select) is _not_ programmed as output...\n"); exit(1); } level_sel2 = inl(gpio_base + GPIO_LVL_64); printf("Display Mux control is from %s\n", ((level_sel2 & (1 << GPIO_DGPU_SELECT)) == 0) ? "dGPU" : "iGPU"); exit(0); }