diff options
189 files changed, 7662 insertions, 3460 deletions
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 0a4185279417..b130df0a1958 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <asm/smp.h> | 12 | #include <asm/smp.h> |
| 13 | #include "agp.h" | 13 | #include "agp.h" |
| 14 | #include "intel-agp.h" | 14 | #include "intel-agp.h" |
| 15 | #include <drm/intel-gtt.h> | ||
| 15 | 16 | ||
| 16 | int intel_agp_enabled; | 17 | int intel_agp_enabled; |
| 17 | EXPORT_SYMBOL(intel_agp_enabled); | 18 | EXPORT_SYMBOL(intel_agp_enabled); |
| @@ -747,7 +748,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, | |||
| 747 | 748 | ||
| 748 | bridge->capndx = cap_ptr; | 749 | bridge->capndx = cap_ptr; |
| 749 | 750 | ||
| 750 | if (intel_gmch_probe(pdev, bridge)) | 751 | if (intel_gmch_probe(pdev, NULL, bridge)) |
| 751 | goto found_gmch; | 752 | goto found_gmch; |
| 752 | 753 | ||
| 753 | for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { | 754 | for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { |
| @@ -824,7 +825,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) | |||
| 824 | 825 | ||
| 825 | agp_remove_bridge(bridge); | 826 | agp_remove_bridge(bridge); |
| 826 | 827 | ||
| 827 | intel_gmch_remove(pdev); | 828 | intel_gmch_remove(); |
| 828 | 829 | ||
| 829 | agp_put_bridge(bridge); | 830 | agp_put_bridge(bridge); |
| 830 | } | 831 | } |
| @@ -902,17 +903,6 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
| 902 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), | 903 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), |
| 903 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), | 904 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), |
| 904 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), | 905 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), |
| 905 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB), | ||
| 906 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB), | ||
| 907 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB), | ||
| 908 | ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB), | ||
| 909 | ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB), | ||
| 910 | ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB), | ||
| 911 | ID(PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB), | ||
| 912 | ID(PCI_DEVICE_ID_INTEL_HASWELL_HB), | ||
| 913 | ID(PCI_DEVICE_ID_INTEL_HASWELL_M_HB), | ||
| 914 | ID(PCI_DEVICE_ID_INTEL_HASWELL_S_HB), | ||
| 915 | ID(PCI_DEVICE_ID_INTEL_HASWELL_E_HB), | ||
| 916 | { } | 906 | { } |
| 917 | }; | 907 | }; |
| 918 | 908 | ||
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 8e2d9140f300..57226424690c 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h | |||
| @@ -251,7 +251,4 @@ | |||
| 251 | #define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */ | 251 | #define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */ |
| 252 | #define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 | 252 | #define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 |
| 253 | 253 | ||
| 254 | int intel_gmch_probe(struct pci_dev *pdev, | ||
| 255 | struct agp_bridge_data *bridge); | ||
| 256 | void intel_gmch_remove(struct pci_dev *pdev); | ||
| 257 | #endif | 254 | #endif |
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 1237e7575c3f..9ed92ef5829b 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c | |||
| @@ -66,7 +66,6 @@ static struct _intel_private { | |||
| 66 | struct pci_dev *bridge_dev; | 66 | struct pci_dev *bridge_dev; |
| 67 | u8 __iomem *registers; | 67 | u8 __iomem *registers; |
| 68 | phys_addr_t gtt_bus_addr; | 68 | phys_addr_t gtt_bus_addr; |
| 69 | phys_addr_t gma_bus_addr; | ||
| 70 | u32 PGETBL_save; | 69 | u32 PGETBL_save; |
| 71 | u32 __iomem *gtt; /* I915G */ | 70 | u32 __iomem *gtt; /* I915G */ |
| 72 | bool clear_fake_agp; /* on first access via agp, fill with scratch */ | 71 | bool clear_fake_agp; /* on first access via agp, fill with scratch */ |
| @@ -76,6 +75,7 @@ static struct _intel_private { | |||
| 76 | struct resource ifp_resource; | 75 | struct resource ifp_resource; |
| 77 | int resource_valid; | 76 | int resource_valid; |
| 78 | struct page *scratch_page; | 77 | struct page *scratch_page; |
| 78 | int refcount; | ||
| 79 | } intel_private; | 79 | } intel_private; |
| 80 | 80 | ||
| 81 | #define INTEL_GTT_GEN intel_private.driver->gen | 81 | #define INTEL_GTT_GEN intel_private.driver->gen |
| @@ -648,6 +648,7 @@ static void intel_gtt_cleanup(void) | |||
| 648 | 648 | ||
| 649 | static int intel_gtt_init(void) | 649 | static int intel_gtt_init(void) |
| 650 | { | 650 | { |
| 651 | u32 gma_addr; | ||
| 651 | u32 gtt_map_size; | 652 | u32 gtt_map_size; |
| 652 | int ret; | 653 | int ret; |
| 653 | 654 | ||
| @@ -694,6 +695,15 @@ static int intel_gtt_init(void) | |||
| 694 | return ret; | 695 | return ret; |
| 695 | } | 696 | } |
| 696 | 697 | ||
| 698 | if (INTEL_GTT_GEN <= 2) | ||
| 699 | pci_read_config_dword(intel_private.pcidev, I810_GMADDR, | ||
| 700 | &gma_addr); | ||
| 701 | else | ||
| 702 | pci_read_config_dword(intel_private.pcidev, I915_GMADDR, | ||
| 703 | &gma_addr); | ||
| 704 | |||
| 705 | intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); | ||
| 706 | |||
| 697 | return 0; | 707 | return 0; |
| 698 | } | 708 | } |
| 699 | 709 | ||
| @@ -767,20 +777,10 @@ static void i830_write_entry(dma_addr_t addr, unsigned int entry, | |||
| 767 | writel(addr | pte_flags, intel_private.gtt + entry); | 777 | writel(addr | pte_flags, intel_private.gtt + entry); |
| 768 | } | 778 | } |
| 769 | 779 | ||
| 770 | static bool intel_enable_gtt(void) | 780 | bool intel_enable_gtt(void) |
| 771 | { | 781 | { |
| 772 | u32 gma_addr; | ||
| 773 | u8 __iomem *reg; | 782 | u8 __iomem *reg; |
| 774 | 783 | ||
| 775 | if (INTEL_GTT_GEN <= 2) | ||
| 776 | pci_read_config_dword(intel_private.pcidev, I810_GMADDR, | ||
| 777 | &gma_addr); | ||
| 778 | else | ||
| 779 | pci_read_config_dword(intel_private.pcidev, I915_GMADDR, | ||
| 780 | &gma_addr); | ||
| 781 | |||
| 782 | intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); | ||
| 783 | |||
| 784 | if (INTEL_GTT_GEN >= 6) | 784 | if (INTEL_GTT_GEN >= 6) |
| 785 | return true; | 785 | return true; |
| 786 | 786 | ||
| @@ -823,6 +823,7 @@ static bool intel_enable_gtt(void) | |||
| 823 | 823 | ||
| 824 | return true; | 824 | return true; |
| 825 | } | 825 | } |
| 826 | EXPORT_SYMBOL(intel_enable_gtt); | ||
| 826 | 827 | ||
| 827 | static int i830_setup(void) | 828 | static int i830_setup(void) |
| 828 | { | 829 | { |
| @@ -860,7 +861,7 @@ static int intel_fake_agp_configure(void) | |||
| 860 | return -EIO; | 861 | return -EIO; |
| 861 | 862 | ||
| 862 | intel_private.clear_fake_agp = true; | 863 | intel_private.clear_fake_agp = true; |
| 863 | agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; | 864 | agp_bridge->gart_bus_addr = intel_private.base.gma_bus_addr; |
| 864 | 865 | ||
| 865 | return 0; | 866 | return 0; |
| 866 | } | 867 | } |
| @@ -1182,9 +1183,17 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry, | |||
| 1182 | static void valleyview_write_entry(dma_addr_t addr, unsigned int entry, | 1183 | static void valleyview_write_entry(dma_addr_t addr, unsigned int entry, |
| 1183 | unsigned int flags) | 1184 | unsigned int flags) |
| 1184 | { | 1185 | { |
| 1186 | unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; | ||
| 1187 | unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; | ||
| 1185 | u32 pte_flags; | 1188 | u32 pte_flags; |
| 1186 | 1189 | ||
| 1187 | pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; | 1190 | if (type_mask == AGP_USER_MEMORY) |
| 1191 | pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; | ||
| 1192 | else { | ||
| 1193 | pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; | ||
| 1194 | if (gfdt) | ||
| 1195 | pte_flags |= GEN6_PTE_GFDT; | ||
| 1196 | } | ||
| 1188 | 1197 | ||
| 1189 | /* gen6 has bit11-4 for physical addr bit39-32 */ | 1198 | /* gen6 has bit11-4 for physical addr bit39-32 */ |
| 1190 | addr |= (addr >> 28) & 0xff0; | 1199 | addr |= (addr >> 28) & 0xff0; |
| @@ -1244,6 +1253,7 @@ static int i9xx_setup(void) | |||
| 1244 | switch (INTEL_GTT_GEN) { | 1253 | switch (INTEL_GTT_GEN) { |
| 1245 | case 5: | 1254 | case 5: |
| 1246 | case 6: | 1255 | case 6: |
| 1256 | case 7: | ||
| 1247 | gtt_offset = MB(2); | 1257 | gtt_offset = MB(2); |
| 1248 | break; | 1258 | break; |
| 1249 | case 4: | 1259 | case 4: |
| @@ -1379,7 +1389,6 @@ static const struct intel_gtt_driver valleyview_gtt_driver = { | |||
| 1379 | .write_entry = valleyview_write_entry, | 1389 | .write_entry = valleyview_write_entry, |
| 1380 | .dma_mask_size = 40, | 1390 | .dma_mask_size = 40, |
| 1381 | .check_flags = gen6_check_flags, | 1391 | .check_flags = gen6_check_flags, |
| 1382 | .chipset_flush = i9xx_chipset_flush, | ||
| 1383 | }; | 1392 | }; |
| 1384 | 1393 | ||
| 1385 | /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of | 1394 | /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of |
| @@ -1523,14 +1532,32 @@ static int find_gmch(u16 device) | |||
| 1523 | return 1; | 1532 | return 1; |
| 1524 | } | 1533 | } |
| 1525 | 1534 | ||
| 1526 | int intel_gmch_probe(struct pci_dev *pdev, | 1535 | int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, |
| 1527 | struct agp_bridge_data *bridge) | 1536 | struct agp_bridge_data *bridge) |
| 1528 | { | 1537 | { |
| 1529 | int i, mask; | 1538 | int i, mask; |
| 1530 | intel_private.driver = NULL; | 1539 | |
| 1540 | /* | ||
| 1541 | * Can be called from the fake agp driver but also directly from | ||
| 1542 | * drm/i915.ko. Hence we need to check whether everything is set up | ||
| 1543 | * already. | ||
| 1544 | */ | ||
| 1545 | if (intel_private.driver) { | ||
| 1546 | intel_private.refcount++; | ||
| 1547 | return 1; | ||
| 1548 | } | ||
| 1531 | 1549 | ||
| 1532 | for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { | 1550 | for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { |
| 1533 | if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { | 1551 | if (gpu_pdev) { |
| 1552 | if (gpu_pdev->device == | ||
| 1553 | intel_gtt_chipsets[i].gmch_chip_id) { | ||
| 1554 | intel_private.pcidev = pci_dev_get(gpu_pdev); | ||
| 1555 | intel_private.driver = | ||
| 1556 | intel_gtt_chipsets[i].gtt_driver; | ||
| 1557 | |||
| 1558 | break; | ||
| 1559 | } | ||
| 1560 | } else if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { | ||
| 1534 | intel_private.driver = | 1561 | intel_private.driver = |
| 1535 | intel_gtt_chipsets[i].gtt_driver; | 1562 | intel_gtt_chipsets[i].gtt_driver; |
| 1536 | break; | 1563 | break; |
| @@ -1540,13 +1567,17 @@ int intel_gmch_probe(struct pci_dev *pdev, | |||
| 1540 | if (!intel_private.driver) | 1567 | if (!intel_private.driver) |
| 1541 | return 0; | 1568 | return 0; |
| 1542 | 1569 | ||
| 1543 | bridge->driver = &intel_fake_agp_driver; | 1570 | intel_private.refcount++; |
| 1544 | bridge->dev_private_data = &intel_private; | 1571 | |
| 1545 | bridge->dev = pdev; | 1572 | if (bridge) { |
| 1573 | bridge->driver = &intel_fake_agp_driver; | ||
| 1574 | bridge->dev_private_data = &intel_private; | ||
| 1575 | bridge->dev = bridge_pdev; | ||
| 1576 | } | ||
| 1546 | 1577 | ||
| 1547 | intel_private.bridge_dev = pci_dev_get(pdev); | 1578 | intel_private.bridge_dev = pci_dev_get(bridge_pdev); |
| 1548 | 1579 | ||
| 1549 | dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); | 1580 | dev_info(&bridge_pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); |
| 1550 | 1581 | ||
| 1551 | mask = intel_private.driver->dma_mask_size; | 1582 | mask = intel_private.driver->dma_mask_size; |
| 1552 | if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) | 1583 | if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) |
| @@ -1556,11 +1587,11 @@ int intel_gmch_probe(struct pci_dev *pdev, | |||
| 1556 | pci_set_consistent_dma_mask(intel_private.pcidev, | 1587 | pci_set_consistent_dma_mask(intel_private.pcidev, |
| 1557 | DMA_BIT_MASK(mask)); | 1588 | DMA_BIT_MASK(mask)); |
| 1558 | 1589 | ||
| 1559 | /*if (bridge->driver == &intel_810_driver) | 1590 | if (intel_gtt_init() != 0) { |
| 1560 | return 1;*/ | 1591 | intel_gmch_remove(); |
| 1561 | 1592 | ||
| 1562 | if (intel_gtt_init() != 0) | ||
| 1563 | return 0; | 1593 | return 0; |
| 1594 | } | ||
| 1564 | 1595 | ||
| 1565 | return 1; | 1596 | return 1; |
| 1566 | } | 1597 | } |
| @@ -1579,12 +1610,16 @@ void intel_gtt_chipset_flush(void) | |||
| 1579 | } | 1610 | } |
| 1580 | EXPORT_SYMBOL(intel_gtt_chipset_flush); | 1611 | EXPORT_SYMBOL(intel_gtt_chipset_flush); |
| 1581 | 1612 | ||
| 1582 | void intel_gmch_remove(struct pci_dev *pdev) | 1613 | void intel_gmch_remove(void) |
| 1583 | { | 1614 | { |
| 1615 | if (--intel_private.refcount) | ||
| 1616 | return; | ||
| 1617 | |||
| 1584 | if (intel_private.pcidev) | 1618 | if (intel_private.pcidev) |
| 1585 | pci_dev_put(intel_private.pcidev); | 1619 | pci_dev_put(intel_private.pcidev); |
| 1586 | if (intel_private.bridge_dev) | 1620 | if (intel_private.bridge_dev) |
| 1587 | pci_dev_put(intel_private.bridge_dev); | 1621 | pci_dev_put(intel_private.bridge_dev); |
| 1622 | intel_private.driver = NULL; | ||
| 1588 | } | 1623 | } |
| 1589 | EXPORT_SYMBOL(intel_gmch_remove); | 1624 | EXPORT_SYMBOL(intel_gmch_remove); |
| 1590 | 1625 | ||
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 65f9d231af14..7282c081fb53 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c | |||
| @@ -460,8 +460,8 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | static bool ast_crtc_mode_fixup(struct drm_crtc *crtc, | 462 | static bool ast_crtc_mode_fixup(struct drm_crtc *crtc, |
| 463 | struct drm_display_mode *mode, | 463 | const struct drm_display_mode *mode, |
| 464 | struct drm_display_mode *adjusted_mode) | 464 | struct drm_display_mode *adjusted_mode) |
| 465 | { | 465 | { |
| 466 | return true; | 466 | return true; |
| 467 | } | 467 | } |
| @@ -680,7 +680,7 @@ static void ast_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
| 680 | } | 680 | } |
| 681 | 681 | ||
| 682 | static bool ast_mode_fixup(struct drm_encoder *encoder, | 682 | static bool ast_mode_fixup(struct drm_encoder *encoder, |
| 683 | struct drm_display_mode *mode, | 683 | const struct drm_display_mode *mode, |
| 684 | struct drm_display_mode *adjusted_mode) | 684 | struct drm_display_mode *adjusted_mode) |
| 685 | { | 685 | { |
| 686 | return true; | 686 | return true; |
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 100f6308c509..a44d31aa4e3c 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c | |||
| @@ -97,7 +97,7 @@ static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 97 | * to just pass that straight through, so this does nothing | 97 | * to just pass that straight through, so this does nothing |
| 98 | */ | 98 | */ |
| 99 | static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc, | 99 | static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc, |
| 100 | struct drm_display_mode *mode, | 100 | const struct drm_display_mode *mode, |
| 101 | struct drm_display_mode *adjusted_mode) | 101 | struct drm_display_mode *adjusted_mode) |
| 102 | { | 102 | { |
| 103 | return true; | 103 | return true; |
| @@ -429,8 +429,8 @@ void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
| 429 | 429 | ||
| 430 | 430 | ||
| 431 | static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder, | 431 | static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder, |
| 432 | struct drm_display_mode *mode, | 432 | const struct drm_display_mode *mode, |
| 433 | struct drm_display_mode *adjusted_mode) | 433 | struct drm_display_mode *adjusted_mode) |
| 434 | { | 434 | { |
| 435 | return true; | 435 | return true; |
| 436 | } | 436 | } |
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 348b367debeb..b356c719f2f1 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c | |||
| @@ -641,8 +641,6 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) | |||
| 641 | 641 | ||
| 642 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) | 642 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) |
| 643 | return -EINVAL; | 643 | return -EINVAL; |
| 644 | if (dev->queue_count) | ||
| 645 | return -EBUSY; /* Not while in use */ | ||
| 646 | 644 | ||
| 647 | /* Make sure buffers are located in AGP memory that we own */ | 645 | /* Make sure buffers are located in AGP memory that we own */ |
| 648 | valid = 0; | 646 | valid = 0; |
| @@ -704,7 +702,6 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) | |||
| 704 | buf->next = NULL; | 702 | buf->next = NULL; |
| 705 | buf->waiting = 0; | 703 | buf->waiting = 0; |
| 706 | buf->pending = 0; | 704 | buf->pending = 0; |
| 707 | init_waitqueue_head(&buf->dma_wait); | ||
| 708 | buf->file_priv = NULL; | 705 | buf->file_priv = NULL; |
| 709 | 706 | ||
| 710 | buf->dev_priv_size = dev->driver->dev_priv_size; | 707 | buf->dev_priv_size = dev->driver->dev_priv_size; |
| @@ -796,13 +793,11 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) | |||
| 796 | order = drm_order(request->size); | 793 | order = drm_order(request->size); |
| 797 | size = 1 << order; | 794 | size = 1 << order; |
| 798 | 795 | ||
| 799 | DRM_DEBUG("count=%d, size=%d (%d), order=%d, queue_count=%d\n", | 796 | DRM_DEBUG("count=%d, size=%d (%d), order=%d\n", |
| 800 | request->count, request->size, size, order, dev->queue_count); | 797 | request->count, request->size, size, order); |
| 801 | 798 | ||
| 802 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) | 799 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) |
| 803 | return -EINVAL; | 800 | return -EINVAL; |
| 804 | if (dev->queue_count) | ||
| 805 | return -EBUSY; /* Not while in use */ | ||
| 806 | 801 | ||
| 807 | alignment = (request->flags & _DRM_PAGE_ALIGN) | 802 | alignment = (request->flags & _DRM_PAGE_ALIGN) |
| 808 | ? PAGE_ALIGN(size) : size; | 803 | ? PAGE_ALIGN(size) : size; |
| @@ -904,7 +899,6 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) | |||
| 904 | buf->next = NULL; | 899 | buf->next = NULL; |
| 905 | buf->waiting = 0; | 900 | buf->waiting = 0; |
| 906 | buf->pending = 0; | 901 | buf->pending = 0; |
| 907 | init_waitqueue_head(&buf->dma_wait); | ||
| 908 | buf->file_priv = NULL; | 902 | buf->file_priv = NULL; |
| 909 | 903 | ||
| 910 | buf->dev_priv_size = dev->driver->dev_priv_size; | 904 | buf->dev_priv_size = dev->driver->dev_priv_size; |
| @@ -1019,8 +1013,6 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request | |||
| 1019 | 1013 | ||
| 1020 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) | 1014 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) |
| 1021 | return -EINVAL; | 1015 | return -EINVAL; |
| 1022 | if (dev->queue_count) | ||
| 1023 | return -EBUSY; /* Not while in use */ | ||
| 1024 | 1016 | ||
| 1025 | spin_lock(&dev->count_lock); | 1017 | spin_lock(&dev->count_lock); |
| 1026 | if (dev->buf_use) { | 1018 | if (dev->buf_use) { |
| @@ -1071,7 +1063,6 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request | |||
| 1071 | buf->next = NULL; | 1063 | buf->next = NULL; |
| 1072 | buf->waiting = 0; | 1064 | buf->waiting = 0; |
| 1073 | buf->pending = 0; | 1065 | buf->pending = 0; |
| 1074 | init_waitqueue_head(&buf->dma_wait); | ||
| 1075 | buf->file_priv = NULL; | 1066 | buf->file_priv = NULL; |
| 1076 | 1067 | ||
| 1077 | buf->dev_priv_size = dev->driver->dev_priv_size; | 1068 | buf->dev_priv_size = dev->driver->dev_priv_size; |
| @@ -1177,8 +1168,6 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request | |||
| 1177 | 1168 | ||
| 1178 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) | 1169 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) |
| 1179 | return -EINVAL; | 1170 | return -EINVAL; |
| 1180 | if (dev->queue_count) | ||
| 1181 | return -EBUSY; /* Not while in use */ | ||
| 1182 | 1171 | ||
| 1183 | spin_lock(&dev->count_lock); | 1172 | spin_lock(&dev->count_lock); |
| 1184 | if (dev->buf_use) { | 1173 | if (dev->buf_use) { |
| @@ -1228,7 +1217,6 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request | |||
| 1228 | buf->next = NULL; | 1217 | buf->next = NULL; |
| 1229 | buf->waiting = 0; | 1218 | buf->waiting = 0; |
| 1230 | buf->pending = 0; | 1219 | buf->pending = 0; |
| 1231 | init_waitqueue_head(&buf->dma_wait); | ||
| 1232 | buf->file_priv = NULL; | 1220 | buf->file_priv = NULL; |
| 1233 | 1221 | ||
| 1234 | buf->dev_priv_size = dev->driver->dev_priv_size; | 1222 | buf->dev_priv_size = dev->driver->dev_priv_size; |
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 1c7a1c0d3edd..70b13fc19396 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c | |||
| @@ -46,7 +46,6 @@ static struct drm_info_list drm_debugfs_list[] = { | |||
| 46 | {"name", drm_name_info, 0}, | 46 | {"name", drm_name_info, 0}, |
| 47 | {"vm", drm_vm_info, 0}, | 47 | {"vm", drm_vm_info, 0}, |
| 48 | {"clients", drm_clients_info, 0}, | 48 | {"clients", drm_clients_info, 0}, |
| 49 | {"queues", drm_queues_info, 0}, | ||
| 50 | {"bufs", drm_bufs_info, 0}, | 49 | {"bufs", drm_bufs_info, 0}, |
| 51 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, | 50 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, |
| 52 | #if DRM_DEBUG_CODE | 51 | #if DRM_DEBUG_CODE |
diff --git a/drivers/gpu/drm/drm_dma.c b/drivers/gpu/drm/drm_dma.c index cfb4e333ec0f..08f5e5309b22 100644 --- a/drivers/gpu/drm/drm_dma.c +++ b/drivers/gpu/drm/drm_dma.c | |||
| @@ -120,11 +120,6 @@ void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf) | |||
| 120 | buf->pending = 0; | 120 | buf->pending = 0; |
| 121 | buf->file_priv = NULL; | 121 | buf->file_priv = NULL; |
| 122 | buf->used = 0; | 122 | buf->used = 0; |
| 123 | |||
| 124 | if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) | ||
| 125 | && waitqueue_active(&buf->dma_wait)) { | ||
| 126 | wake_up_interruptible(&buf->dma_wait); | ||
| 127 | } | ||
| 128 | } | 123 | } |
| 129 | 124 | ||
| 130 | /** | 125 | /** |
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 8a9d0792e4ec..9238de4009fa 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
| @@ -182,7 +182,6 @@ static struct drm_ioctl_desc drm_ioctls[] = { | |||
| 182 | int drm_lastclose(struct drm_device * dev) | 182 | int drm_lastclose(struct drm_device * dev) |
| 183 | { | 183 | { |
| 184 | struct drm_vma_entry *vma, *vma_temp; | 184 | struct drm_vma_entry *vma, *vma_temp; |
| 185 | int i; | ||
| 186 | 185 | ||
| 187 | DRM_DEBUG("\n"); | 186 | DRM_DEBUG("\n"); |
| 188 | 187 | ||
| @@ -228,16 +227,6 @@ int drm_lastclose(struct drm_device * dev) | |||
| 228 | kfree(vma); | 227 | kfree(vma); |
| 229 | } | 228 | } |
| 230 | 229 | ||
| 231 | if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) { | ||
| 232 | for (i = 0; i < dev->queue_count; i++) { | ||
| 233 | kfree(dev->queuelist[i]); | ||
| 234 | dev->queuelist[i] = NULL; | ||
| 235 | } | ||
| 236 | kfree(dev->queuelist); | ||
| 237 | dev->queuelist = NULL; | ||
| 238 | } | ||
| 239 | dev->queue_count = 0; | ||
| 240 | |||
| 241 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && | 230 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && |
| 242 | !drm_core_check_feature(dev, DRIVER_MODESET)) | 231 | !drm_core_check_feature(dev, DRIVER_MODESET)) |
| 243 | drm_dma_takedown(dev); | 232 | drm_dma_takedown(dev); |
| @@ -486,7 +475,7 @@ long drm_ioctl(struct file *filp, | |||
| 486 | kfree(kdata); | 475 | kfree(kdata); |
| 487 | atomic_dec(&dev->ioctl_count); | 476 | atomic_dec(&dev->ioctl_count); |
| 488 | if (retcode) | 477 | if (retcode) |
| 489 | DRM_DEBUG("ret = %x\n", retcode); | 478 | DRM_DEBUG("ret = %d\n", retcode); |
| 490 | return retcode; | 479 | return retcode; |
| 491 | } | 480 | } |
| 492 | 481 | ||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 5683b7fdd746..f546d1e8af82 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
| @@ -228,7 +228,7 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) | |||
| 228 | int i, ret; | 228 | int i, ret; |
| 229 | for (i = 0; i < fb_helper->crtc_count; i++) { | 229 | for (i = 0; i < fb_helper->crtc_count; i++) { |
| 230 | struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; | 230 | struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; |
| 231 | ret = drm_crtc_helper_set_config(mode_set); | 231 | ret = mode_set->crtc->funcs->set_config(mode_set); |
| 232 | if (ret) | 232 | if (ret) |
| 233 | error = true; | 233 | error = true; |
| 234 | } | 234 | } |
| @@ -1353,7 +1353,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) | |||
| 1353 | struct drm_device *dev = fb_helper->dev; | 1353 | struct drm_device *dev = fb_helper->dev; |
| 1354 | int count = 0; | 1354 | int count = 0; |
| 1355 | u32 max_width, max_height, bpp_sel; | 1355 | u32 max_width, max_height, bpp_sel; |
| 1356 | bool bound = false, crtcs_bound = false; | 1356 | int bound = 0, crtcs_bound = 0; |
| 1357 | struct drm_crtc *crtc; | 1357 | struct drm_crtc *crtc; |
| 1358 | 1358 | ||
| 1359 | if (!fb_helper->fb) | 1359 | if (!fb_helper->fb) |
| @@ -1362,12 +1362,12 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) | |||
| 1362 | mutex_lock(&dev->mode_config.mutex); | 1362 | mutex_lock(&dev->mode_config.mutex); |
| 1363 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 1363 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
| 1364 | if (crtc->fb) | 1364 | if (crtc->fb) |
| 1365 | crtcs_bound = true; | 1365 | crtcs_bound++; |
| 1366 | if (crtc->fb == fb_helper->fb) | 1366 | if (crtc->fb == fb_helper->fb) |
| 1367 | bound = true; | 1367 | bound++; |
| 1368 | } | 1368 | } |
| 1369 | 1369 | ||
| 1370 | if (!bound && crtcs_bound) { | 1370 | if (bound < crtcs_bound) { |
| 1371 | fb_helper->delayed_hotplug = true; | 1371 | fb_helper->delayed_hotplug = true; |
| 1372 | mutex_unlock(&dev->mode_config.mutex); | 1372 | mutex_unlock(&dev->mode_config.mutex); |
| 1373 | return 0; | 1373 | return 0; |
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 123de28f94ef..5062eec673f1 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
| @@ -75,10 +75,6 @@ static int drm_setup(struct drm_device * dev) | |||
| 75 | 75 | ||
| 76 | dev->sigdata.lock = NULL; | 76 | dev->sigdata.lock = NULL; |
| 77 | 77 | ||
| 78 | dev->queue_count = 0; | ||
| 79 | dev->queue_reserved = 0; | ||
| 80 | dev->queue_slots = 0; | ||
| 81 | dev->queuelist = NULL; | ||
| 82 | dev->context_flag = 0; | 78 | dev->context_flag = 0; |
| 83 | dev->interrupt_flag = 0; | 79 | dev->interrupt_flag = 0; |
| 84 | dev->dma_flag = 0; | 80 | dev->dma_flag = 0; |
| @@ -144,12 +140,12 @@ int drm_open(struct inode *inode, struct file *filp) | |||
| 144 | } | 140 | } |
| 145 | if (!retcode) { | 141 | if (!retcode) { |
| 146 | mutex_lock(&dev->struct_mutex); | 142 | mutex_lock(&dev->struct_mutex); |
| 147 | if (minor->type == DRM_MINOR_LEGACY) { | 143 | if (dev->dev_mapping == NULL) |
| 148 | if (dev->dev_mapping == NULL) | 144 | dev->dev_mapping = &inode->i_data; |
| 149 | dev->dev_mapping = inode->i_mapping; | 145 | /* ihold ensures nobody can remove inode with our i_data */ |
| 150 | else if (dev->dev_mapping != inode->i_mapping) | 146 | ihold(container_of(dev->dev_mapping, struct inode, i_data)); |
| 151 | retcode = -ENODEV; | 147 | inode->i_mapping = dev->dev_mapping; |
| 152 | } | 148 | filp->f_mapping = dev->dev_mapping; |
| 153 | mutex_unlock(&dev->struct_mutex); | 149 | mutex_unlock(&dev->struct_mutex); |
| 154 | } | 150 | } |
| 155 | 151 | ||
| @@ -370,72 +366,16 @@ int drm_fasync(int fd, struct file *filp, int on) | |||
| 370 | } | 366 | } |
| 371 | EXPORT_SYMBOL(drm_fasync); | 367 | EXPORT_SYMBOL(drm_fasync); |
| 372 | 368 | ||
| 373 | /* | ||
| 374 | * Reclaim locked buffers; note that this may be a bad idea if the current | ||
| 375 | * context doesn't have the hw lock... | ||
| 376 | */ | ||
| 377 | static void drm_reclaim_locked_buffers(struct drm_device *dev, struct file *f) | ||
| 378 | { | ||
| 379 | struct drm_file *file_priv = f->private_data; | ||
| 380 | |||
| 381 | if (drm_i_have_hw_lock(dev, file_priv)) { | ||
| 382 | dev->driver->reclaim_buffers_locked(dev, file_priv); | ||
| 383 | } else { | ||
| 384 | unsigned long _end = jiffies + 3 * DRM_HZ; | ||
| 385 | int locked = 0; | ||
| 386 | |||
| 387 | drm_idlelock_take(&file_priv->master->lock); | ||
| 388 | |||
| 389 | /* | ||
| 390 | * Wait for a while. | ||
| 391 | */ | ||
| 392 | do { | ||
| 393 | spin_lock_bh(&file_priv->master->lock.spinlock); | ||
| 394 | locked = file_priv->master->lock.idle_has_lock; | ||
| 395 | spin_unlock_bh(&file_priv->master->lock.spinlock); | ||
| 396 | if (locked) | ||
| 397 | break; | ||
| 398 | schedule(); | ||
| 399 | } while (!time_after_eq(jiffies, _end)); | ||
| 400 | |||
| 401 | if (!locked) { | ||
| 402 | DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n" | ||
| 403 | "\tdriver to use reclaim_buffers_idlelocked() instead.\n" | ||
| 404 | "\tI will go on reclaiming the buffers anyway.\n"); | ||
| 405 | } | ||
| 406 | |||
| 407 | dev->driver->reclaim_buffers_locked(dev, file_priv); | ||
| 408 | drm_idlelock_release(&file_priv->master->lock); | ||
| 409 | } | ||
| 410 | } | ||
| 411 | |||
| 412 | static void drm_master_release(struct drm_device *dev, struct file *filp) | 369 | static void drm_master_release(struct drm_device *dev, struct file *filp) |
| 413 | { | 370 | { |
| 414 | struct drm_file *file_priv = filp->private_data; | 371 | struct drm_file *file_priv = filp->private_data; |
| 415 | 372 | ||
| 416 | if (dev->driver->reclaim_buffers_locked && | ||
| 417 | file_priv->master->lock.hw_lock) | ||
| 418 | drm_reclaim_locked_buffers(dev, filp); | ||
| 419 | |||
| 420 | if (dev->driver->reclaim_buffers_idlelocked && | ||
| 421 | file_priv->master->lock.hw_lock) { | ||
| 422 | drm_idlelock_take(&file_priv->master->lock); | ||
| 423 | dev->driver->reclaim_buffers_idlelocked(dev, file_priv); | ||
| 424 | drm_idlelock_release(&file_priv->master->lock); | ||
| 425 | } | ||
| 426 | |||
| 427 | |||
| 428 | if (drm_i_have_hw_lock(dev, file_priv)) { | 373 | if (drm_i_have_hw_lock(dev, file_priv)) { |
| 429 | DRM_DEBUG("File %p released, freeing lock for context %d\n", | 374 | DRM_DEBUG("File %p released, freeing lock for context %d\n", |
| 430 | filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); | 375 | filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); |
| 431 | drm_lock_free(&file_priv->master->lock, | 376 | drm_lock_free(&file_priv->master->lock, |
| 432 | _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); | 377 | _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); |
| 433 | } | 378 | } |
| 434 | |||
| 435 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && | ||
| 436 | !dev->driver->reclaim_buffers_locked) { | ||
| 437 | dev->driver->reclaim_buffers(dev, file_priv); | ||
| 438 | } | ||
| 439 | } | 379 | } |
| 440 | 380 | ||
| 441 | static void drm_events_release(struct drm_file *file_priv) | 381 | static void drm_events_release(struct drm_file *file_priv) |
| @@ -505,6 +445,9 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 505 | if (file_priv->minor->master) | 445 | if (file_priv->minor->master) |
| 506 | drm_master_release(dev, filp); | 446 | drm_master_release(dev, filp); |
| 507 | 447 | ||
| 448 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) | ||
| 449 | drm_core_reclaim_buffers(dev, file_priv); | ||
| 450 | |||
| 508 | drm_events_release(file_priv); | 451 | drm_events_release(file_priv); |
| 509 | 452 | ||
| 510 | if (dev->driver->driver_features & DRIVER_MODESET) | 453 | if (dev->driver->driver_features & DRIVER_MODESET) |
| @@ -566,6 +509,9 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 566 | } | 509 | } |
| 567 | } | 510 | } |
| 568 | 511 | ||
| 512 | BUG_ON(dev->dev_mapping == NULL); | ||
| 513 | iput(container_of(dev->dev_mapping, struct inode, i_data)); | ||
| 514 | |||
| 569 | /* drop the reference held my the file priv */ | 515 | /* drop the reference held my the file priv */ |
| 570 | drm_master_put(&file_priv->master); | 516 | drm_master_put(&file_priv->master); |
| 571 | file_priv->is_master = 0; | 517 | file_priv->is_master = 0; |
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index d58e69da1fb5..fbe0842038b5 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
| @@ -354,7 +354,7 @@ drm_gem_create_mmap_offset(struct drm_gem_object *obj) | |||
| 354 | 354 | ||
| 355 | /* Get a DRM GEM mmap offset allocated... */ | 355 | /* Get a DRM GEM mmap offset allocated... */ |
| 356 | list->file_offset_node = drm_mm_search_free(&mm->offset_manager, | 356 | list->file_offset_node = drm_mm_search_free(&mm->offset_manager, |
| 357 | obj->size / PAGE_SIZE, 0, 0); | 357 | obj->size / PAGE_SIZE, 0, false); |
| 358 | 358 | ||
| 359 | if (!list->file_offset_node) { | 359 | if (!list->file_offset_node) { |
| 360 | DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); | 360 | DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); |
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index ab1162da70f8..8928edbb94c7 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c | |||
| @@ -110,42 +110,6 @@ int drm_vm_info(struct seq_file *m, void *data) | |||
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | /** | 112 | /** |
| 113 | * Called when "/proc/dri/.../queues" is read. | ||
| 114 | */ | ||
| 115 | int drm_queues_info(struct seq_file *m, void *data) | ||
| 116 | { | ||
| 117 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 118 | struct drm_device *dev = node->minor->dev; | ||
| 119 | int i; | ||
| 120 | struct drm_queue *q; | ||
| 121 | |||
| 122 | mutex_lock(&dev->struct_mutex); | ||
| 123 | seq_printf(m, " ctx/flags use fin" | ||
| 124 | " blk/rw/rwf wait flushed queued" | ||
| 125 | " locks\n\n"); | ||
| 126 | for (i = 0; i < dev->queue_count; i++) { | ||
| 127 | q = dev->queuelist[i]; | ||
| 128 | atomic_inc(&q->use_count); | ||
| 129 | seq_printf(m, "%5d/0x%03x %5d %5d" | ||
| 130 | " %5d/%c%c/%c%c%c %5Zd\n", | ||
| 131 | i, | ||
| 132 | q->flags, | ||
| 133 | atomic_read(&q->use_count), | ||
| 134 | atomic_read(&q->finalization), | ||
| 135 | atomic_read(&q->block_count), | ||
| 136 | atomic_read(&q->block_read) ? 'r' : '-', | ||
| 137 | atomic_read(&q->block_write) ? 'w' : '-', | ||
| 138 | waitqueue_active(&q->read_queue) ? 'r' : '-', | ||
| 139 | waitqueue_active(&q->write_queue) ? 'w' : '-', | ||
| 140 | waitqueue_active(&q->flush_queue) ? 'f' : '-', | ||
| 141 | DRM_BUFCOUNT(&q->waitlist)); | ||
| 142 | atomic_dec(&q->use_count); | ||
| 143 | } | ||
| 144 | mutex_unlock(&dev->struct_mutex); | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | /** | ||
| 149 | * Called when "/proc/dri/.../bufs" is read. | 113 | * Called when "/proc/dri/.../bufs" is read. |
| 150 | */ | 114 | */ |
| 151 | int drm_bufs_info(struct seq_file *m, void *data) | 115 | int drm_bufs_info(struct seq_file *m, void *data) |
| @@ -235,7 +199,7 @@ int drm_clients_info(struct seq_file *m, void *data) | |||
| 235 | } | 199 | } |
| 236 | 200 | ||
| 237 | 201 | ||
| 238 | int drm_gem_one_name_info(int id, void *ptr, void *data) | 202 | static int drm_gem_one_name_info(int id, void *ptr, void *data) |
| 239 | { | 203 | { |
| 240 | struct drm_gem_object *obj = ptr; | 204 | struct drm_gem_object *obj = ptr; |
| 241 | struct seq_file *m = data; | 205 | struct seq_file *m = data; |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index c798eeae0a03..03f16f352fe2 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -974,7 +974,6 @@ EXPORT_SYMBOL(drm_vblank_off); | |||
| 974 | * drm_vblank_pre_modeset - account for vblanks across mode sets | 974 | * drm_vblank_pre_modeset - account for vblanks across mode sets |
| 975 | * @dev: DRM device | 975 | * @dev: DRM device |
| 976 | * @crtc: CRTC in question | 976 | * @crtc: CRTC in question |
| 977 | * @post: post or pre mode set? | ||
| 978 | * | 977 | * |
| 979 | * Account for vblank events across mode setting events, which will likely | 978 | * Account for vblank events across mode setting events, which will likely |
| 980 | * reset the hardware frame counter. | 979 | * reset the hardware frame counter. |
| @@ -1037,6 +1036,10 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, | |||
| 1037 | if (!dev->num_crtcs) | 1036 | if (!dev->num_crtcs) |
| 1038 | return 0; | 1037 | return 0; |
| 1039 | 1038 | ||
| 1039 | /* KMS drivers handle this internally */ | ||
| 1040 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
| 1041 | return 0; | ||
| 1042 | |||
| 1040 | crtc = modeset->crtc; | 1043 | crtc = modeset->crtc; |
| 1041 | if (crtc >= dev->num_crtcs) | 1044 | if (crtc >= dev->num_crtcs) |
| 1042 | return -EINVAL; | 1045 | return -EINVAL; |
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 521152041691..32039553e172 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c | |||
| @@ -70,10 +70,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 70 | lock->context, task_pid_nr(current), | 70 | lock->context, task_pid_nr(current), |
| 71 | master->lock.hw_lock->lock, lock->flags); | 71 | master->lock.hw_lock->lock, lock->flags); |
| 72 | 72 | ||
| 73 | if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)) | ||
| 74 | if (lock->context < 0) | ||
| 75 | return -EINVAL; | ||
| 76 | |||
| 77 | add_wait_queue(&master->lock.lock_queue, &entry); | 73 | add_wait_queue(&master->lock.lock_queue, &entry); |
| 78 | spin_lock_bh(&master->lock.spinlock); | 74 | spin_lock_bh(&master->lock.spinlock); |
| 79 | master->lock.user_waiters++; | 75 | master->lock.user_waiters++; |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 961fb54f4266..9bb82f7f0061 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
| @@ -118,45 +118,53 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node) | |||
| 118 | 118 | ||
| 119 | static void drm_mm_insert_helper(struct drm_mm_node *hole_node, | 119 | static void drm_mm_insert_helper(struct drm_mm_node *hole_node, |
| 120 | struct drm_mm_node *node, | 120 | struct drm_mm_node *node, |
| 121 | unsigned long size, unsigned alignment) | 121 | unsigned long size, unsigned alignment, |
| 122 | unsigned long color) | ||
| 122 | { | 123 | { |
| 123 | struct drm_mm *mm = hole_node->mm; | 124 | struct drm_mm *mm = hole_node->mm; |
| 124 | unsigned long tmp = 0, wasted = 0; | ||
| 125 | unsigned long hole_start = drm_mm_hole_node_start(hole_node); | 125 | unsigned long hole_start = drm_mm_hole_node_start(hole_node); |
| 126 | unsigned long hole_end = drm_mm_hole_node_end(hole_node); | 126 | unsigned long hole_end = drm_mm_hole_node_end(hole_node); |
| 127 | unsigned long adj_start = hole_start; | ||
| 128 | unsigned long adj_end = hole_end; | ||
| 127 | 129 | ||
| 128 | BUG_ON(!hole_node->hole_follows || node->allocated); | 130 | BUG_ON(!hole_node->hole_follows || node->allocated); |
| 129 | 131 | ||
| 130 | if (alignment) | 132 | if (mm->color_adjust) |
| 131 | tmp = hole_start % alignment; | 133 | mm->color_adjust(hole_node, color, &adj_start, &adj_end); |
| 132 | 134 | ||
| 133 | if (!tmp) { | 135 | if (alignment) { |
| 136 | unsigned tmp = adj_start % alignment; | ||
| 137 | if (tmp) | ||
| 138 | adj_start += alignment - tmp; | ||
| 139 | } | ||
| 140 | |||
| 141 | if (adj_start == hole_start) { | ||
| 134 | hole_node->hole_follows = 0; | 142 | hole_node->hole_follows = 0; |
| 135 | list_del_init(&hole_node->hole_stack); | 143 | list_del(&hole_node->hole_stack); |
| 136 | } else | 144 | } |
| 137 | wasted = alignment - tmp; | ||
| 138 | 145 | ||
| 139 | node->start = hole_start + wasted; | 146 | node->start = adj_start; |
| 140 | node->size = size; | 147 | node->size = size; |
| 141 | node->mm = mm; | 148 | node->mm = mm; |
| 149 | node->color = color; | ||
| 142 | node->allocated = 1; | 150 | node->allocated = 1; |
| 143 | 151 | ||
| 144 | INIT_LIST_HEAD(&node->hole_stack); | 152 | INIT_LIST_HEAD(&node->hole_stack); |
| 145 | list_add(&node->node_list, &hole_node->node_list); | 153 | list_add(&node->node_list, &hole_node->node_list); |
| 146 | 154 | ||
| 147 | BUG_ON(node->start + node->size > hole_end); | 155 | BUG_ON(node->start + node->size > adj_end); |
| 148 | 156 | ||
| 157 | node->hole_follows = 0; | ||
| 149 | if (node->start + node->size < hole_end) { | 158 | if (node->start + node->size < hole_end) { |
| 150 | list_add(&node->hole_stack, &mm->hole_stack); | 159 | list_add(&node->hole_stack, &mm->hole_stack); |
| 151 | node->hole_follows = 1; | 160 | node->hole_follows = 1; |
| 152 | } else { | ||
| 153 | node->hole_follows = 0; | ||
| 154 | } | 161 | } |
| 155 | } | 162 | } |
| 156 | 163 | ||
| 157 | struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, | 164 | struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, |
| 158 | unsigned long size, | 165 | unsigned long size, |
| 159 | unsigned alignment, | 166 | unsigned alignment, |
| 167 | unsigned long color, | ||
| 160 | int atomic) | 168 | int atomic) |
| 161 | { | 169 | { |
| 162 | struct drm_mm_node *node; | 170 | struct drm_mm_node *node; |
| @@ -165,7 +173,7 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, | |||
| 165 | if (unlikely(node == NULL)) | 173 | if (unlikely(node == NULL)) |
| 166 | return NULL; | 174 | return NULL; |
| 167 | 175 | ||
| 168 | drm_mm_insert_helper(hole_node, node, size, alignment); | 176 | drm_mm_insert_helper(hole_node, node, size, alignment, color); |
| 169 | 177 | ||
| 170 | return node; | 178 | return node; |
| 171 | } | 179 | } |
| @@ -181,11 +189,11 @@ int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, | |||
| 181 | { | 189 | { |
| 182 | struct drm_mm_node *hole_node; | 190 | struct drm_mm_node *hole_node; |
| 183 | 191 | ||
| 184 | hole_node = drm_mm_search_free(mm, size, alignment, 0); | 192 | hole_node = drm_mm_search_free(mm, size, alignment, false); |
| 185 | if (!hole_node) | 193 | if (!hole_node) |
| 186 | return -ENOSPC; | 194 | return -ENOSPC; |
| 187 | 195 | ||
| 188 | drm_mm_insert_helper(hole_node, node, size, alignment); | 196 | drm_mm_insert_helper(hole_node, node, size, alignment, 0); |
| 189 | 197 | ||
| 190 | return 0; | 198 | return 0; |
| 191 | } | 199 | } |
| @@ -194,50 +202,57 @@ EXPORT_SYMBOL(drm_mm_insert_node); | |||
| 194 | static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, | 202 | static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, |
| 195 | struct drm_mm_node *node, | 203 | struct drm_mm_node *node, |
| 196 | unsigned long size, unsigned alignment, | 204 | unsigned long size, unsigned alignment, |
| 205 | unsigned long color, | ||
| 197 | unsigned long start, unsigned long end) | 206 | unsigned long start, unsigned long end) |
| 198 | { | 207 | { |
| 199 | struct drm_mm *mm = hole_node->mm; | 208 | struct drm_mm *mm = hole_node->mm; |
| 200 | unsigned long tmp = 0, wasted = 0; | ||
| 201 | unsigned long hole_start = drm_mm_hole_node_start(hole_node); | 209 | unsigned long hole_start = drm_mm_hole_node_start(hole_node); |
| 202 | unsigned long hole_end = drm_mm_hole_node_end(hole_node); | 210 | unsigned long hole_end = drm_mm_hole_node_end(hole_node); |
| 211 | unsigned long adj_start = hole_start; | ||
| 212 | unsigned long adj_end = hole_end; | ||
| 203 | 213 | ||
| 204 | BUG_ON(!hole_node->hole_follows || node->allocated); | 214 | BUG_ON(!hole_node->hole_follows || node->allocated); |
| 205 | 215 | ||
| 206 | if (hole_start < start) | 216 | if (mm->color_adjust) |
| 207 | wasted += start - hole_start; | 217 | mm->color_adjust(hole_node, color, &adj_start, &adj_end); |
| 208 | if (alignment) | ||
| 209 | tmp = (hole_start + wasted) % alignment; | ||
| 210 | 218 | ||
| 211 | if (tmp) | 219 | if (adj_start < start) |
| 212 | wasted += alignment - tmp; | 220 | adj_start = start; |
| 221 | |||
| 222 | if (alignment) { | ||
| 223 | unsigned tmp = adj_start % alignment; | ||
| 224 | if (tmp) | ||
| 225 | adj_start += alignment - tmp; | ||
| 226 | } | ||
| 213 | 227 | ||
| 214 | if (!wasted) { | 228 | if (adj_start == hole_start) { |
| 215 | hole_node->hole_follows = 0; | 229 | hole_node->hole_follows = 0; |
| 216 | list_del_init(&hole_node->hole_stack); | 230 | list_del(&hole_node->hole_stack); |
| 217 | } | 231 | } |
| 218 | 232 | ||
| 219 | node->start = hole_start + wasted; | 233 | node->start = adj_start; |
| 220 | node->size = size; | 234 | node->size = size; |
| 221 | node->mm = mm; | 235 | node->mm = mm; |
| 236 | node->color = color; | ||
| 222 | node->allocated = 1; | 237 | node->allocated = 1; |
| 223 | 238 | ||
| 224 | INIT_LIST_HEAD(&node->hole_stack); | 239 | INIT_LIST_HEAD(&node->hole_stack); |
| 225 | list_add(&node->node_list, &hole_node->node_list); | 240 | list_add(&node->node_list, &hole_node->node_list); |
| 226 | 241 | ||
| 227 | BUG_ON(node->start + node->size > hole_end); | 242 | BUG_ON(node->start + node->size > adj_end); |
| 228 | BUG_ON(node->start + node->size > end); | 243 | BUG_ON(node->start + node->size > end); |
| 229 | 244 | ||
| 245 | node->hole_follows = 0; | ||
| 230 | if (node->start + node->size < hole_end) { | 246 | if (node->start + node->size < hole_end) { |
| 231 | list_add(&node->hole_stack, &mm->hole_stack); | 247 | list_add(&node->hole_stack, &mm->hole_stack); |
| 232 | node->hole_follows = 1; | 248 | node->hole_follows = 1; |
| 233 | } else { | ||
| 234 | node->hole_follows = 0; | ||
| 235 | } | 249 | } |
| 236 | } | 250 | } |
| 237 | 251 | ||
| 238 | struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node, | 252 | struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node, |
| 239 | unsigned long size, | 253 | unsigned long size, |
| 240 | unsigned alignment, | 254 | unsigned alignment, |
| 255 | unsigned long color, | ||
| 241 | unsigned long start, | 256 | unsigned long start, |
| 242 | unsigned long end, | 257 | unsigned long end, |
| 243 | int atomic) | 258 | int atomic) |
| @@ -248,7 +263,7 @@ struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node | |||
| 248 | if (unlikely(node == NULL)) | 263 | if (unlikely(node == NULL)) |
| 249 | return NULL; | 264 | return NULL; |
| 250 | 265 | ||
| 251 | drm_mm_insert_helper_range(hole_node, node, size, alignment, | 266 | drm_mm_insert_helper_range(hole_node, node, size, alignment, color, |
| 252 | start, end); | 267 | start, end); |
| 253 | 268 | ||
| 254 | return node; | 269 | return node; |
| @@ -267,11 +282,11 @@ int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node, | |||
| 267 | struct drm_mm_node *hole_node; | 282 | struct drm_mm_node *hole_node; |
| 268 | 283 | ||
| 269 | hole_node = drm_mm_search_free_in_range(mm, size, alignment, | 284 | hole_node = drm_mm_search_free_in_range(mm, size, alignment, |
| 270 | start, end, 0); | 285 | start, end, false); |
| 271 | if (!hole_node) | 286 | if (!hole_node) |
| 272 | return -ENOSPC; | 287 | return -ENOSPC; |
| 273 | 288 | ||
| 274 | drm_mm_insert_helper_range(hole_node, node, size, alignment, | 289 | drm_mm_insert_helper_range(hole_node, node, size, alignment, 0, |
| 275 | start, end); | 290 | start, end); |
| 276 | 291 | ||
| 277 | return 0; | 292 | return 0; |
| @@ -336,27 +351,23 @@ EXPORT_SYMBOL(drm_mm_put_block); | |||
| 336 | static int check_free_hole(unsigned long start, unsigned long end, | 351 | static int check_free_hole(unsigned long start, unsigned long end, |
| 337 | unsigned long size, unsigned alignment) | 352 | unsigned long size, unsigned alignment) |
| 338 | { | 353 | { |
| 339 | unsigned wasted = 0; | ||
| 340 | |||
| 341 | if (end - start < size) | 354 | if (end - start < size) |
| 342 | return 0; | 355 | return 0; |
| 343 | 356 | ||
| 344 | if (alignment) { | 357 | if (alignment) { |
| 345 | unsigned tmp = start % alignment; | 358 | unsigned tmp = start % alignment; |
| 346 | if (tmp) | 359 | if (tmp) |
| 347 | wasted = alignment - tmp; | 360 | start += alignment - tmp; |
| 348 | } | ||
| 349 | |||
| 350 | if (end >= start + size + wasted) { | ||
| 351 | return 1; | ||
| 352 | } | 361 | } |
| 353 | 362 | ||
| 354 | return 0; | 363 | return end >= start + size; |
| 355 | } | 364 | } |
| 356 | 365 | ||
| 357 | struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | 366 | struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, |
| 358 | unsigned long size, | 367 | unsigned long size, |
| 359 | unsigned alignment, int best_match) | 368 | unsigned alignment, |
| 369 | unsigned long color, | ||
| 370 | bool best_match) | ||
| 360 | { | 371 | { |
| 361 | struct drm_mm_node *entry; | 372 | struct drm_mm_node *entry; |
| 362 | struct drm_mm_node *best; | 373 | struct drm_mm_node *best; |
| @@ -368,10 +379,17 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | |||
| 368 | best_size = ~0UL; | 379 | best_size = ~0UL; |
| 369 | 380 | ||
| 370 | list_for_each_entry(entry, &mm->hole_stack, hole_stack) { | 381 | list_for_each_entry(entry, &mm->hole_stack, hole_stack) { |
| 382 | unsigned long adj_start = drm_mm_hole_node_start(entry); | ||
| 383 | unsigned long adj_end = drm_mm_hole_node_end(entry); | ||
| 384 | |||
| 385 | if (mm->color_adjust) { | ||
| 386 | mm->color_adjust(entry, color, &adj_start, &adj_end); | ||
| 387 | if (adj_end <= adj_start) | ||
| 388 | continue; | ||
| 389 | } | ||
| 390 | |||
| 371 | BUG_ON(!entry->hole_follows); | 391 | BUG_ON(!entry->hole_follows); |
| 372 | if (!check_free_hole(drm_mm_hole_node_start(entry), | 392 | if (!check_free_hole(adj_start, adj_end, size, alignment)) |
| 373 | drm_mm_hole_node_end(entry), | ||
| 374 | size, alignment)) | ||
| 375 | continue; | 393 | continue; |
| 376 | 394 | ||
| 377 | if (!best_match) | 395 | if (!best_match) |
| @@ -385,14 +403,15 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | |||
| 385 | 403 | ||
| 386 | return best; | 404 | return best; |
| 387 | } | 405 | } |
| 388 | EXPORT_SYMBOL(drm_mm_search_free); | 406 | EXPORT_SYMBOL(drm_mm_search_free_generic); |
| 389 | 407 | ||
| 390 | struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, | 408 | struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, |
| 391 | unsigned long size, | 409 | unsigned long size, |
| 392 | unsigned alignment, | 410 | unsigned alignment, |
| 393 | unsigned long start, | 411 | unsigned long color, |
| 394 | unsigned long end, | 412 | unsigned long start, |
| 395 | int best_match) | 413 | unsigned long end, |
| 414 | bool best_match) | ||
| 396 | { | 415 | { |
| 397 | struct drm_mm_node *entry; | 416 | struct drm_mm_node *entry; |
| 398 | struct drm_mm_node *best; | 417 | struct drm_mm_node *best; |
| @@ -410,6 +429,13 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, | |||
| 410 | end : drm_mm_hole_node_end(entry); | 429 | end : drm_mm_hole_node_end(entry); |
| 411 | 430 | ||
| 412 | BUG_ON(!entry->hole_follows); | 431 | BUG_ON(!entry->hole_follows); |
| 432 | |||
| 433 | if (mm->color_adjust) { | ||
| 434 | mm->color_adjust(entry, color, &adj_start, &adj_end); | ||
| 435 | if (adj_end <= adj_start) | ||
| 436 | continue; | ||
| 437 | } | ||
| 438 | |||
| 413 | if (!check_free_hole(adj_start, adj_end, size, alignment)) | 439 | if (!check_free_hole(adj_start, adj_end, size, alignment)) |
| 414 | continue; | 440 | continue; |
| 415 | 441 | ||
| @@ -424,7 +450,7 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, | |||
| 424 | 450 | ||
| 425 | return best; | 451 | return best; |
| 426 | } | 452 | } |
| 427 | EXPORT_SYMBOL(drm_mm_search_free_in_range); | 453 | EXPORT_SYMBOL(drm_mm_search_free_in_range_generic); |
| 428 | 454 | ||
| 429 | /** | 455 | /** |
| 430 | * Moves an allocation. To be used with embedded struct drm_mm_node. | 456 | * Moves an allocation. To be used with embedded struct drm_mm_node. |
| @@ -437,6 +463,7 @@ void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) | |||
| 437 | new->mm = old->mm; | 463 | new->mm = old->mm; |
| 438 | new->start = old->start; | 464 | new->start = old->start; |
| 439 | new->size = old->size; | 465 | new->size = old->size; |
| 466 | new->color = old->color; | ||
| 440 | 467 | ||
| 441 | old->allocated = 0; | 468 | old->allocated = 0; |
| 442 | new->allocated = 1; | 469 | new->allocated = 1; |
| @@ -452,9 +479,12 @@ EXPORT_SYMBOL(drm_mm_replace_node); | |||
| 452 | * Warning: As long as the scan list is non-empty, no other operations than | 479 | * Warning: As long as the scan list is non-empty, no other operations than |
| 453 | * adding/removing nodes to/from the scan list are allowed. | 480 | * adding/removing nodes to/from the scan list are allowed. |
| 454 | */ | 481 | */ |
| 455 | void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, | 482 | void drm_mm_init_scan(struct drm_mm *mm, |
| 456 | unsigned alignment) | 483 | unsigned long size, |
| 484 | unsigned alignment, | ||
| 485 | unsigned long color) | ||
| 457 | { | 486 | { |
| 487 | mm->scan_color = color; | ||
| 458 | mm->scan_alignment = alignment; | 488 | mm->scan_alignment = alignment; |
| 459 | mm->scan_size = size; | 489 | mm->scan_size = size; |
| 460 | mm->scanned_blocks = 0; | 490 | mm->scanned_blocks = 0; |
| @@ -474,11 +504,14 @@ EXPORT_SYMBOL(drm_mm_init_scan); | |||
| 474 | * Warning: As long as the scan list is non-empty, no other operations than | 504 | * Warning: As long as the scan list is non-empty, no other operations than |
| 475 | * adding/removing nodes to/from the scan list are allowed. | 505 | * adding/removing nodes to/from the scan list are allowed. |
| 476 | */ | 506 | */ |
| 477 | void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size, | 507 | void drm_mm_init_scan_with_range(struct drm_mm *mm, |
| 508 | unsigned long size, | ||
| 478 | unsigned alignment, | 509 | unsigned alignment, |
| 510 | unsigned long color, | ||
| 479 | unsigned long start, | 511 | unsigned long start, |
| 480 | unsigned long end) | 512 | unsigned long end) |
| 481 | { | 513 | { |
| 514 | mm->scan_color = color; | ||
| 482 | mm->scan_alignment = alignment; | 515 | mm->scan_alignment = alignment; |
| 483 | mm->scan_size = size; | 516 | mm->scan_size = size; |
| 484 | mm->scanned_blocks = 0; | 517 | mm->scanned_blocks = 0; |
| @@ -522,17 +555,21 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) | |||
| 522 | 555 | ||
| 523 | hole_start = drm_mm_hole_node_start(prev_node); | 556 | hole_start = drm_mm_hole_node_start(prev_node); |
| 524 | hole_end = drm_mm_hole_node_end(prev_node); | 557 | hole_end = drm_mm_hole_node_end(prev_node); |
| 558 | |||
| 559 | adj_start = hole_start; | ||
| 560 | adj_end = hole_end; | ||
| 561 | |||
| 562 | if (mm->color_adjust) | ||
| 563 | mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); | ||
| 564 | |||
| 525 | if (mm->scan_check_range) { | 565 | if (mm->scan_check_range) { |
| 526 | adj_start = hole_start < mm->scan_start ? | 566 | if (adj_start < mm->scan_start) |
| 527 | mm->scan_start : hole_start; | 567 | adj_start = mm->scan_start; |
| 528 | adj_end = hole_end > mm->scan_end ? | 568 | if (adj_end > mm->scan_end) |
| 529 | mm->scan_end : hole_end; | 569 | adj_end = mm->scan_end; |
| 530 | } else { | ||
| 531 | adj_start = hole_start; | ||
| 532 | adj_end = hole_end; | ||
| 533 | } | 570 | } |
| 534 | 571 | ||
| 535 | if (check_free_hole(adj_start , adj_end, | 572 | if (check_free_hole(adj_start, adj_end, |
| 536 | mm->scan_size, mm->scan_alignment)) { | 573 | mm->scan_size, mm->scan_alignment)) { |
| 537 | mm->scan_hit_start = hole_start; | 574 | mm->scan_hit_start = hole_start; |
| 538 | mm->scan_hit_size = hole_end; | 575 | mm->scan_hit_size = hole_end; |
| @@ -616,6 +653,8 @@ int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size) | |||
| 616 | mm->head_node.size = start - mm->head_node.start; | 653 | mm->head_node.size = start - mm->head_node.start; |
| 617 | list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack); | 654 | list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack); |
| 618 | 655 | ||
| 656 | mm->color_adjust = NULL; | ||
| 657 | |||
| 619 | return 0; | 658 | return 0; |
| 620 | } | 659 | } |
| 621 | EXPORT_SYMBOL(drm_mm_init); | 660 | EXPORT_SYMBOL(drm_mm_init); |
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index 13f3d936472f..5320364582ce 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c | |||
| @@ -465,3 +465,52 @@ void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) | |||
| 465 | DRM_INFO("Module unloaded\n"); | 465 | DRM_INFO("Module unloaded\n"); |
| 466 | } | 466 | } |
| 467 | EXPORT_SYMBOL(drm_pci_exit); | 467 | EXPORT_SYMBOL(drm_pci_exit); |
| 468 | |||
| 469 | int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) | ||
| 470 | { | ||
| 471 | struct pci_dev *root; | ||
| 472 | int pos; | ||
| 473 | u32 lnkcap, lnkcap2; | ||
| 474 | |||
| 475 | *mask = 0; | ||
| 476 | if (!dev->pdev) | ||
| 477 | return -EINVAL; | ||
| 478 | |||
| 479 | if (!pci_is_pcie(dev->pdev)) | ||
| 480 | return -EINVAL; | ||
| 481 | |||
| 482 | root = dev->pdev->bus->self; | ||
| 483 | |||
| 484 | pos = pci_pcie_cap(root); | ||
| 485 | if (!pos) | ||
| 486 | return -EINVAL; | ||
| 487 | |||
| 488 | /* we've been informed via and serverworks don't make the cut */ | ||
| 489 | if (root->vendor == PCI_VENDOR_ID_VIA || | ||
| 490 | root->vendor == PCI_VENDOR_ID_SERVERWORKS) | ||
| 491 | return -EINVAL; | ||
| 492 | |||
| 493 | pci_read_config_dword(root, pos + PCI_EXP_LNKCAP, &lnkcap); | ||
| 494 | pci_read_config_dword(root, pos + PCI_EXP_LNKCAP2, &lnkcap2); | ||
| 495 | |||
| 496 | lnkcap &= PCI_EXP_LNKCAP_SLS; | ||
| 497 | lnkcap2 &= 0xfe; | ||
| 498 | |||
| 499 | if (lnkcap2) { /* PCIE GEN 3.0 */ | ||
| 500 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB) | ||
| 501 | *mask |= DRM_PCIE_SPEED_25; | ||
| 502 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB) | ||
| 503 | *mask |= DRM_PCIE_SPEED_50; | ||
| 504 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB) | ||
| 505 | *mask |= DRM_PCIE_SPEED_80; | ||
| 506 | } else { | ||
| 507 | if (lnkcap & 1) | ||
| 508 | *mask |= DRM_PCIE_SPEED_25; | ||
| 509 | if (lnkcap & 2) | ||
| 510 | *mask |= DRM_PCIE_SPEED_50; | ||
| 511 | } | ||
| 512 | |||
| 513 | DRM_INFO("probing gen 2 caps for device %x:%x = %x/%x\n", root->vendor, root->device, lnkcap, lnkcap2); | ||
| 514 | return 0; | ||
| 515 | } | ||
| 516 | EXPORT_SYMBOL(drm_pcie_get_speed_cap_mask); | ||
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c index fff87221f9e9..371c695322d9 100644 --- a/drivers/gpu/drm/drm_proc.c +++ b/drivers/gpu/drm/drm_proc.c | |||
| @@ -53,7 +53,6 @@ static struct drm_info_list drm_proc_list[] = { | |||
| 53 | {"name", drm_name_info, 0}, | 53 | {"name", drm_name_info, 0}, |
| 54 | {"vm", drm_vm_info, 0}, | 54 | {"vm", drm_vm_info, 0}, |
| 55 | {"clients", drm_clients_info, 0}, | 55 | {"clients", drm_clients_info, 0}, |
| 56 | {"queues", drm_queues_info, 0}, | ||
| 57 | {"bufs", drm_bufs_info, 0}, | 56 | {"bufs", drm_bufs_info, 0}, |
| 58 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, | 57 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, |
| 59 | #if DRM_DEBUG_CODE | 58 | #if DRM_DEBUG_CODE |
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 45cf1dd3eb9c..45ac8d6c92b7 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c | |||
| @@ -134,6 +134,7 @@ void drm_sysfs_destroy(void) | |||
| 134 | return; | 134 | return; |
| 135 | class_remove_file(drm_class, &class_attr_version.attr); | 135 | class_remove_file(drm_class, &class_attr_version.attr); |
| 136 | class_destroy(drm_class); | 136 | class_destroy(drm_class); |
| 137 | drm_class = NULL; | ||
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | /** | 140 | /** |
| @@ -554,6 +555,9 @@ void drm_sysfs_device_remove(struct drm_minor *minor) | |||
| 554 | 555 | ||
| 555 | int drm_class_device_register(struct device *dev) | 556 | int drm_class_device_register(struct device *dev) |
| 556 | { | 557 | { |
| 558 | if (!drm_class || IS_ERR(drm_class)) | ||
| 559 | return -ENOENT; | ||
| 560 | |||
| 557 | dev->class = drm_class; | 561 | dev->class = drm_class; |
| 558 | return device_register(dev); | 562 | return device_register(dev); |
| 559 | } | 563 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 4afb625128d7..32a34c85899b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c | |||
| @@ -237,7 +237,7 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc) | |||
| 237 | 237 | ||
| 238 | static bool | 238 | static bool |
| 239 | exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, | 239 | exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, |
| 240 | struct drm_display_mode *mode, | 240 | const struct drm_display_mode *mode, |
| 241 | struct drm_display_mode *adjusted_mode) | 241 | struct drm_display_mode *adjusted_mode) |
| 242 | { | 242 | { |
| 243 | DRM_DEBUG_KMS("%s\n", __FILE__); | 243 | DRM_DEBUG_KMS("%s\n", __FILE__); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index c82c90c443e7..277653d5fda0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h | |||
| @@ -174,7 +174,7 @@ struct exynos_drm_manager_ops { | |||
| 174 | void (*apply)(struct device *subdrv_dev); | 174 | void (*apply)(struct device *subdrv_dev); |
| 175 | void (*mode_fixup)(struct device *subdrv_dev, | 175 | void (*mode_fixup)(struct device *subdrv_dev, |
| 176 | struct drm_connector *connector, | 176 | struct drm_connector *connector, |
| 177 | struct drm_display_mode *mode, | 177 | const struct drm_display_mode *mode, |
| 178 | struct drm_display_mode *adjusted_mode); | 178 | struct drm_display_mode *adjusted_mode); |
| 179 | void (*mode_set)(struct device *subdrv_dev, void *mode); | 179 | void (*mode_set)(struct device *subdrv_dev, void *mode); |
| 180 | void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width, | 180 | void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width, |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 23d5ad379f86..4a13a747f5d4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c | |||
| @@ -108,7 +108,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
| 108 | 108 | ||
| 109 | static bool | 109 | static bool |
| 110 | exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, | 110 | exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, |
| 111 | struct drm_display_mode *mode, | 111 | const struct drm_display_mode *mode, |
| 112 | struct drm_display_mode *adjusted_mode) | 112 | struct drm_display_mode *adjusted_mode) |
| 113 | { | 113 | { |
| 114 | struct drm_device *dev = encoder->dev; | 114 | struct drm_device *dev = encoder->dev; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 5d9d2c2f8f3f..8ffcdf8b9e22 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c | |||
| @@ -142,7 +142,7 @@ static void drm_hdmi_disable_vblank(struct device *subdrv_dev) | |||
| 142 | 142 | ||
| 143 | static void drm_hdmi_mode_fixup(struct device *subdrv_dev, | 143 | static void drm_hdmi_mode_fixup(struct device *subdrv_dev, |
| 144 | struct drm_connector *connector, | 144 | struct drm_connector *connector, |
| 145 | struct drm_display_mode *mode, | 145 | const struct drm_display_mode *mode, |
| 146 | struct drm_display_mode *adjusted_mode) | 146 | struct drm_display_mode *adjusted_mode) |
| 147 | { | 147 | { |
| 148 | struct drm_hdmi_context *ctx = to_context(subdrv_dev); | 148 | struct drm_hdmi_context *ctx = to_context(subdrv_dev); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index bd8126996e52..a91c42088e42 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h | |||
| @@ -51,7 +51,7 @@ struct exynos_hdmi_ops { | |||
| 51 | 51 | ||
| 52 | /* manager */ | 52 | /* manager */ |
| 53 | void (*mode_fixup)(void *ctx, struct drm_connector *connector, | 53 | void (*mode_fixup)(void *ctx, struct drm_connector *connector, |
| 54 | struct drm_display_mode *mode, | 54 | const struct drm_display_mode *mode, |
| 55 | struct drm_display_mode *adjusted_mode); | 55 | struct drm_display_mode *adjusted_mode); |
| 56 | void (*mode_set)(void *ctx, void *mode); | 56 | void (*mode_set)(void *ctx, void *mode); |
| 57 | void (*get_max_resol)(void *ctx, unsigned int *width, | 57 | void (*get_max_resol)(void *ctx, unsigned int *width, |
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index a137e9e39a33..066bde3f19c4 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
| @@ -1940,7 +1940,7 @@ static void hdmi_conf_apply(struct hdmi_context *hdata) | |||
| 1940 | } | 1940 | } |
| 1941 | 1941 | ||
| 1942 | static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, | 1942 | static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, |
| 1943 | struct drm_display_mode *mode, | 1943 | const struct drm_display_mode *mode, |
| 1944 | struct drm_display_mode *adjusted_mode) | 1944 | struct drm_display_mode *adjusted_mode) |
| 1945 | { | 1945 | { |
| 1946 | struct drm_display_mode *m; | 1946 | struct drm_display_mode *m; |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index 187422018601..8c175345d85c 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c | |||
| @@ -82,7 +82,7 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector, | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder, | 84 | static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder, |
| 85 | struct drm_display_mode *mode, | 85 | const struct drm_display_mode *mode, |
| 86 | struct drm_display_mode *adjusted_mode) | 86 | struct drm_display_mode *adjusted_mode) |
| 87 | { | 87 | { |
| 88 | return true; | 88 | return true; |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index c3e9a0f701df..a68509ba22a8 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c | |||
| @@ -913,7 +913,7 @@ static void cdv_intel_crtc_commit(struct drm_crtc *crtc) | |||
| 913 | } | 913 | } |
| 914 | 914 | ||
| 915 | static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc, | 915 | static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc, |
| 916 | struct drm_display_mode *mode, | 916 | const struct drm_display_mode *mode, |
| 917 | struct drm_display_mode *adjusted_mode) | 917 | struct drm_display_mode *adjusted_mode) |
| 918 | { | 918 | { |
| 919 | return true; | 919 | return true; |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index 88b59d4a7b7f..a86f87b9ddde 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c | |||
| @@ -90,7 +90,7 @@ static void cdv_hdmi_mode_set(struct drm_encoder *encoder, | |||
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder, | 92 | static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder, |
| 93 | struct drm_display_mode *mode, | 93 | const struct drm_display_mode *mode, |
| 94 | struct drm_display_mode *adjusted_mode) | 94 | struct drm_display_mode *adjusted_mode) |
| 95 | { | 95 | { |
| 96 | return true; | 96 | return true; |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index ff5b58eb878c..c7f9468b74ba 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c | |||
| @@ -270,7 +270,7 @@ static int cdv_intel_lvds_mode_valid(struct drm_connector *connector, | |||
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder, | 272 | static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder, |
| 273 | struct drm_display_mode *mode, | 273 | const struct drm_display_mode *mode, |
| 274 | struct drm_display_mode *adjusted_mode) | 274 | struct drm_display_mode *adjusted_mode) |
| 275 | { | 275 | { |
| 276 | struct drm_device *dev = encoder->dev; | 276 | struct drm_device *dev = encoder->dev; |
diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c index 973d7f6d66b7..8d7caf0f363e 100644 --- a/drivers/gpu/drm/gma500/intel_bios.c +++ b/drivers/gpu/drm/gma500/intel_bios.c | |||
| @@ -427,7 +427,7 @@ parse_device_mapping(struct drm_psb_private *dev_priv, | |||
| 427 | * | 427 | * |
| 428 | * Returns 0 on success, nonzero on failure. | 428 | * Returns 0 on success, nonzero on failure. |
| 429 | */ | 429 | */ |
| 430 | bool psb_intel_init_bios(struct drm_device *dev) | 430 | int psb_intel_init_bios(struct drm_device *dev) |
| 431 | { | 431 | { |
| 432 | struct drm_psb_private *dev_priv = dev->dev_private; | 432 | struct drm_psb_private *dev_priv = dev->dev_private; |
| 433 | struct pci_dev *pdev = dev->pdev; | 433 | struct pci_dev *pdev = dev->pdev; |
diff --git a/drivers/gpu/drm/gma500/intel_bios.h b/drivers/gpu/drm/gma500/intel_bios.h index 0a738663eb5a..2e95523b84b1 100644 --- a/drivers/gpu/drm/gma500/intel_bios.h +++ b/drivers/gpu/drm/gma500/intel_bios.h | |||
| @@ -431,7 +431,7 @@ struct bdb_driver_features { | |||
| 431 | u8 custom_vbt_version; | 431 | u8 custom_vbt_version; |
| 432 | } __attribute__((packed)); | 432 | } __attribute__((packed)); |
| 433 | 433 | ||
| 434 | extern bool psb_intel_init_bios(struct drm_device *dev); | 434 | extern int psb_intel_init_bios(struct drm_device *dev); |
| 435 | extern void psb_intel_destroy_bios(struct drm_device *dev); | 435 | extern void psb_intel_destroy_bios(struct drm_device *dev); |
| 436 | 436 | ||
| 437 | /* | 437 | /* |
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c index b34ff097b979..d4813e03f5ee 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c | |||
| @@ -684,7 +684,7 @@ void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode) | |||
| 684 | } | 684 | } |
| 685 | 685 | ||
| 686 | bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, | 686 | bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, |
| 687 | struct drm_display_mode *mode, | 687 | const struct drm_display_mode *mode, |
| 688 | struct drm_display_mode *adjusted_mode) | 688 | struct drm_display_mode *adjusted_mode) |
| 689 | { | 689 | { |
| 690 | struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); | 690 | struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); |
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h index 6f762478b959..2b40663e1696 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h +++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h | |||
| @@ -65,7 +65,7 @@ extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, | |||
| 65 | /* MDFLD DPI helper functions */ | 65 | /* MDFLD DPI helper functions */ |
| 66 | extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode); | 66 | extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode); |
| 67 | extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, | 67 | extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, |
| 68 | struct drm_display_mode *mode, | 68 | const struct drm_display_mode *mode, |
| 69 | struct drm_display_mode *adjusted_mode); | 69 | struct drm_display_mode *adjusted_mode); |
| 70 | extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder); | 70 | extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder); |
| 71 | extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder); | 71 | extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder); |
diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c index 3f3cd619c79f..dec6a9aea3c6 100644 --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c | |||
| @@ -117,7 +117,7 @@ static void psb_intel_crtc_commit(struct drm_crtc *crtc) | |||
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, | 119 | static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, |
| 120 | struct drm_display_mode *mode, | 120 | const struct drm_display_mode *mode, |
| 121 | struct drm_display_mode *adjusted_mode) | 121 | struct drm_display_mode *adjusted_mode) |
| 122 | { | 122 | { |
| 123 | return true; | 123 | return true; |
diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index f821c835ca90..cdafd2acc72f 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c | |||
| @@ -487,7 +487,7 @@ oaktrail_crtc_mode_set_exit: | |||
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | static bool oaktrail_crtc_mode_fixup(struct drm_crtc *crtc, | 489 | static bool oaktrail_crtc_mode_fixup(struct drm_crtc *crtc, |
| 490 | struct drm_display_mode *mode, | 490 | const struct drm_display_mode *mode, |
| 491 | struct drm_display_mode *adjusted_mode) | 491 | struct drm_display_mode *adjusted_mode) |
| 492 | { | 492 | { |
| 493 | return true; | 493 | return true; |
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index c10899c953b9..2eb3dc4e9c9b 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c | |||
| @@ -191,7 +191,7 @@ static int oaktrail_hdmi_mode_valid(struct drm_connector *connector, | |||
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder, | 193 | static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder, |
| 194 | struct drm_display_mode *mode, | 194 | const struct drm_display_mode *mode, |
| 195 | struct drm_display_mode *adjusted_mode) | 195 | struct drm_display_mode *adjusted_mode) |
| 196 | { | 196 | { |
| 197 | return true; | 197 | return true; |
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index a8858a907f47..0c4737438530 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c | |||
| @@ -633,7 +633,6 @@ static struct drm_driver driver = { | |||
| 633 | .open = psb_driver_open, | 633 | .open = psb_driver_open, |
| 634 | .preclose = psb_driver_preclose, | 634 | .preclose = psb_driver_preclose, |
| 635 | .postclose = psb_driver_close, | 635 | .postclose = psb_driver_close, |
| 636 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 637 | 636 | ||
| 638 | .gem_init_object = psb_gem_init_object, | 637 | .gem_init_object = psb_gem_init_object, |
| 639 | .gem_free_object = psb_gem_free_object, | 638 | .gem_free_object = psb_gem_free_object, |
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index 36c3c99612f6..30dc22a7156c 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c | |||
| @@ -543,7 +543,7 @@ void psb_intel_encoder_destroy(struct drm_encoder *encoder) | |||
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, | 545 | static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, |
| 546 | struct drm_display_mode *mode, | 546 | const struct drm_display_mode *mode, |
| 547 | struct drm_display_mode *adjusted_mode) | 547 | struct drm_display_mode *adjusted_mode) |
| 548 | { | 548 | { |
| 549 | return true; | 549 | return true; |
diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index 2515f83248cb..ebe1a28f60e1 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h | |||
| @@ -268,7 +268,7 @@ extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device | |||
| 268 | *mode_cmd, | 268 | *mode_cmd, |
| 269 | void *mm_private); | 269 | void *mm_private); |
| 270 | extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, | 270 | extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, |
| 271 | struct drm_display_mode *mode, | 271 | const struct drm_display_mode *mode, |
| 272 | struct drm_display_mode *adjusted_mode); | 272 | struct drm_display_mode *adjusted_mode); |
| 273 | extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, | 273 | extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, |
| 274 | struct drm_display_mode *mode); | 274 | struct drm_display_mode *mode); |
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index c83f5b5d1057..37adc9edf974 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c | |||
| @@ -375,7 +375,7 @@ int psb_intel_lvds_mode_valid(struct drm_connector *connector, | |||
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, | 377 | bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, |
| 378 | struct drm_display_mode *mode, | 378 | const struct drm_display_mode *mode, |
| 379 | struct drm_display_mode *adjusted_mode) | 379 | struct drm_display_mode *adjusted_mode) |
| 380 | { | 380 | { |
| 381 | struct drm_device *dev = encoder->dev; | 381 | struct drm_device *dev = encoder->dev; |
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index d39b15be7649..0466c7b985f8 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c | |||
| @@ -901,7 +901,7 @@ static bool psb_intel_sdvo_set_tv_format(struct psb_intel_sdvo *psb_intel_sdvo) | |||
| 901 | 901 | ||
| 902 | static bool | 902 | static bool |
| 903 | psb_intel_sdvo_set_output_timings_from_mode(struct psb_intel_sdvo *psb_intel_sdvo, | 903 | psb_intel_sdvo_set_output_timings_from_mode(struct psb_intel_sdvo *psb_intel_sdvo, |
| 904 | struct drm_display_mode *mode) | 904 | const struct drm_display_mode *mode) |
| 905 | { | 905 | { |
| 906 | struct psb_intel_sdvo_dtd output_dtd; | 906 | struct psb_intel_sdvo_dtd output_dtd; |
| 907 | 907 | ||
| @@ -918,7 +918,7 @@ psb_intel_sdvo_set_output_timings_from_mode(struct psb_intel_sdvo *psb_intel_sdv | |||
| 918 | 918 | ||
| 919 | static bool | 919 | static bool |
| 920 | psb_intel_sdvo_set_input_timings_for_mode(struct psb_intel_sdvo *psb_intel_sdvo, | 920 | psb_intel_sdvo_set_input_timings_for_mode(struct psb_intel_sdvo *psb_intel_sdvo, |
| 921 | struct drm_display_mode *mode, | 921 | const struct drm_display_mode *mode, |
| 922 | struct drm_display_mode *adjusted_mode) | 922 | struct drm_display_mode *adjusted_mode) |
| 923 | { | 923 | { |
| 924 | /* Reset the input timing to the screen. Assume always input 0. */ | 924 | /* Reset the input timing to the screen. Assume always input 0. */ |
| @@ -942,7 +942,7 @@ psb_intel_sdvo_set_input_timings_for_mode(struct psb_intel_sdvo *psb_intel_sdvo, | |||
| 942 | } | 942 | } |
| 943 | 943 | ||
| 944 | static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, | 944 | static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, |
| 945 | struct drm_display_mode *mode, | 945 | const struct drm_display_mode *mode, |
| 946 | struct drm_display_mode *adjusted_mode) | 946 | struct drm_display_mode *adjusted_mode) |
| 947 | { | 947 | { |
| 948 | struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); | 948 | struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); |
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index d3f2e8785010..36d952280c50 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c | |||
| @@ -88,7 +88,7 @@ static void ch7006_encoder_restore(struct drm_encoder *encoder) | |||
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder, | 90 | static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder, |
| 91 | struct drm_display_mode *mode, | 91 | const struct drm_display_mode *mode, |
| 92 | struct drm_display_mode *adjusted_mode) | 92 | struct drm_display_mode *adjusted_mode) |
| 93 | { | 93 | { |
| 94 | struct ch7006_priv *priv = to_ch7006_priv(encoder); | 94 | struct ch7006_priv *priv = to_ch7006_priv(encoder); |
diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c index c860f24a5afc..9b83574141a6 100644 --- a/drivers/gpu/drm/i2c/ch7006_mode.c +++ b/drivers/gpu/drm/i2c/ch7006_mode.c | |||
| @@ -172,7 +172,7 @@ struct ch7006_mode ch7006_modes[] = { | |||
| 172 | }; | 172 | }; |
| 173 | 173 | ||
| 174 | struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, | 174 | struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, |
| 175 | struct drm_display_mode *drm_mode) | 175 | const struct drm_display_mode *drm_mode) |
| 176 | { | 176 | { |
| 177 | struct ch7006_priv *priv = to_ch7006_priv(encoder); | 177 | struct ch7006_priv *priv = to_ch7006_priv(encoder); |
| 178 | struct ch7006_mode *mode; | 178 | struct ch7006_mode *mode; |
diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h index 17667b7d57e7..09599f4c0c9a 100644 --- a/drivers/gpu/drm/i2c/ch7006_priv.h +++ b/drivers/gpu/drm/i2c/ch7006_priv.h | |||
| @@ -111,7 +111,7 @@ extern struct ch7006_tv_norm_info ch7006_tv_norms[]; | |||
| 111 | extern struct ch7006_mode ch7006_modes[]; | 111 | extern struct ch7006_mode ch7006_modes[]; |
| 112 | 112 | ||
| 113 | struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, | 113 | struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, |
| 114 | struct drm_display_mode *drm_mode); | 114 | const struct drm_display_mode *drm_mode); |
| 115 | 115 | ||
| 116 | void ch7006_setup_levels(struct drm_encoder *encoder); | 116 | void ch7006_setup_levels(struct drm_encoder *encoder); |
| 117 | void ch7006_setup_subcarrier(struct drm_encoder *encoder); | 117 | void ch7006_setup_subcarrier(struct drm_encoder *encoder); |
diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c index b7d45ab4ba69..30b8ae5e5c4a 100644 --- a/drivers/gpu/drm/i2c/sil164_drv.c +++ b/drivers/gpu/drm/i2c/sil164_drv.c | |||
| @@ -254,7 +254,7 @@ sil164_encoder_restore(struct drm_encoder *encoder) | |||
| 254 | 254 | ||
| 255 | static bool | 255 | static bool |
| 256 | sil164_encoder_mode_fixup(struct drm_encoder *encoder, | 256 | sil164_encoder_mode_fixup(struct drm_encoder *encoder, |
| 257 | struct drm_display_mode *mode, | 257 | const struct drm_display_mode *mode, |
| 258 | struct drm_display_mode *adjusted_mode) | 258 | struct drm_display_mode *adjusted_mode) |
| 259 | { | 259 | { |
| 260 | return true; | 260 | return true; |
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index fa9439159ebd..57d892eaaa6e 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c | |||
| @@ -881,7 +881,7 @@ static int i810_flush_queue(struct drm_device *dev) | |||
| 881 | } | 881 | } |
| 882 | 882 | ||
| 883 | /* Must be called with the lock held */ | 883 | /* Must be called with the lock held */ |
| 884 | static void i810_reclaim_buffers(struct drm_device *dev, | 884 | void i810_driver_reclaim_buffers(struct drm_device *dev, |
| 885 | struct drm_file *file_priv) | 885 | struct drm_file *file_priv) |
| 886 | { | 886 | { |
| 887 | struct drm_device_dma *dma = dev->dma; | 887 | struct drm_device_dma *dma = dev->dma; |
| @@ -1220,12 +1220,17 @@ void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) | |||
| 1220 | if (dev_priv->page_flipping) | 1220 | if (dev_priv->page_flipping) |
| 1221 | i810_do_cleanup_pageflip(dev); | 1221 | i810_do_cleanup_pageflip(dev); |
| 1222 | } | 1222 | } |
| 1223 | } | ||
| 1224 | 1223 | ||
| 1225 | void i810_driver_reclaim_buffers_locked(struct drm_device *dev, | 1224 | if (file_priv->master && file_priv->master->lock.hw_lock) { |
| 1226 | struct drm_file *file_priv) | 1225 | drm_idlelock_take(&file_priv->master->lock); |
| 1227 | { | 1226 | i810_driver_reclaim_buffers(dev, file_priv); |
| 1228 | i810_reclaim_buffers(dev, file_priv); | 1227 | drm_idlelock_release(&file_priv->master->lock); |
| 1228 | } else { | ||
| 1229 | /* master disappeared, clean up stuff anyway and hope nothing | ||
| 1230 | * goes wrong */ | ||
| 1231 | i810_driver_reclaim_buffers(dev, file_priv); | ||
| 1232 | } | ||
| 1233 | |||
| 1229 | } | 1234 | } |
| 1230 | 1235 | ||
| 1231 | int i810_driver_dma_quiescent(struct drm_device *dev) | 1236 | int i810_driver_dma_quiescent(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index ec12f7dc717a..f9924ad04d09 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c | |||
| @@ -57,13 +57,12 @@ static const struct file_operations i810_driver_fops = { | |||
| 57 | static struct drm_driver driver = { | 57 | static struct drm_driver driver = { |
| 58 | .driver_features = | 58 | .driver_features = |
| 59 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | | 59 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | |
| 60 | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE, | 60 | DRIVER_HAVE_DMA, |
| 61 | .dev_priv_size = sizeof(drm_i810_buf_priv_t), | 61 | .dev_priv_size = sizeof(drm_i810_buf_priv_t), |
| 62 | .load = i810_driver_load, | 62 | .load = i810_driver_load, |
| 63 | .lastclose = i810_driver_lastclose, | 63 | .lastclose = i810_driver_lastclose, |
| 64 | .preclose = i810_driver_preclose, | 64 | .preclose = i810_driver_preclose, |
| 65 | .device_is_agp = i810_driver_device_is_agp, | 65 | .device_is_agp = i810_driver_device_is_agp, |
| 66 | .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked, | ||
| 67 | .dma_quiescent = i810_driver_dma_quiescent, | 66 | .dma_quiescent = i810_driver_dma_quiescent, |
| 68 | .ioctls = i810_ioctls, | 67 | .ioctls = i810_ioctls, |
| 69 | .fops = &i810_driver_fops, | 68 | .fops = &i810_driver_fops, |
diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h index c9339f481795..6e0acad9e0f5 100644 --- a/drivers/gpu/drm/i810/i810_drv.h +++ b/drivers/gpu/drm/i810/i810_drv.h | |||
| @@ -116,14 +116,12 @@ typedef struct drm_i810_private { | |||
| 116 | 116 | ||
| 117 | /* i810_dma.c */ | 117 | /* i810_dma.c */ |
| 118 | extern int i810_driver_dma_quiescent(struct drm_device *dev); | 118 | extern int i810_driver_dma_quiescent(struct drm_device *dev); |
| 119 | extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev, | 119 | void i810_driver_reclaim_buffers(struct drm_device *dev, |
| 120 | struct drm_file *file_priv); | 120 | struct drm_file *file_priv); |
| 121 | extern int i810_driver_load(struct drm_device *, unsigned long flags); | 121 | extern int i810_driver_load(struct drm_device *, unsigned long flags); |
| 122 | extern void i810_driver_lastclose(struct drm_device *dev); | 122 | extern void i810_driver_lastclose(struct drm_device *dev); |
| 123 | extern void i810_driver_preclose(struct drm_device *dev, | 123 | extern void i810_driver_preclose(struct drm_device *dev, |
| 124 | struct drm_file *file_priv); | 124 | struct drm_file *file_priv); |
| 125 | extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev, | ||
| 126 | struct drm_file *file_priv); | ||
| 127 | extern int i810_driver_device_is_agp(struct drm_device *dev); | 125 | extern int i810_driver_device_is_agp(struct drm_device *dev); |
| 128 | 126 | ||
| 129 | extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 127 | extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 2e9268da58d8..b0bacdba6d7e 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
| @@ -7,6 +7,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \ | |||
| 7 | i915_debugfs.o \ | 7 | i915_debugfs.o \ |
| 8 | i915_suspend.o \ | 8 | i915_suspend.o \ |
| 9 | i915_gem.o \ | 9 | i915_gem.o \ |
| 10 | i915_gem_context.o \ | ||
| 10 | i915_gem_debug.o \ | 11 | i915_gem_debug.o \ |
| 11 | i915_gem_evict.o \ | 12 | i915_gem_evict.o \ |
| 12 | i915_gem_execbuffer.o \ | 13 | i915_gem_execbuffer.o \ |
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h index 8c2ad014c47f..58914691a77b 100644 --- a/drivers/gpu/drm/i915/dvo.h +++ b/drivers/gpu/drm/i915/dvo.h | |||
| @@ -86,7 +86,7 @@ struct intel_dvo_dev_ops { | |||
| 86 | * buses with clock limitations. | 86 | * buses with clock limitations. |
| 87 | */ | 87 | */ |
| 88 | bool (*mode_fixup)(struct intel_dvo_device *dvo, | 88 | bool (*mode_fixup)(struct intel_dvo_device *dvo, |
| 89 | struct drm_display_mode *mode, | 89 | const struct drm_display_mode *mode, |
| 90 | struct drm_display_mode *adjusted_mode); | 90 | struct drm_display_mode *adjusted_mode); |
| 91 | 91 | ||
| 92 | /* | 92 | /* |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5363e9c66c27..359f6e8b9b00 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
| @@ -676,6 +676,7 @@ static void i915_ring_error_state(struct seq_file *m, | |||
| 676 | seq_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]); | 676 | seq_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]); |
| 677 | seq_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]); | 677 | seq_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]); |
| 678 | if (INTEL_INFO(dev)->gen >= 6) { | 678 | if (INTEL_INFO(dev)->gen >= 6) { |
| 679 | seq_printf(m, " RC PSMI: 0x%08x\n", error->rc_psmi[ring]); | ||
| 679 | seq_printf(m, " FAULT_REG: 0x%08x\n", error->fault_reg[ring]); | 680 | seq_printf(m, " FAULT_REG: 0x%08x\n", error->fault_reg[ring]); |
| 680 | seq_printf(m, " SYNC_0: 0x%08x\n", | 681 | seq_printf(m, " SYNC_0: 0x%08x\n", |
| 681 | error->semaphore_mboxes[ring][0]); | 682 | error->semaphore_mboxes[ring][0]); |
| @@ -713,6 +714,7 @@ static int i915_error_state(struct seq_file *m, void *unused) | |||
| 713 | seq_printf(m, "EIR: 0x%08x\n", error->eir); | 714 | seq_printf(m, "EIR: 0x%08x\n", error->eir); |
| 714 | seq_printf(m, "IER: 0x%08x\n", error->ier); | 715 | seq_printf(m, "IER: 0x%08x\n", error->ier); |
| 715 | seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); | 716 | seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); |
| 717 | seq_printf(m, "CCID: 0x%08x\n", error->ccid); | ||
| 716 | 718 | ||
| 717 | for (i = 0; i < dev_priv->num_fence_regs; i++) | 719 | for (i = 0; i < dev_priv->num_fence_regs; i++) |
| 718 | seq_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); | 720 | seq_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); |
| @@ -1765,6 +1767,64 @@ static const struct file_operations i915_max_freq_fops = { | |||
| 1765 | }; | 1767 | }; |
| 1766 | 1768 | ||
| 1767 | static ssize_t | 1769 | static ssize_t |
| 1770 | i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max, | ||
| 1771 | loff_t *ppos) | ||
| 1772 | { | ||
| 1773 | struct drm_device *dev = filp->private_data; | ||
| 1774 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 1775 | char buf[80]; | ||
| 1776 | int len; | ||
| 1777 | |||
| 1778 | len = snprintf(buf, sizeof(buf), | ||
| 1779 | "min freq: %d\n", dev_priv->min_delay * 50); | ||
| 1780 | |||
| 1781 | if (len > sizeof(buf)) | ||
| 1782 | len = sizeof(buf); | ||
| 1783 | |||
| 1784 | return simple_read_from_buffer(ubuf, max, ppos, buf, len); | ||
| 1785 | } | ||
| 1786 | |||
| 1787 | static ssize_t | ||
| 1788 | i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt, | ||
| 1789 | loff_t *ppos) | ||
| 1790 | { | ||
| 1791 | struct drm_device *dev = filp->private_data; | ||
| 1792 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1793 | char buf[20]; | ||
| 1794 | int val = 1; | ||
| 1795 | |||
| 1796 | if (cnt > 0) { | ||
| 1797 | if (cnt > sizeof(buf) - 1) | ||
| 1798 | return -EINVAL; | ||
| 1799 | |||
| 1800 | if (copy_from_user(buf, ubuf, cnt)) | ||
| 1801 | return -EFAULT; | ||
| 1802 | buf[cnt] = 0; | ||
| 1803 | |||
| 1804 | val = simple_strtoul(buf, NULL, 0); | ||
| 1805 | } | ||
| 1806 | |||
| 1807 | DRM_DEBUG_DRIVER("Manually setting min freq to %d\n", val); | ||
| 1808 | |||
| 1809 | /* | ||
| 1810 | * Turbo will still be enabled, but won't go below the set value. | ||
| 1811 | */ | ||
| 1812 | dev_priv->min_delay = val / 50; | ||
| 1813 | |||
| 1814 | gen6_set_rps(dev, val / 50); | ||
| 1815 | |||
| 1816 | return cnt; | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | static const struct file_operations i915_min_freq_fops = { | ||
| 1820 | .owner = THIS_MODULE, | ||
| 1821 | .open = simple_open, | ||
| 1822 | .read = i915_min_freq_read, | ||
| 1823 | .write = i915_min_freq_write, | ||
| 1824 | .llseek = default_llseek, | ||
| 1825 | }; | ||
| 1826 | |||
| 1827 | static ssize_t | ||
| 1768 | i915_cache_sharing_read(struct file *filp, | 1828 | i915_cache_sharing_read(struct file *filp, |
| 1769 | char __user *ubuf, | 1829 | char __user *ubuf, |
| 1770 | size_t max, | 1830 | size_t max, |
| @@ -1997,6 +2057,12 @@ int i915_debugfs_init(struct drm_minor *minor) | |||
| 1997 | return ret; | 2057 | return ret; |
| 1998 | 2058 | ||
| 1999 | ret = i915_debugfs_create(minor->debugfs_root, minor, | 2059 | ret = i915_debugfs_create(minor->debugfs_root, minor, |
| 2060 | "i915_min_freq", | ||
| 2061 | &i915_min_freq_fops); | ||
| 2062 | if (ret) | ||
| 2063 | return ret; | ||
| 2064 | |||
| 2065 | ret = i915_debugfs_create(minor->debugfs_root, minor, | ||
| 2000 | "i915_cache_sharing", | 2066 | "i915_cache_sharing", |
| 2001 | &i915_cache_sharing_fops); | 2067 | &i915_cache_sharing_fops); |
| 2002 | if (ret) | 2068 | if (ret) |
| @@ -2028,6 +2094,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor) | |||
| 2028 | 1, minor); | 2094 | 1, minor); |
| 2029 | drm_debugfs_remove_files((struct drm_info_list *) &i915_max_freq_fops, | 2095 | drm_debugfs_remove_files((struct drm_info_list *) &i915_max_freq_fops, |
| 2030 | 1, minor); | 2096 | 1, minor); |
| 2097 | drm_debugfs_remove_files((struct drm_info_list *) &i915_min_freq_fops, | ||
| 2098 | 1, minor); | ||
| 2031 | drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops, | 2099 | drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops, |
| 2032 | 1, minor); | 2100 | 1, minor); |
| 2033 | drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops, | 2101 | drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops, |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 36822b924eb1..9cf7dfe022b9 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -1006,6 +1006,9 @@ static int i915_getparam(struct drm_device *dev, void *data, | |||
| 1006 | case I915_PARAM_HAS_ALIASING_PPGTT: | 1006 | case I915_PARAM_HAS_ALIASING_PPGTT: |
| 1007 | value = dev_priv->mm.aliasing_ppgtt ? 1 : 0; | 1007 | value = dev_priv->mm.aliasing_ppgtt ? 1 : 0; |
| 1008 | break; | 1008 | break; |
| 1009 | case I915_PARAM_HAS_WAIT_TIMEOUT: | ||
| 1010 | value = 1; | ||
| 1011 | break; | ||
| 1009 | default: | 1012 | default: |
| 1010 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", | 1013 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", |
| 1011 | param->param); | 1014 | param->param); |
| @@ -1082,8 +1085,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data, | |||
| 1082 | 1085 | ||
| 1083 | ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12); | 1086 | ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12); |
| 1084 | 1087 | ||
| 1085 | dev_priv->dri1.gfx_hws_cpu_addr = ioremap_wc(dev->agp->base + hws->addr, | 1088 | dev_priv->dri1.gfx_hws_cpu_addr = |
| 1086 | 4096); | 1089 | ioremap_wc(dev_priv->mm.gtt_base_addr + hws->addr, 4096); |
| 1087 | if (dev_priv->dri1.gfx_hws_cpu_addr == NULL) { | 1090 | if (dev_priv->dri1.gfx_hws_cpu_addr == NULL) { |
| 1088 | i915_dma_cleanup(dev); | 1091 | i915_dma_cleanup(dev); |
| 1089 | ring->status_page.gfx_addr = 0; | 1092 | ring->status_page.gfx_addr = 0; |
| @@ -1411,7 +1414,7 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) | |||
| 1411 | if (!ap) | 1414 | if (!ap) |
| 1412 | return; | 1415 | return; |
| 1413 | 1416 | ||
| 1414 | ap->ranges[0].base = dev_priv->dev->agp->base; | 1417 | ap->ranges[0].base = dev_priv->mm.gtt->gma_bus_addr; |
| 1415 | ap->ranges[0].size = | 1418 | ap->ranges[0].size = |
| 1416 | dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; | 1419 | dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; |
| 1417 | primary = | 1420 | primary = |
| @@ -1467,11 +1470,18 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1467 | goto free_priv; | 1470 | goto free_priv; |
| 1468 | } | 1471 | } |
| 1469 | 1472 | ||
| 1473 | ret = intel_gmch_probe(dev_priv->bridge_dev, dev->pdev, NULL); | ||
| 1474 | if (!ret) { | ||
| 1475 | DRM_ERROR("failed to set up gmch\n"); | ||
| 1476 | ret = -EIO; | ||
| 1477 | goto put_bridge; | ||
| 1478 | } | ||
| 1479 | |||
| 1470 | dev_priv->mm.gtt = intel_gtt_get(); | 1480 | dev_priv->mm.gtt = intel_gtt_get(); |
| 1471 | if (!dev_priv->mm.gtt) { | 1481 | if (!dev_priv->mm.gtt) { |
| 1472 | DRM_ERROR("Failed to initialize GTT\n"); | 1482 | DRM_ERROR("Failed to initialize GTT\n"); |
| 1473 | ret = -ENODEV; | 1483 | ret = -ENODEV; |
| 1474 | goto put_bridge; | 1484 | goto put_gmch; |
| 1475 | } | 1485 | } |
| 1476 | 1486 | ||
| 1477 | i915_kick_out_firmware_fb(dev_priv); | 1487 | i915_kick_out_firmware_fb(dev_priv); |
| @@ -1498,19 +1508,22 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1498 | if (!dev_priv->regs) { | 1508 | if (!dev_priv->regs) { |
| 1499 | DRM_ERROR("failed to map registers\n"); | 1509 | DRM_ERROR("failed to map registers\n"); |
| 1500 | ret = -EIO; | 1510 | ret = -EIO; |
| 1501 | goto put_bridge; | 1511 | goto put_gmch; |
| 1502 | } | 1512 | } |
| 1503 | 1513 | ||
| 1504 | aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; | 1514 | aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; |
| 1515 | dev_priv->mm.gtt_base_addr = dev_priv->mm.gtt->gma_bus_addr; | ||
| 1505 | 1516 | ||
| 1506 | dev_priv->mm.gtt_mapping = | 1517 | dev_priv->mm.gtt_mapping = |
| 1507 | io_mapping_create_wc(dev->agp->base, aperture_size); | 1518 | io_mapping_create_wc(dev_priv->mm.gtt_base_addr, |
| 1519 | aperture_size); | ||
| 1508 | if (dev_priv->mm.gtt_mapping == NULL) { | 1520 | if (dev_priv->mm.gtt_mapping == NULL) { |
| 1509 | ret = -EIO; | 1521 | ret = -EIO; |
| 1510 | goto out_rmmap; | 1522 | goto out_rmmap; |
| 1511 | } | 1523 | } |
| 1512 | 1524 | ||
| 1513 | i915_mtrr_setup(dev_priv, dev->agp->base, aperture_size); | 1525 | i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr, |
| 1526 | aperture_size); | ||
| 1514 | 1527 | ||
| 1515 | /* The i915 workqueue is primarily used for batched retirement of | 1528 | /* The i915 workqueue is primarily used for batched retirement of |
| 1516 | * requests (and thus managing bo) once the task has been completed | 1529 | * requests (and thus managing bo) once the task has been completed |
| @@ -1534,7 +1547,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1534 | goto out_mtrrfree; | 1547 | goto out_mtrrfree; |
| 1535 | } | 1548 | } |
| 1536 | 1549 | ||
| 1550 | /* This must be called before any calls to HAS_PCH_* */ | ||
| 1551 | intel_detect_pch(dev); | ||
| 1552 | |||
| 1537 | intel_irq_init(dev); | 1553 | intel_irq_init(dev); |
| 1554 | intel_gt_init(dev); | ||
| 1538 | 1555 | ||
| 1539 | /* Try to make sure MCHBAR is enabled before poking at it */ | 1556 | /* Try to make sure MCHBAR is enabled before poking at it */ |
| 1540 | intel_setup_mchbar(dev); | 1557 | intel_setup_mchbar(dev); |
| @@ -1567,7 +1584,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1567 | if (!IS_I945G(dev) && !IS_I945GM(dev)) | 1584 | if (!IS_I945G(dev) && !IS_I945GM(dev)) |
| 1568 | pci_enable_msi(dev->pdev); | 1585 | pci_enable_msi(dev->pdev); |
| 1569 | 1586 | ||
| 1570 | spin_lock_init(&dev_priv->gt_lock); | ||
| 1571 | spin_lock_init(&dev_priv->irq_lock); | 1587 | spin_lock_init(&dev_priv->irq_lock); |
| 1572 | spin_lock_init(&dev_priv->error_lock); | 1588 | spin_lock_init(&dev_priv->error_lock); |
| 1573 | spin_lock_init(&dev_priv->rps_lock); | 1589 | spin_lock_init(&dev_priv->rps_lock); |
| @@ -1586,8 +1602,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1586 | /* Start out suspended */ | 1602 | /* Start out suspended */ |
| 1587 | dev_priv->mm.suspended = 1; | 1603 | dev_priv->mm.suspended = 1; |
| 1588 | 1604 | ||
| 1589 | intel_detect_pch(dev); | ||
| 1590 | |||
| 1591 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 1605 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 1592 | ret = i915_load_modeset_init(dev); | 1606 | ret = i915_load_modeset_init(dev); |
| 1593 | if (ret < 0) { | 1607 | if (ret < 0) { |
| @@ -1622,13 +1636,16 @@ out_gem_unload: | |||
| 1622 | destroy_workqueue(dev_priv->wq); | 1636 | destroy_workqueue(dev_priv->wq); |
| 1623 | out_mtrrfree: | 1637 | out_mtrrfree: |
| 1624 | if (dev_priv->mm.gtt_mtrr >= 0) { | 1638 | if (dev_priv->mm.gtt_mtrr >= 0) { |
| 1625 | mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, | 1639 | mtrr_del(dev_priv->mm.gtt_mtrr, |
| 1626 | dev->agp->agp_info.aper_size * 1024 * 1024); | 1640 | dev_priv->mm.gtt_base_addr, |
| 1641 | aperture_size); | ||
| 1627 | dev_priv->mm.gtt_mtrr = -1; | 1642 | dev_priv->mm.gtt_mtrr = -1; |
| 1628 | } | 1643 | } |
| 1629 | io_mapping_free(dev_priv->mm.gtt_mapping); | 1644 | io_mapping_free(dev_priv->mm.gtt_mapping); |
| 1630 | out_rmmap: | 1645 | out_rmmap: |
| 1631 | pci_iounmap(dev->pdev, dev_priv->regs); | 1646 | pci_iounmap(dev->pdev, dev_priv->regs); |
| 1647 | put_gmch: | ||
| 1648 | intel_gmch_remove(); | ||
| 1632 | put_bridge: | 1649 | put_bridge: |
| 1633 | pci_dev_put(dev_priv->bridge_dev); | 1650 | pci_dev_put(dev_priv->bridge_dev); |
| 1634 | free_priv: | 1651 | free_priv: |
| @@ -1660,8 +1677,9 @@ int i915_driver_unload(struct drm_device *dev) | |||
| 1660 | 1677 | ||
| 1661 | io_mapping_free(dev_priv->mm.gtt_mapping); | 1678 | io_mapping_free(dev_priv->mm.gtt_mapping); |
| 1662 | if (dev_priv->mm.gtt_mtrr >= 0) { | 1679 | if (dev_priv->mm.gtt_mtrr >= 0) { |
| 1663 | mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, | 1680 | mtrr_del(dev_priv->mm.gtt_mtrr, |
| 1664 | dev->agp->agp_info.aper_size * 1024 * 1024); | 1681 | dev_priv->mm.gtt_base_addr, |
| 1682 | dev_priv->mm.gtt->gtt_mappable_entries * PAGE_SIZE); | ||
| 1665 | dev_priv->mm.gtt_mtrr = -1; | 1683 | dev_priv->mm.gtt_mtrr = -1; |
| 1666 | } | 1684 | } |
| 1667 | 1685 | ||
| @@ -1702,6 +1720,7 @@ int i915_driver_unload(struct drm_device *dev) | |||
| 1702 | mutex_lock(&dev->struct_mutex); | 1720 | mutex_lock(&dev->struct_mutex); |
| 1703 | i915_gem_free_all_phys_object(dev); | 1721 | i915_gem_free_all_phys_object(dev); |
| 1704 | i915_gem_cleanup_ringbuffer(dev); | 1722 | i915_gem_cleanup_ringbuffer(dev); |
| 1723 | i915_gem_context_fini(dev); | ||
| 1705 | mutex_unlock(&dev->struct_mutex); | 1724 | mutex_unlock(&dev->struct_mutex); |
| 1706 | i915_gem_cleanup_aliasing_ppgtt(dev); | 1725 | i915_gem_cleanup_aliasing_ppgtt(dev); |
| 1707 | i915_gem_cleanup_stolen(dev); | 1726 | i915_gem_cleanup_stolen(dev); |
| @@ -1741,6 +1760,8 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file) | |||
| 1741 | spin_lock_init(&file_priv->mm.lock); | 1760 | spin_lock_init(&file_priv->mm.lock); |
| 1742 | INIT_LIST_HEAD(&file_priv->mm.request_list); | 1761 | INIT_LIST_HEAD(&file_priv->mm.request_list); |
| 1743 | 1762 | ||
| 1763 | idr_init(&file_priv->context_idr); | ||
| 1764 | |||
| 1744 | return 0; | 1765 | return 0; |
| 1745 | } | 1766 | } |
| 1746 | 1767 | ||
| @@ -1760,7 +1781,13 @@ void i915_driver_lastclose(struct drm_device * dev) | |||
| 1760 | { | 1781 | { |
| 1761 | drm_i915_private_t *dev_priv = dev->dev_private; | 1782 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 1762 | 1783 | ||
| 1763 | if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) { | 1784 | /* On gen6+ we refuse to init without kms enabled, but then the drm core |
| 1785 | * goes right around and calls lastclose. Check for this and don't clean | ||
| 1786 | * up anything. */ | ||
| 1787 | if (!dev_priv) | ||
| 1788 | return; | ||
| 1789 | |||
| 1790 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
| 1764 | intel_fb_restore_mode(dev); | 1791 | intel_fb_restore_mode(dev); |
| 1765 | vga_switcheroo_process_delayed_switch(); | 1792 | vga_switcheroo_process_delayed_switch(); |
| 1766 | return; | 1793 | return; |
| @@ -1773,6 +1800,7 @@ void i915_driver_lastclose(struct drm_device * dev) | |||
| 1773 | 1800 | ||
| 1774 | void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) | 1801 | void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) |
| 1775 | { | 1802 | { |
| 1803 | i915_gem_context_close(dev, file_priv); | ||
| 1776 | i915_gem_release(dev, file_priv); | 1804 | i915_gem_release(dev, file_priv); |
| 1777 | } | 1805 | } |
| 1778 | 1806 | ||
| @@ -1826,6 +1854,9 @@ struct drm_ioctl_desc i915_ioctls[] = { | |||
| 1826 | DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 1854 | DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
| 1827 | DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 1855 | DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
| 1828 | DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 1856 | DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
| 1857 | DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_UNLOCKED), | ||
| 1858 | DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED), | ||
| 1859 | DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED), | ||
| 1829 | }; | 1860 | }; |
| 1830 | 1861 | ||
| 1831 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); | 1862 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 9fe9ebe52a7a..ed22612bc847 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "drm.h" | 32 | #include "drm.h" |
| 33 | #include "i915_drm.h" | 33 | #include "i915_drm.h" |
| 34 | #include "i915_drv.h" | 34 | #include "i915_drv.h" |
| 35 | #include "i915_trace.h" | ||
| 35 | #include "intel_drv.h" | 36 | #include "intel_drv.h" |
| 36 | 37 | ||
| 37 | #include <linux/console.h> | 38 | #include <linux/console.h> |
| @@ -215,7 +216,6 @@ static const struct intel_device_info intel_ironlake_d_info = { | |||
| 215 | .gen = 5, | 216 | .gen = 5, |
| 216 | .need_gfx_hws = 1, .has_hotplug = 1, | 217 | .need_gfx_hws = 1, .has_hotplug = 1, |
| 217 | .has_bsd_ring = 1, | 218 | .has_bsd_ring = 1, |
| 218 | .has_pch_split = 1, | ||
| 219 | }; | 219 | }; |
| 220 | 220 | ||
| 221 | static const struct intel_device_info intel_ironlake_m_info = { | 221 | static const struct intel_device_info intel_ironlake_m_info = { |
| @@ -223,7 +223,6 @@ static const struct intel_device_info intel_ironlake_m_info = { | |||
| 223 | .need_gfx_hws = 1, .has_hotplug = 1, | 223 | .need_gfx_hws = 1, .has_hotplug = 1, |
| 224 | .has_fbc = 1, | 224 | .has_fbc = 1, |
| 225 | .has_bsd_ring = 1, | 225 | .has_bsd_ring = 1, |
| 226 | .has_pch_split = 1, | ||
| 227 | }; | 226 | }; |
| 228 | 227 | ||
| 229 | static const struct intel_device_info intel_sandybridge_d_info = { | 228 | static const struct intel_device_info intel_sandybridge_d_info = { |
| @@ -232,7 +231,6 @@ static const struct intel_device_info intel_sandybridge_d_info = { | |||
| 232 | .has_bsd_ring = 1, | 231 | .has_bsd_ring = 1, |
| 233 | .has_blt_ring = 1, | 232 | .has_blt_ring = 1, |
| 234 | .has_llc = 1, | 233 | .has_llc = 1, |
| 235 | .has_pch_split = 1, | ||
| 236 | .has_force_wake = 1, | 234 | .has_force_wake = 1, |
| 237 | }; | 235 | }; |
| 238 | 236 | ||
| @@ -243,7 +241,6 @@ static const struct intel_device_info intel_sandybridge_m_info = { | |||
| 243 | .has_bsd_ring = 1, | 241 | .has_bsd_ring = 1, |
| 244 | .has_blt_ring = 1, | 242 | .has_blt_ring = 1, |
| 245 | .has_llc = 1, | 243 | .has_llc = 1, |
| 246 | .has_pch_split = 1, | ||
| 247 | .has_force_wake = 1, | 244 | .has_force_wake = 1, |
| 248 | }; | 245 | }; |
| 249 | 246 | ||
| @@ -253,7 +250,6 @@ static const struct intel_device_info intel_ivybridge_d_info = { | |||
| 253 | .has_bsd_ring = 1, | 250 | .has_bsd_ring = 1, |
| 254 | .has_blt_ring = 1, | 251 | .has_blt_ring = 1, |
| 255 | .has_llc = 1, | 252 | .has_llc = 1, |
| 256 | .has_pch_split = 1, | ||
| 257 | .has_force_wake = 1, | 253 | .has_force_wake = 1, |
| 258 | }; | 254 | }; |
| 259 | 255 | ||
| @@ -264,7 +260,6 @@ static const struct intel_device_info intel_ivybridge_m_info = { | |||
| 264 | .has_bsd_ring = 1, | 260 | .has_bsd_ring = 1, |
| 265 | .has_blt_ring = 1, | 261 | .has_blt_ring = 1, |
| 266 | .has_llc = 1, | 262 | .has_llc = 1, |
| 267 | .has_pch_split = 1, | ||
| 268 | .has_force_wake = 1, | 263 | .has_force_wake = 1, |
| 269 | }; | 264 | }; |
| 270 | 265 | ||
| @@ -292,7 +287,6 @@ static const struct intel_device_info intel_haswell_d_info = { | |||
| 292 | .has_bsd_ring = 1, | 287 | .has_bsd_ring = 1, |
| 293 | .has_blt_ring = 1, | 288 | .has_blt_ring = 1, |
| 294 | .has_llc = 1, | 289 | .has_llc = 1, |
| 295 | .has_pch_split = 1, | ||
| 296 | .has_force_wake = 1, | 290 | .has_force_wake = 1, |
| 297 | }; | 291 | }; |
| 298 | 292 | ||
| @@ -302,7 +296,6 @@ static const struct intel_device_info intel_haswell_m_info = { | |||
| 302 | .has_bsd_ring = 1, | 296 | .has_bsd_ring = 1, |
| 303 | .has_blt_ring = 1, | 297 | .has_blt_ring = 1, |
| 304 | .has_llc = 1, | 298 | .has_llc = 1, |
| 305 | .has_pch_split = 1, | ||
| 306 | .has_force_wake = 1, | 299 | .has_force_wake = 1, |
| 307 | }; | 300 | }; |
| 308 | 301 | ||
| @@ -358,6 +351,9 @@ static const struct pci_device_id pciidlist[] = { /* aka */ | |||
| 358 | INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */ | 351 | INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */ |
| 359 | INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */ | 352 | INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */ |
| 360 | INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */ | 353 | INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */ |
| 354 | INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info), | ||
| 355 | INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info), | ||
| 356 | INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info), | ||
| 361 | {0, 0, 0} | 357 | {0, 0, 0} |
| 362 | }; | 358 | }; |
| 363 | 359 | ||
| @@ -429,135 +425,6 @@ bool i915_semaphore_is_enabled(struct drm_device *dev) | |||
| 429 | return 1; | 425 | return 1; |
| 430 | } | 426 | } |
| 431 | 427 | ||
| 432 | void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 433 | { | ||
| 434 | int count; | ||
| 435 | |||
| 436 | count = 0; | ||
| 437 | while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1)) | ||
| 438 | udelay(10); | ||
| 439 | |||
| 440 | I915_WRITE_NOTRACE(FORCEWAKE, 1); | ||
| 441 | POSTING_READ(FORCEWAKE); | ||
| 442 | |||
| 443 | count = 0; | ||
| 444 | while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0) | ||
| 445 | udelay(10); | ||
| 446 | } | ||
| 447 | |||
| 448 | void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) | ||
| 449 | { | ||
| 450 | int count; | ||
| 451 | |||
| 452 | count = 0; | ||
| 453 | while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1)) | ||
| 454 | udelay(10); | ||
| 455 | |||
| 456 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1)); | ||
| 457 | POSTING_READ(FORCEWAKE_MT); | ||
| 458 | |||
| 459 | count = 0; | ||
| 460 | while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0) | ||
| 461 | udelay(10); | ||
| 462 | } | ||
| 463 | |||
| 464 | /* | ||
| 465 | * Generally this is called implicitly by the register read function. However, | ||
| 466 | * if some sequence requires the GT to not power down then this function should | ||
| 467 | * be called at the beginning of the sequence followed by a call to | ||
| 468 | * gen6_gt_force_wake_put() at the end of the sequence. | ||
| 469 | */ | ||
| 470 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 471 | { | ||
| 472 | unsigned long irqflags; | ||
| 473 | |||
| 474 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); | ||
| 475 | if (dev_priv->forcewake_count++ == 0) | ||
| 476 | dev_priv->display.force_wake_get(dev_priv); | ||
| 477 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | ||
| 478 | } | ||
| 479 | |||
| 480 | static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) | ||
| 481 | { | ||
| 482 | u32 gtfifodbg; | ||
| 483 | gtfifodbg = I915_READ_NOTRACE(GTFIFODBG); | ||
| 484 | if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, | ||
| 485 | "MMIO read or write has been dropped %x\n", gtfifodbg)) | ||
| 486 | I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); | ||
| 487 | } | ||
| 488 | |||
| 489 | void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 490 | { | ||
| 491 | I915_WRITE_NOTRACE(FORCEWAKE, 0); | ||
| 492 | /* The below doubles as a POSTING_READ */ | ||
| 493 | gen6_gt_check_fifodbg(dev_priv); | ||
| 494 | } | ||
| 495 | |||
| 496 | void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) | ||
| 497 | { | ||
| 498 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1)); | ||
| 499 | /* The below doubles as a POSTING_READ */ | ||
| 500 | gen6_gt_check_fifodbg(dev_priv); | ||
| 501 | } | ||
| 502 | |||
| 503 | /* | ||
| 504 | * see gen6_gt_force_wake_get() | ||
| 505 | */ | ||
| 506 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 507 | { | ||
| 508 | unsigned long irqflags; | ||
| 509 | |||
| 510 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); | ||
| 511 | if (--dev_priv->forcewake_count == 0) | ||
| 512 | dev_priv->display.force_wake_put(dev_priv); | ||
| 513 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | ||
| 514 | } | ||
| 515 | |||
| 516 | int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) | ||
| 517 | { | ||
| 518 | int ret = 0; | ||
| 519 | |||
| 520 | if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { | ||
| 521 | int loop = 500; | ||
| 522 | u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | ||
| 523 | while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { | ||
| 524 | udelay(10); | ||
| 525 | fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | ||
| 526 | } | ||
| 527 | if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES)) | ||
| 528 | ++ret; | ||
| 529 | dev_priv->gt_fifo_count = fifo; | ||
| 530 | } | ||
| 531 | dev_priv->gt_fifo_count--; | ||
| 532 | |||
| 533 | return ret; | ||
| 534 | } | ||
| 535 | |||
| 536 | void vlv_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 537 | { | ||
| 538 | int count; | ||
| 539 | |||
| 540 | count = 0; | ||
| 541 | |||
| 542 | /* Already awake? */ | ||
| 543 | if ((I915_READ(0x130094) & 0xa1) == 0xa1) | ||
| 544 | return; | ||
| 545 | |||
| 546 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff); | ||
| 547 | POSTING_READ(FORCEWAKE_VLV); | ||
| 548 | |||
| 549 | count = 0; | ||
| 550 | while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0) | ||
| 551 | udelay(10); | ||
| 552 | } | ||
| 553 | |||
| 554 | void vlv_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 555 | { | ||
| 556 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000); | ||
| 557 | /* FIXME: confirm VLV behavior with Punit folks */ | ||
| 558 | POSTING_READ(FORCEWAKE_VLV); | ||
| 559 | } | ||
| 560 | |||
| 561 | static int i915_drm_freeze(struct drm_device *dev) | 428 | static int i915_drm_freeze(struct drm_device *dev) |
| 562 | { | 429 | { |
| 563 | struct drm_i915_private *dev_priv = dev->dev_private; | 430 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -637,7 +504,7 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
| 637 | 504 | ||
| 638 | /* KMS EnterVT equivalent */ | 505 | /* KMS EnterVT equivalent */ |
| 639 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 506 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 640 | if (HAS_PCH_SPLIT(dev)) | 507 | if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) |
| 641 | ironlake_init_pch_refclk(dev); | 508 | ironlake_init_pch_refclk(dev); |
| 642 | 509 | ||
| 643 | mutex_lock(&dev->struct_mutex); | 510 | mutex_lock(&dev->struct_mutex); |
| @@ -794,9 +661,9 @@ static int gen6_do_reset(struct drm_device *dev) | |||
| 794 | 661 | ||
| 795 | /* If reset with a user forcewake, try to restore, otherwise turn it off */ | 662 | /* If reset with a user forcewake, try to restore, otherwise turn it off */ |
| 796 | if (dev_priv->forcewake_count) | 663 | if (dev_priv->forcewake_count) |
| 797 | dev_priv->display.force_wake_get(dev_priv); | 664 | dev_priv->gt.force_wake_get(dev_priv); |
| 798 | else | 665 | else |
| 799 | dev_priv->display.force_wake_put(dev_priv); | 666 | dev_priv->gt.force_wake_put(dev_priv); |
| 800 | 667 | ||
| 801 | /* Restore fifo count */ | 668 | /* Restore fifo count */ |
| 802 | dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | 669 | dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); |
| @@ -805,7 +672,7 @@ static int gen6_do_reset(struct drm_device *dev) | |||
| 805 | return ret; | 672 | return ret; |
| 806 | } | 673 | } |
| 807 | 674 | ||
| 808 | static int intel_gpu_reset(struct drm_device *dev) | 675 | int intel_gpu_reset(struct drm_device *dev) |
| 809 | { | 676 | { |
| 810 | struct drm_i915_private *dev_priv = dev->dev_private; | 677 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 811 | int ret = -ENODEV; | 678 | int ret = -ENODEV; |
| @@ -863,10 +730,7 @@ int i915_reset(struct drm_device *dev) | |||
| 863 | if (!i915_try_reset) | 730 | if (!i915_try_reset) |
| 864 | return 0; | 731 | return 0; |
| 865 | 732 | ||
| 866 | if (!mutex_trylock(&dev->struct_mutex)) | 733 | mutex_lock(&dev->struct_mutex); |
| 867 | return -EBUSY; | ||
| 868 | |||
| 869 | dev_priv->stop_rings = 0; | ||
| 870 | 734 | ||
| 871 | i915_gem_reset(dev); | 735 | i915_gem_reset(dev); |
| 872 | 736 | ||
| @@ -909,12 +773,16 @@ int i915_reset(struct drm_device *dev) | |||
| 909 | for_each_ring(ring, dev_priv, i) | 773 | for_each_ring(ring, dev_priv, i) |
| 910 | ring->init(ring); | 774 | ring->init(ring); |
| 911 | 775 | ||
| 776 | i915_gem_context_init(dev); | ||
| 912 | i915_gem_init_ppgtt(dev); | 777 | i915_gem_init_ppgtt(dev); |
| 913 | 778 | ||
| 914 | mutex_unlock(&dev->struct_mutex); | 779 | /* |
| 780 | * It would make sense to re-init all the other hw state, at | ||
| 781 | * least the rps/rc6/emon init done within modeset_init_hw. For | ||
| 782 | * some unknown reason, this blows up my ilk, so don't. | ||
| 783 | */ | ||
| 915 | 784 | ||
| 916 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | 785 | mutex_unlock(&dev->struct_mutex); |
| 917 | intel_modeset_init_hw(dev); | ||
| 918 | 786 | ||
| 919 | drm_irq_uninstall(dev); | 787 | drm_irq_uninstall(dev); |
| 920 | drm_irq_install(dev); | 788 | drm_irq_install(dev); |
| @@ -925,10 +793,12 @@ int i915_reset(struct drm_device *dev) | |||
| 925 | return 0; | 793 | return 0; |
| 926 | } | 794 | } |
| 927 | 795 | ||
| 928 | |||
| 929 | static int __devinit | 796 | static int __devinit |
| 930 | i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 797 | i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 931 | { | 798 | { |
| 799 | struct intel_device_info *intel_info = | ||
| 800 | (struct intel_device_info *) ent->driver_data; | ||
| 801 | |||
| 932 | /* Only bind to function 0 of the device. Early generations | 802 | /* Only bind to function 0 of the device. Early generations |
| 933 | * used function 1 as a placeholder for multi-head. This causes | 803 | * used function 1 as a placeholder for multi-head. This causes |
| 934 | * us confusion instead, especially on the systems where both | 804 | * us confusion instead, especially on the systems where both |
| @@ -937,6 +807,18 @@ i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 937 | if (PCI_FUNC(pdev->devfn)) | 807 | if (PCI_FUNC(pdev->devfn)) |
| 938 | return -ENODEV; | 808 | return -ENODEV; |
| 939 | 809 | ||
| 810 | /* We've managed to ship a kms-enabled ddx that shipped with an XvMC | ||
| 811 | * implementation for gen3 (and only gen3) that used legacy drm maps | ||
| 812 | * (gasp!) to share buffers between X and the client. Hence we need to | ||
| 813 | * keep around the fake agp stuff for gen3, even when kms is enabled. */ | ||
| 814 | if (intel_info->gen != 3) { | ||
| 815 | driver.driver_features &= | ||
| 816 | ~(DRIVER_USE_AGP | DRIVER_REQUIRE_AGP); | ||
| 817 | } else if (!intel_agp_enabled) { | ||
| 818 | DRM_ERROR("drm/i915 can't work without intel_agp module!\n"); | ||
| 819 | return -ENODEV; | ||
| 820 | } | ||
| 821 | |||
| 940 | return drm_get_pci_dev(pdev, ent, &driver); | 822 | return drm_get_pci_dev(pdev, ent, &driver); |
| 941 | } | 823 | } |
| 942 | 824 | ||
| @@ -1058,7 +940,6 @@ static struct drm_driver driver = { | |||
| 1058 | .resume = i915_resume, | 940 | .resume = i915_resume, |
| 1059 | 941 | ||
| 1060 | .device_is_agp = i915_driver_device_is_agp, | 942 | .device_is_agp = i915_driver_device_is_agp, |
| 1061 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 1062 | .master_create = i915_master_create, | 943 | .master_create = i915_master_create, |
| 1063 | .master_destroy = i915_master_destroy, | 944 | .master_destroy = i915_master_destroy, |
| 1064 | #if defined(CONFIG_DEBUG_FS) | 945 | #if defined(CONFIG_DEBUG_FS) |
| @@ -1097,11 +978,6 @@ static struct pci_driver i915_pci_driver = { | |||
| 1097 | 978 | ||
| 1098 | static int __init i915_init(void) | 979 | static int __init i915_init(void) |
| 1099 | { | 980 | { |
| 1100 | if (!intel_agp_enabled) { | ||
| 1101 | DRM_ERROR("drm/i915 can't work without intel_agp module!\n"); | ||
| 1102 | return -ENODEV; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | driver.num_ioctls = i915_max_ioctl; | 981 | driver.num_ioctls = i915_max_ioctl; |
| 1106 | 982 | ||
| 1107 | /* | 983 | /* |
| @@ -1149,6 +1025,84 @@ MODULE_LICENSE("GPL and additional rights"); | |||
| 1149 | ((reg) < 0x40000) && \ | 1025 | ((reg) < 0x40000) && \ |
| 1150 | ((reg) != FORCEWAKE)) | 1026 | ((reg) != FORCEWAKE)) |
| 1151 | 1027 | ||
| 1028 | static bool IS_DISPLAYREG(u32 reg) | ||
| 1029 | { | ||
| 1030 | /* | ||
| 1031 | * This should make it easier to transition modules over to the | ||
| 1032 | * new register block scheme, since we can do it incrementally. | ||
| 1033 | */ | ||
| 1034 | if (reg >= 0x180000) | ||
| 1035 | return false; | ||
| 1036 | |||
| 1037 | if (reg >= RENDER_RING_BASE && | ||
| 1038 | reg < RENDER_RING_BASE + 0xff) | ||
| 1039 | return false; | ||
| 1040 | if (reg >= GEN6_BSD_RING_BASE && | ||
| 1041 | reg < GEN6_BSD_RING_BASE + 0xff) | ||
| 1042 | return false; | ||
| 1043 | if (reg >= BLT_RING_BASE && | ||
| 1044 | reg < BLT_RING_BASE + 0xff) | ||
| 1045 | return false; | ||
| 1046 | |||
| 1047 | if (reg == PGTBL_ER) | ||
| 1048 | return false; | ||
| 1049 | |||
| 1050 | if (reg >= IPEIR_I965 && | ||
| 1051 | reg < HWSTAM) | ||
| 1052 | return false; | ||
| 1053 | |||
| 1054 | if (reg == MI_MODE) | ||
| 1055 | return false; | ||
| 1056 | |||
| 1057 | if (reg == GFX_MODE_GEN7) | ||
| 1058 | return false; | ||
| 1059 | |||
| 1060 | if (reg == RENDER_HWS_PGA_GEN7 || | ||
| 1061 | reg == BSD_HWS_PGA_GEN7 || | ||
| 1062 | reg == BLT_HWS_PGA_GEN7) | ||
| 1063 | return false; | ||
| 1064 | |||
| 1065 | if (reg == GEN6_BSD_SLEEP_PSMI_CONTROL || | ||
| 1066 | reg == GEN6_BSD_RNCID) | ||
| 1067 | return false; | ||
| 1068 | |||
| 1069 | if (reg == GEN6_BLITTER_ECOSKPD) | ||
| 1070 | return false; | ||
| 1071 | |||
| 1072 | if (reg >= 0x4000c && | ||
| 1073 | reg <= 0x4002c) | ||
| 1074 | return false; | ||
| 1075 | |||
| 1076 | if (reg >= 0x4f000 && | ||
| 1077 | reg <= 0x4f08f) | ||
| 1078 | return false; | ||
| 1079 | |||
| 1080 | if (reg >= 0x4f100 && | ||
| 1081 | reg <= 0x4f11f) | ||
| 1082 | return false; | ||
| 1083 | |||
| 1084 | if (reg >= VLV_MASTER_IER && | ||
| 1085 | reg <= GEN6_PMIER) | ||
| 1086 | return false; | ||
| 1087 | |||
| 1088 | if (reg >= FENCE_REG_SANDYBRIDGE_0 && | ||
| 1089 | reg < (FENCE_REG_SANDYBRIDGE_0 + (16*8))) | ||
| 1090 | return false; | ||
| 1091 | |||
| 1092 | if (reg >= VLV_IIR_RW && | ||
| 1093 | reg <= VLV_ISR) | ||
| 1094 | return false; | ||
| 1095 | |||
| 1096 | if (reg == FORCEWAKE_VLV || | ||
| 1097 | reg == FORCEWAKE_ACK_VLV) | ||
| 1098 | return false; | ||
| 1099 | |||
| 1100 | if (reg == GEN6_GDRST) | ||
| 1101 | return false; | ||
| 1102 | |||
| 1103 | return true; | ||
| 1104 | } | ||
| 1105 | |||
| 1152 | #define __i915_read(x, y) \ | 1106 | #define __i915_read(x, y) \ |
| 1153 | u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ | 1107 | u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ |
| 1154 | u##x val = 0; \ | 1108 | u##x val = 0; \ |
| @@ -1156,11 +1110,13 @@ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ | |||
| 1156 | unsigned long irqflags; \ | 1110 | unsigned long irqflags; \ |
| 1157 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \ | 1111 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \ |
| 1158 | if (dev_priv->forcewake_count == 0) \ | 1112 | if (dev_priv->forcewake_count == 0) \ |
| 1159 | dev_priv->display.force_wake_get(dev_priv); \ | 1113 | dev_priv->gt.force_wake_get(dev_priv); \ |
| 1160 | val = read##y(dev_priv->regs + reg); \ | 1114 | val = read##y(dev_priv->regs + reg); \ |
| 1161 | if (dev_priv->forcewake_count == 0) \ | 1115 | if (dev_priv->forcewake_count == 0) \ |
| 1162 | dev_priv->display.force_wake_put(dev_priv); \ | 1116 | dev_priv->gt.force_wake_put(dev_priv); \ |
| 1163 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \ | 1117 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \ |
| 1118 | } else if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \ | ||
| 1119 | val = read##y(dev_priv->regs + reg + 0x180000); \ | ||
| 1164 | } else { \ | 1120 | } else { \ |
| 1165 | val = read##y(dev_priv->regs + reg); \ | 1121 | val = read##y(dev_priv->regs + reg); \ |
| 1166 | } \ | 1122 | } \ |
| @@ -1181,7 +1137,11 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ | |||
| 1181 | if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ | 1137 | if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ |
| 1182 | __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ | 1138 | __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ |
| 1183 | } \ | 1139 | } \ |
| 1184 | write##y(val, dev_priv->regs + reg); \ | 1140 | if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \ |
| 1141 | write##y(val, dev_priv->regs + reg + 0x180000); \ | ||
| 1142 | } else { \ | ||
| 1143 | write##y(val, dev_priv->regs + reg); \ | ||
| 1144 | } \ | ||
| 1185 | if (unlikely(__fifo_ret)) { \ | 1145 | if (unlikely(__fifo_ret)) { \ |
| 1186 | gen6_gt_check_fifodbg(dev_priv); \ | 1146 | gen6_gt_check_fifodbg(dev_priv); \ |
| 1187 | } \ | 1147 | } \ |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b0b676abde0d..627fe35781b4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -79,6 +79,10 @@ enum port { | |||
| 79 | 79 | ||
| 80 | #define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++) | 80 | #define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++) |
| 81 | 81 | ||
| 82 | #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \ | ||
| 83 | list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \ | ||
| 84 | if ((intel_encoder)->base.crtc == (__crtc)) | ||
| 85 | |||
| 82 | struct intel_pch_pll { | 86 | struct intel_pch_pll { |
| 83 | int refcount; /* count of number of CRTCs sharing this PLL */ | 87 | int refcount; /* count of number of CRTCs sharing this PLL */ |
| 84 | int active; /* count of number of active CRTCs (i.e. DPMS on) */ | 88 | int active; /* count of number of active CRTCs (i.e. DPMS on) */ |
| @@ -176,6 +180,7 @@ struct drm_i915_error_state { | |||
| 176 | u32 eir; | 180 | u32 eir; |
| 177 | u32 pgtbl_er; | 181 | u32 pgtbl_er; |
| 178 | u32 ier; | 182 | u32 ier; |
| 183 | u32 ccid; | ||
| 179 | bool waiting[I915_NUM_RINGS]; | 184 | bool waiting[I915_NUM_RINGS]; |
| 180 | u32 pipestat[I915_MAX_PIPES]; | 185 | u32 pipestat[I915_MAX_PIPES]; |
| 181 | u32 tail[I915_NUM_RINGS]; | 186 | u32 tail[I915_NUM_RINGS]; |
| @@ -185,6 +190,7 @@ struct drm_i915_error_state { | |||
| 185 | u32 instdone[I915_NUM_RINGS]; | 190 | u32 instdone[I915_NUM_RINGS]; |
| 186 | u32 acthd[I915_NUM_RINGS]; | 191 | u32 acthd[I915_NUM_RINGS]; |
| 187 | u32 semaphore_mboxes[I915_NUM_RINGS][I915_NUM_RINGS - 1]; | 192 | u32 semaphore_mboxes[I915_NUM_RINGS][I915_NUM_RINGS - 1]; |
| 193 | u32 rc_psmi[I915_NUM_RINGS]; /* sleep state */ | ||
| 188 | /* our own tracking of ring head and tail */ | 194 | /* our own tracking of ring head and tail */ |
| 189 | u32 cpu_ring_head[I915_NUM_RINGS]; | 195 | u32 cpu_ring_head[I915_NUM_RINGS]; |
| 190 | u32 cpu_ring_tail[I915_NUM_RINGS]; | 196 | u32 cpu_ring_tail[I915_NUM_RINGS]; |
| @@ -261,8 +267,6 @@ struct drm_i915_display_funcs { | |||
| 261 | struct drm_i915_gem_object *obj); | 267 | struct drm_i915_gem_object *obj); |
| 262 | int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 268 | int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
| 263 | int x, int y); | 269 | int x, int y); |
| 264 | void (*force_wake_get)(struct drm_i915_private *dev_priv); | ||
| 265 | void (*force_wake_put)(struct drm_i915_private *dev_priv); | ||
| 266 | /* clock updates for mode set */ | 270 | /* clock updates for mode set */ |
| 267 | /* cursor updates */ | 271 | /* cursor updates */ |
| 268 | /* render clock increase/decrease */ | 272 | /* render clock increase/decrease */ |
| @@ -270,6 +274,11 @@ struct drm_i915_display_funcs { | |||
| 270 | /* pll clock increase/decrease */ | 274 | /* pll clock increase/decrease */ |
| 271 | }; | 275 | }; |
| 272 | 276 | ||
| 277 | struct drm_i915_gt_funcs { | ||
| 278 | void (*force_wake_get)(struct drm_i915_private *dev_priv); | ||
| 279 | void (*force_wake_put)(struct drm_i915_private *dev_priv); | ||
| 280 | }; | ||
| 281 | |||
| 273 | struct intel_device_info { | 282 | struct intel_device_info { |
| 274 | u8 gen; | 283 | u8 gen; |
| 275 | u8 is_mobile:1; | 284 | u8 is_mobile:1; |
| @@ -284,7 +293,6 @@ struct intel_device_info { | |||
| 284 | u8 is_crestline:1; | 293 | u8 is_crestline:1; |
| 285 | u8 is_ivybridge:1; | 294 | u8 is_ivybridge:1; |
| 286 | u8 is_valleyview:1; | 295 | u8 is_valleyview:1; |
| 287 | u8 has_pch_split:1; | ||
| 288 | u8 has_force_wake:1; | 296 | u8 has_force_wake:1; |
| 289 | u8 is_haswell:1; | 297 | u8 is_haswell:1; |
| 290 | u8 has_fbc:1; | 298 | u8 has_fbc:1; |
| @@ -309,6 +317,17 @@ struct i915_hw_ppgtt { | |||
| 309 | dma_addr_t scratch_page_dma_addr; | 317 | dma_addr_t scratch_page_dma_addr; |
| 310 | }; | 318 | }; |
| 311 | 319 | ||
| 320 | |||
| 321 | /* This must match up with the value previously used for execbuf2.rsvd1. */ | ||
| 322 | #define DEFAULT_CONTEXT_ID 0 | ||
| 323 | struct i915_hw_context { | ||
| 324 | int id; | ||
| 325 | bool is_initialized; | ||
| 326 | struct drm_i915_file_private *file_priv; | ||
| 327 | struct intel_ring_buffer *ring; | ||
| 328 | struct drm_i915_gem_object *obj; | ||
| 329 | }; | ||
| 330 | |||
| 312 | enum no_fbc_reason { | 331 | enum no_fbc_reason { |
| 313 | FBC_NO_OUTPUT, /* no outputs enabled to compress */ | 332 | FBC_NO_OUTPUT, /* no outputs enabled to compress */ |
| 314 | FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */ | 333 | FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */ |
| @@ -321,6 +340,7 @@ enum no_fbc_reason { | |||
| 321 | }; | 340 | }; |
| 322 | 341 | ||
| 323 | enum intel_pch { | 342 | enum intel_pch { |
| 343 | PCH_NONE = 0, /* No PCH present */ | ||
| 324 | PCH_IBX, /* Ibexpeak PCH */ | 344 | PCH_IBX, /* Ibexpeak PCH */ |
| 325 | PCH_CPT, /* Cougarpoint PCH */ | 345 | PCH_CPT, /* Cougarpoint PCH */ |
| 326 | PCH_LPT, /* Lynxpoint PCH */ | 346 | PCH_LPT, /* Lynxpoint PCH */ |
| @@ -350,6 +370,8 @@ typedef struct drm_i915_private { | |||
| 350 | int relative_constants_mode; | 370 | int relative_constants_mode; |
| 351 | 371 | ||
| 352 | void __iomem *regs; | 372 | void __iomem *regs; |
| 373 | |||
| 374 | struct drm_i915_gt_funcs gt; | ||
| 353 | /** gt_fifo_count and the subsequent register write are synchronized | 375 | /** gt_fifo_count and the subsequent register write are synchronized |
| 354 | * with dev->struct_mutex. */ | 376 | * with dev->struct_mutex. */ |
| 355 | unsigned gt_fifo_count; | 377 | unsigned gt_fifo_count; |
| @@ -652,11 +674,14 @@ typedef struct drm_i915_private { | |||
| 652 | unsigned long gtt_end; | 674 | unsigned long gtt_end; |
| 653 | 675 | ||
| 654 | struct io_mapping *gtt_mapping; | 676 | struct io_mapping *gtt_mapping; |
| 677 | phys_addr_t gtt_base_addr; | ||
| 655 | int gtt_mtrr; | 678 | int gtt_mtrr; |
| 656 | 679 | ||
| 657 | /** PPGTT used for aliasing the PPGTT with the GTT */ | 680 | /** PPGTT used for aliasing the PPGTT with the GTT */ |
| 658 | struct i915_hw_ppgtt *aliasing_ppgtt; | 681 | struct i915_hw_ppgtt *aliasing_ppgtt; |
| 659 | 682 | ||
| 683 | u32 *l3_remap_info; | ||
| 684 | |||
| 660 | struct shrinker inactive_shrinker; | 685 | struct shrinker inactive_shrinker; |
| 661 | 686 | ||
| 662 | /** | 687 | /** |
| @@ -817,6 +842,10 @@ typedef struct drm_i915_private { | |||
| 817 | 842 | ||
| 818 | struct drm_property *broadcast_rgb_property; | 843 | struct drm_property *broadcast_rgb_property; |
| 819 | struct drm_property *force_audio_property; | 844 | struct drm_property *force_audio_property; |
| 845 | |||
| 846 | struct work_struct parity_error_work; | ||
| 847 | bool hw_contexts_disabled; | ||
| 848 | uint32_t hw_context_size; | ||
| 820 | } drm_i915_private_t; | 849 | } drm_i915_private_t; |
| 821 | 850 | ||
| 822 | /* Iterate over initialised rings */ | 851 | /* Iterate over initialised rings */ |
| @@ -1026,6 +1055,7 @@ struct drm_i915_file_private { | |||
| 1026 | struct spinlock lock; | 1055 | struct spinlock lock; |
| 1027 | struct list_head request_list; | 1056 | struct list_head request_list; |
| 1028 | } mm; | 1057 | } mm; |
| 1058 | struct idr context_idr; | ||
| 1029 | }; | 1059 | }; |
| 1030 | 1060 | ||
| 1031 | #define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info) | 1061 | #define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info) |
| @@ -1071,7 +1101,8 @@ struct drm_i915_file_private { | |||
| 1071 | #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) | 1101 | #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) |
| 1072 | #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) | 1102 | #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) |
| 1073 | 1103 | ||
| 1074 | #define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >=6) | 1104 | #define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6) |
| 1105 | #define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >=6 && !IS_VALLEYVIEW(dev)) | ||
| 1075 | 1106 | ||
| 1076 | #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) | 1107 | #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) |
| 1077 | #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) | 1108 | #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) |
| @@ -1094,13 +1125,13 @@ struct drm_i915_file_private { | |||
| 1094 | #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) | 1125 | #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) |
| 1095 | #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) | 1126 | #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) |
| 1096 | 1127 | ||
| 1097 | #define HAS_PCH_SPLIT(dev) (INTEL_INFO(dev)->has_pch_split) | ||
| 1098 | #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5) | 1128 | #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5) |
| 1099 | 1129 | ||
| 1100 | #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) | 1130 | #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) |
| 1101 | #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT) | 1131 | #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT) |
| 1102 | #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) | 1132 | #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) |
| 1103 | #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) | 1133 | #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) |
| 1134 | #define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE) | ||
| 1104 | 1135 | ||
| 1105 | #define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) | 1136 | #define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) |
| 1106 | 1137 | ||
| @@ -1166,6 +1197,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, | |||
| 1166 | extern int i915_emit_box(struct drm_device *dev, | 1197 | extern int i915_emit_box(struct drm_device *dev, |
| 1167 | struct drm_clip_rect *box, | 1198 | struct drm_clip_rect *box, |
| 1168 | int DR1, int DR4); | 1199 | int DR1, int DR4); |
| 1200 | extern int intel_gpu_reset(struct drm_device *dev); | ||
| 1169 | extern int i915_reset(struct drm_device *dev); | 1201 | extern int i915_reset(struct drm_device *dev); |
| 1170 | extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); | 1202 | extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); |
| 1171 | extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); | 1203 | extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); |
| @@ -1178,6 +1210,7 @@ void i915_hangcheck_elapsed(unsigned long data); | |||
| 1178 | void i915_handle_error(struct drm_device *dev, bool wedged); | 1210 | void i915_handle_error(struct drm_device *dev, bool wedged); |
| 1179 | 1211 | ||
| 1180 | extern void intel_irq_init(struct drm_device *dev); | 1212 | extern void intel_irq_init(struct drm_device *dev); |
| 1213 | extern void intel_gt_init(struct drm_device *dev); | ||
| 1181 | 1214 | ||
| 1182 | void i915_error_state_free(struct kref *error_ref); | 1215 | void i915_error_state_free(struct kref *error_ref); |
| 1183 | 1216 | ||
| @@ -1237,6 +1270,8 @@ int i915_gem_get_tiling(struct drm_device *dev, void *data, | |||
| 1237 | struct drm_file *file_priv); | 1270 | struct drm_file *file_priv); |
| 1238 | int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | 1271 | int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, |
| 1239 | struct drm_file *file_priv); | 1272 | struct drm_file *file_priv); |
| 1273 | int i915_gem_wait_ioctl(struct drm_device *dev, void *data, | ||
| 1274 | struct drm_file *file_priv); | ||
| 1240 | void i915_gem_load(struct drm_device *dev); | 1275 | void i915_gem_load(struct drm_device *dev); |
| 1241 | int i915_gem_init_object(struct drm_gem_object *obj); | 1276 | int i915_gem_init_object(struct drm_gem_object *obj); |
| 1242 | int __must_check i915_gem_flush_ring(struct intel_ring_buffer *ring, | 1277 | int __must_check i915_gem_flush_ring(struct intel_ring_buffer *ring, |
| @@ -1306,6 +1341,8 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj) | |||
| 1306 | 1341 | ||
| 1307 | void i915_gem_retire_requests(struct drm_device *dev); | 1342 | void i915_gem_retire_requests(struct drm_device *dev); |
| 1308 | void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring); | 1343 | void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring); |
| 1344 | int __must_check i915_gem_check_wedge(struct drm_i915_private *dev_priv, | ||
| 1345 | bool interruptible); | ||
| 1309 | 1346 | ||
| 1310 | void i915_gem_reset(struct drm_device *dev); | 1347 | void i915_gem_reset(struct drm_device *dev); |
| 1311 | void i915_gem_clflush_object(struct drm_i915_gem_object *obj); | 1348 | void i915_gem_clflush_object(struct drm_i915_gem_object *obj); |
| @@ -1315,6 +1352,7 @@ int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj, | |||
| 1315 | int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj); | 1352 | int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj); |
| 1316 | int __must_check i915_gem_init(struct drm_device *dev); | 1353 | int __must_check i915_gem_init(struct drm_device *dev); |
| 1317 | int __must_check i915_gem_init_hw(struct drm_device *dev); | 1354 | int __must_check i915_gem_init_hw(struct drm_device *dev); |
| 1355 | void i915_gem_l3_remap(struct drm_device *dev); | ||
| 1318 | void i915_gem_init_swizzling(struct drm_device *dev); | 1356 | void i915_gem_init_swizzling(struct drm_device *dev); |
| 1319 | void i915_gem_init_ppgtt(struct drm_device *dev); | 1357 | void i915_gem_init_ppgtt(struct drm_device *dev); |
| 1320 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); | 1358 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); |
| @@ -1323,8 +1361,8 @@ int __must_check i915_gem_idle(struct drm_device *dev); | |||
| 1323 | int __must_check i915_add_request(struct intel_ring_buffer *ring, | 1361 | int __must_check i915_add_request(struct intel_ring_buffer *ring, |
| 1324 | struct drm_file *file, | 1362 | struct drm_file *file, |
| 1325 | struct drm_i915_gem_request *request); | 1363 | struct drm_i915_gem_request *request); |
| 1326 | int __must_check i915_wait_request(struct intel_ring_buffer *ring, | 1364 | int __must_check i915_wait_seqno(struct intel_ring_buffer *ring, |
| 1327 | uint32_t seqno); | 1365 | uint32_t seqno); |
| 1328 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); | 1366 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); |
| 1329 | int __must_check | 1367 | int __must_check |
| 1330 | i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, | 1368 | i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, |
| @@ -1358,6 +1396,16 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, | |||
| 1358 | struct dma_buf *i915_gem_prime_export(struct drm_device *dev, | 1396 | struct dma_buf *i915_gem_prime_export(struct drm_device *dev, |
| 1359 | struct drm_gem_object *gem_obj, int flags); | 1397 | struct drm_gem_object *gem_obj, int flags); |
| 1360 | 1398 | ||
| 1399 | /* i915_gem_context.c */ | ||
| 1400 | void i915_gem_context_init(struct drm_device *dev); | ||
| 1401 | void i915_gem_context_fini(struct drm_device *dev); | ||
| 1402 | void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); | ||
| 1403 | int i915_switch_context(struct intel_ring_buffer *ring, | ||
| 1404 | struct drm_file *file, int to_id); | ||
| 1405 | int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, | ||
| 1406 | struct drm_file *file); | ||
| 1407 | int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, | ||
| 1408 | struct drm_file *file); | ||
| 1361 | 1409 | ||
| 1362 | /* i915_gem_gtt.c */ | 1410 | /* i915_gem_gtt.c */ |
| 1363 | int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); | 1411 | int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); |
| @@ -1475,20 +1523,12 @@ extern bool intel_fbc_enabled(struct drm_device *dev); | |||
| 1475 | extern void intel_disable_fbc(struct drm_device *dev); | 1523 | extern void intel_disable_fbc(struct drm_device *dev); |
| 1476 | extern bool ironlake_set_drps(struct drm_device *dev, u8 val); | 1524 | extern bool ironlake_set_drps(struct drm_device *dev, u8 val); |
| 1477 | extern void ironlake_init_pch_refclk(struct drm_device *dev); | 1525 | extern void ironlake_init_pch_refclk(struct drm_device *dev); |
| 1478 | extern void ironlake_enable_rc6(struct drm_device *dev); | ||
| 1479 | extern void gen6_set_rps(struct drm_device *dev, u8 val); | 1526 | extern void gen6_set_rps(struct drm_device *dev, u8 val); |
| 1480 | extern void intel_detect_pch(struct drm_device *dev); | 1527 | extern void intel_detect_pch(struct drm_device *dev); |
| 1481 | extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); | 1528 | extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); |
| 1482 | extern int intel_enable_rc6(const struct drm_device *dev); | 1529 | extern int intel_enable_rc6(const struct drm_device *dev); |
| 1483 | 1530 | ||
| 1484 | extern bool i915_semaphore_is_enabled(struct drm_device *dev); | 1531 | extern bool i915_semaphore_is_enabled(struct drm_device *dev); |
| 1485 | extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); | ||
| 1486 | extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv); | ||
| 1487 | extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); | ||
| 1488 | extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv); | ||
| 1489 | |||
| 1490 | extern void vlv_force_wake_get(struct drm_i915_private *dev_priv); | ||
| 1491 | extern void vlv_force_wake_put(struct drm_i915_private *dev_priv); | ||
| 1492 | 1532 | ||
| 1493 | /* overlay */ | 1533 | /* overlay */ |
| 1494 | #ifdef CONFIG_DEBUG_FS | 1534 | #ifdef CONFIG_DEBUG_FS |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 288d7b8f49ae..5c4657a54f97 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -96,9 +96,18 @@ i915_gem_wait_for_error(struct drm_device *dev) | |||
| 96 | if (!atomic_read(&dev_priv->mm.wedged)) | 96 | if (!atomic_read(&dev_priv->mm.wedged)) |
| 97 | return 0; | 97 | return 0; |
| 98 | 98 | ||
| 99 | ret = wait_for_completion_interruptible(x); | 99 | /* |
| 100 | if (ret) | 100 | * Only wait 10 seconds for the gpu reset to complete to avoid hanging |
| 101 | * userspace. If it takes that long something really bad is going on and | ||
| 102 | * we should simply try to bail out and fail as gracefully as possible. | ||
| 103 | */ | ||
| 104 | ret = wait_for_completion_interruptible_timeout(x, 10*HZ); | ||
| 105 | if (ret == 0) { | ||
| 106 | DRM_ERROR("Timed out waiting for the gpu reset to complete\n"); | ||
| 107 | return -EIO; | ||
| 108 | } else if (ret < 0) { | ||
| 101 | return ret; | 109 | return ret; |
| 110 | } | ||
| 102 | 111 | ||
| 103 | if (atomic_read(&dev_priv->mm.wedged)) { | 112 | if (atomic_read(&dev_priv->mm.wedged)) { |
| 104 | /* GPU is hung, bump the completion count to account for | 113 | /* GPU is hung, bump the completion count to account for |
| @@ -1122,7 +1131,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 1122 | 1131 | ||
| 1123 | obj->fault_mappable = true; | 1132 | obj->fault_mappable = true; |
| 1124 | 1133 | ||
| 1125 | pfn = ((dev->agp->base + obj->gtt_offset) >> PAGE_SHIFT) + | 1134 | pfn = ((dev_priv->mm.gtt_base_addr + obj->gtt_offset) >> PAGE_SHIFT) + |
| 1126 | page_offset; | 1135 | page_offset; |
| 1127 | 1136 | ||
| 1128 | /* Finally, remap it using the new GTT offset */ | 1137 | /* Finally, remap it using the new GTT offset */ |
| @@ -1132,6 +1141,11 @@ unlock: | |||
| 1132 | out: | 1141 | out: |
| 1133 | switch (ret) { | 1142 | switch (ret) { |
| 1134 | case -EIO: | 1143 | case -EIO: |
| 1144 | /* If this -EIO is due to a gpu hang, give the reset code a | ||
| 1145 | * chance to clean up the mess. Otherwise return the proper | ||
| 1146 | * SIGBUS. */ | ||
| 1147 | if (!atomic_read(&dev_priv->mm.wedged)) | ||
| 1148 | return VM_FAULT_SIGBUS; | ||
| 1135 | case -EAGAIN: | 1149 | case -EAGAIN: |
| 1136 | /* Give the error handler a chance to run and move the | 1150 | /* Give the error handler a chance to run and move the |
| 1137 | * objects off the GPU active list. Next time we service the | 1151 | * objects off the GPU active list. Next time we service the |
| @@ -1568,6 +1582,21 @@ i915_add_request(struct intel_ring_buffer *ring, | |||
| 1568 | int was_empty; | 1582 | int was_empty; |
| 1569 | int ret; | 1583 | int ret; |
| 1570 | 1584 | ||
| 1585 | /* | ||
| 1586 | * Emit any outstanding flushes - execbuf can fail to emit the flush | ||
| 1587 | * after having emitted the batchbuffer command. Hence we need to fix | ||
| 1588 | * things up similar to emitting the lazy request. The difference here | ||
| 1589 | * is that the flush _must_ happen before the next request, no matter | ||
| 1590 | * what. | ||
| 1591 | */ | ||
| 1592 | if (ring->gpu_caches_dirty) { | ||
| 1593 | ret = i915_gem_flush_ring(ring, 0, I915_GEM_GPU_DOMAINS); | ||
| 1594 | if (ret) | ||
| 1595 | return ret; | ||
| 1596 | |||
| 1597 | ring->gpu_caches_dirty = false; | ||
| 1598 | } | ||
| 1599 | |||
| 1571 | BUG_ON(request == NULL); | 1600 | BUG_ON(request == NULL); |
| 1572 | seqno = i915_gem_next_request_seqno(ring); | 1601 | seqno = i915_gem_next_request_seqno(ring); |
| 1573 | 1602 | ||
| @@ -1613,6 +1642,9 @@ i915_add_request(struct intel_ring_buffer *ring, | |||
| 1613 | queue_delayed_work(dev_priv->wq, | 1642 | queue_delayed_work(dev_priv->wq, |
| 1614 | &dev_priv->mm.retire_work, HZ); | 1643 | &dev_priv->mm.retire_work, HZ); |
| 1615 | } | 1644 | } |
| 1645 | |||
| 1646 | WARN_ON(!list_empty(&ring->gpu_write_list)); | ||
| 1647 | |||
| 1616 | return 0; | 1648 | return 0; |
| 1617 | } | 1649 | } |
| 1618 | 1650 | ||
| @@ -1827,14 +1859,11 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
| 1827 | */ | 1859 | */ |
| 1828 | idle = true; | 1860 | idle = true; |
| 1829 | for_each_ring(ring, dev_priv, i) { | 1861 | for_each_ring(ring, dev_priv, i) { |
| 1830 | if (!list_empty(&ring->gpu_write_list)) { | 1862 | if (ring->gpu_caches_dirty) { |
| 1831 | struct drm_i915_gem_request *request; | 1863 | struct drm_i915_gem_request *request; |
| 1832 | int ret; | ||
| 1833 | 1864 | ||
| 1834 | ret = i915_gem_flush_ring(ring, | ||
| 1835 | 0, I915_GEM_GPU_DOMAINS); | ||
| 1836 | request = kzalloc(sizeof(*request), GFP_KERNEL); | 1865 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
| 1837 | if (ret || request == NULL || | 1866 | if (request == NULL || |
| 1838 | i915_add_request(ring, NULL, request)) | 1867 | i915_add_request(ring, NULL, request)) |
| 1839 | kfree(request); | 1868 | kfree(request); |
| 1840 | } | 1869 | } |
| @@ -1848,11 +1877,10 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
| 1848 | mutex_unlock(&dev->struct_mutex); | 1877 | mutex_unlock(&dev->struct_mutex); |
| 1849 | } | 1878 | } |
| 1850 | 1879 | ||
| 1851 | static int | 1880 | int |
| 1852 | i915_gem_check_wedge(struct drm_i915_private *dev_priv) | 1881 | i915_gem_check_wedge(struct drm_i915_private *dev_priv, |
| 1882 | bool interruptible) | ||
| 1853 | { | 1883 | { |
| 1854 | BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); | ||
| 1855 | |||
| 1856 | if (atomic_read(&dev_priv->mm.wedged)) { | 1884 | if (atomic_read(&dev_priv->mm.wedged)) { |
| 1857 | struct completion *x = &dev_priv->error_completion; | 1885 | struct completion *x = &dev_priv->error_completion; |
| 1858 | bool recovery_complete; | 1886 | bool recovery_complete; |
| @@ -1863,7 +1891,16 @@ i915_gem_check_wedge(struct drm_i915_private *dev_priv) | |||
| 1863 | recovery_complete = x->done > 0; | 1891 | recovery_complete = x->done > 0; |
| 1864 | spin_unlock_irqrestore(&x->wait.lock, flags); | 1892 | spin_unlock_irqrestore(&x->wait.lock, flags); |
| 1865 | 1893 | ||
| 1866 | return recovery_complete ? -EIO : -EAGAIN; | 1894 | /* Non-interruptible callers can't handle -EAGAIN, hence return |
| 1895 | * -EIO unconditionally for these. */ | ||
| 1896 | if (!interruptible) | ||
| 1897 | return -EIO; | ||
| 1898 | |||
| 1899 | /* Recovery complete, but still wedged means reset failure. */ | ||
| 1900 | if (recovery_complete) | ||
| 1901 | return -EIO; | ||
| 1902 | |||
| 1903 | return -EAGAIN; | ||
| 1867 | } | 1904 | } |
| 1868 | 1905 | ||
| 1869 | return 0; | 1906 | return 0; |
| @@ -1899,34 +1936,85 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno) | |||
| 1899 | return ret; | 1936 | return ret; |
| 1900 | } | 1937 | } |
| 1901 | 1938 | ||
| 1939 | /** | ||
| 1940 | * __wait_seqno - wait until execution of seqno has finished | ||
| 1941 | * @ring: the ring expected to report seqno | ||
| 1942 | * @seqno: duh! | ||
| 1943 | * @interruptible: do an interruptible wait (normally yes) | ||
| 1944 | * @timeout: in - how long to wait (NULL forever); out - how much time remaining | ||
| 1945 | * | ||
| 1946 | * Returns 0 if the seqno was found within the alloted time. Else returns the | ||
| 1947 | * errno with remaining time filled in timeout argument. | ||
| 1948 | */ | ||
| 1902 | static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, | 1949 | static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, |
| 1903 | bool interruptible) | 1950 | bool interruptible, struct timespec *timeout) |
| 1904 | { | 1951 | { |
| 1905 | drm_i915_private_t *dev_priv = ring->dev->dev_private; | 1952 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
| 1906 | int ret = 0; | 1953 | struct timespec before, now, wait_time={1,0}; |
| 1954 | unsigned long timeout_jiffies; | ||
| 1955 | long end; | ||
| 1956 | bool wait_forever = true; | ||
| 1957 | int ret; | ||
| 1907 | 1958 | ||
| 1908 | if (i915_seqno_passed(ring->get_seqno(ring), seqno)) | 1959 | if (i915_seqno_passed(ring->get_seqno(ring), seqno)) |
| 1909 | return 0; | 1960 | return 0; |
| 1910 | 1961 | ||
| 1911 | trace_i915_gem_request_wait_begin(ring, seqno); | 1962 | trace_i915_gem_request_wait_begin(ring, seqno); |
| 1963 | |||
| 1964 | if (timeout != NULL) { | ||
| 1965 | wait_time = *timeout; | ||
| 1966 | wait_forever = false; | ||
| 1967 | } | ||
| 1968 | |||
| 1969 | timeout_jiffies = timespec_to_jiffies(&wait_time); | ||
| 1970 | |||
| 1912 | if (WARN_ON(!ring->irq_get(ring))) | 1971 | if (WARN_ON(!ring->irq_get(ring))) |
| 1913 | return -ENODEV; | 1972 | return -ENODEV; |
| 1914 | 1973 | ||
| 1974 | /* Record current time in case interrupted by signal, or wedged * */ | ||
| 1975 | getrawmonotonic(&before); | ||
| 1976 | |||
| 1915 | #define EXIT_COND \ | 1977 | #define EXIT_COND \ |
| 1916 | (i915_seqno_passed(ring->get_seqno(ring), seqno) || \ | 1978 | (i915_seqno_passed(ring->get_seqno(ring), seqno) || \ |
| 1917 | atomic_read(&dev_priv->mm.wedged)) | 1979 | atomic_read(&dev_priv->mm.wedged)) |
| 1980 | do { | ||
| 1981 | if (interruptible) | ||
| 1982 | end = wait_event_interruptible_timeout(ring->irq_queue, | ||
| 1983 | EXIT_COND, | ||
| 1984 | timeout_jiffies); | ||
| 1985 | else | ||
| 1986 | end = wait_event_timeout(ring->irq_queue, EXIT_COND, | ||
| 1987 | timeout_jiffies); | ||
| 1918 | 1988 | ||
| 1919 | if (interruptible) | 1989 | ret = i915_gem_check_wedge(dev_priv, interruptible); |
| 1920 | ret = wait_event_interruptible(ring->irq_queue, | 1990 | if (ret) |
| 1921 | EXIT_COND); | 1991 | end = ret; |
| 1922 | else | 1992 | } while (end == 0 && wait_forever); |
| 1923 | wait_event(ring->irq_queue, EXIT_COND); | 1993 | |
| 1994 | getrawmonotonic(&now); | ||
| 1924 | 1995 | ||
| 1925 | ring->irq_put(ring); | 1996 | ring->irq_put(ring); |
| 1926 | trace_i915_gem_request_wait_end(ring, seqno); | 1997 | trace_i915_gem_request_wait_end(ring, seqno); |
| 1927 | #undef EXIT_COND | 1998 | #undef EXIT_COND |
| 1928 | 1999 | ||
| 1929 | return ret; | 2000 | if (timeout) { |
| 2001 | struct timespec sleep_time = timespec_sub(now, before); | ||
| 2002 | *timeout = timespec_sub(*timeout, sleep_time); | ||
| 2003 | } | ||
| 2004 | |||
| 2005 | switch (end) { | ||
| 2006 | case -EIO: | ||
| 2007 | case -EAGAIN: /* Wedged */ | ||
| 2008 | case -ERESTARTSYS: /* Signal */ | ||
| 2009 | return (int)end; | ||
| 2010 | case 0: /* Timeout */ | ||
| 2011 | if (timeout) | ||
| 2012 | set_normalized_timespec(timeout, 0, 0); | ||
| 2013 | return -ETIME; | ||
| 2014 | default: /* Completed */ | ||
| 2015 | WARN_ON(end < 0); /* We're not aware of other errors */ | ||
| 2016 | return 0; | ||
| 2017 | } | ||
| 1930 | } | 2018 | } |
| 1931 | 2019 | ||
| 1932 | /** | 2020 | /** |
| @@ -1934,15 +2022,14 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, | |||
| 1934 | * request and object lists appropriately for that event. | 2022 | * request and object lists appropriately for that event. |
| 1935 | */ | 2023 | */ |
| 1936 | int | 2024 | int |
| 1937 | i915_wait_request(struct intel_ring_buffer *ring, | 2025 | i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno) |
| 1938 | uint32_t seqno) | ||
| 1939 | { | 2026 | { |
| 1940 | drm_i915_private_t *dev_priv = ring->dev->dev_private; | 2027 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
| 1941 | int ret = 0; | 2028 | int ret = 0; |
| 1942 | 2029 | ||
| 1943 | BUG_ON(seqno == 0); | 2030 | BUG_ON(seqno == 0); |
| 1944 | 2031 | ||
| 1945 | ret = i915_gem_check_wedge(dev_priv); | 2032 | ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); |
| 1946 | if (ret) | 2033 | if (ret) |
| 1947 | return ret; | 2034 | return ret; |
| 1948 | 2035 | ||
| @@ -1950,9 +2037,7 @@ i915_wait_request(struct intel_ring_buffer *ring, | |||
| 1950 | if (ret) | 2037 | if (ret) |
| 1951 | return ret; | 2038 | return ret; |
| 1952 | 2039 | ||
| 1953 | ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible); | 2040 | ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible, NULL); |
| 1954 | if (atomic_read(&dev_priv->mm.wedged)) | ||
| 1955 | ret = -EAGAIN; | ||
| 1956 | 2041 | ||
| 1957 | return ret; | 2042 | return ret; |
| 1958 | } | 2043 | } |
| @@ -1975,7 +2060,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj) | |||
| 1975 | * it. | 2060 | * it. |
| 1976 | */ | 2061 | */ |
| 1977 | if (obj->active) { | 2062 | if (obj->active) { |
| 1978 | ret = i915_wait_request(obj->ring, obj->last_rendering_seqno); | 2063 | ret = i915_wait_seqno(obj->ring, obj->last_rendering_seqno); |
| 1979 | if (ret) | 2064 | if (ret) |
| 1980 | return ret; | 2065 | return ret; |
| 1981 | i915_gem_retire_requests_ring(obj->ring); | 2066 | i915_gem_retire_requests_ring(obj->ring); |
| @@ -1985,6 +2070,115 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj) | |||
| 1985 | } | 2070 | } |
| 1986 | 2071 | ||
| 1987 | /** | 2072 | /** |
| 2073 | * Ensures that an object will eventually get non-busy by flushing any required | ||
| 2074 | * write domains, emitting any outstanding lazy request and retiring and | ||
| 2075 | * completed requests. | ||
| 2076 | */ | ||
| 2077 | static int | ||
| 2078 | i915_gem_object_flush_active(struct drm_i915_gem_object *obj) | ||
| 2079 | { | ||
| 2080 | int ret; | ||
| 2081 | |||
| 2082 | if (obj->active) { | ||
| 2083 | ret = i915_gem_object_flush_gpu_write_domain(obj); | ||
| 2084 | if (ret) | ||
| 2085 | return ret; | ||
| 2086 | |||
| 2087 | ret = i915_gem_check_olr(obj->ring, | ||
| 2088 | obj->last_rendering_seqno); | ||
| 2089 | if (ret) | ||
| 2090 | return ret; | ||
| 2091 | i915_gem_retire_requests_ring(obj->ring); | ||
| 2092 | } | ||
| 2093 | |||
| 2094 | return 0; | ||
| 2095 | } | ||
| 2096 | |||
| 2097 | /** | ||
| 2098 | * i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT | ||
| 2099 | * @DRM_IOCTL_ARGS: standard ioctl arguments | ||
| 2100 | * | ||
| 2101 | * Returns 0 if successful, else an error is returned with the remaining time in | ||
| 2102 | * the timeout parameter. | ||
| 2103 | * -ETIME: object is still busy after timeout | ||
| 2104 | * -ERESTARTSYS: signal interrupted the wait | ||
| 2105 | * -ENONENT: object doesn't exist | ||
| 2106 | * Also possible, but rare: | ||
| 2107 | * -EAGAIN: GPU wedged | ||
| 2108 | * -ENOMEM: damn | ||
| 2109 | * -ENODEV: Internal IRQ fail | ||
| 2110 | * -E?: The add request failed | ||
| 2111 | * | ||
| 2112 | * The wait ioctl with a timeout of 0 reimplements the busy ioctl. With any | ||
| 2113 | * non-zero timeout parameter the wait ioctl will wait for the given number of | ||
| 2114 | * nanoseconds on an object becoming unbusy. Since the wait itself does so | ||
| 2115 | * without holding struct_mutex the object may become re-busied before this | ||
| 2116 | * function completes. A similar but shorter * race condition exists in the busy | ||
| 2117 | * ioctl | ||
| 2118 | */ | ||
| 2119 | int | ||
| 2120 | i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) | ||
| 2121 | { | ||
| 2122 | struct drm_i915_gem_wait *args = data; | ||
| 2123 | struct drm_i915_gem_object *obj; | ||
| 2124 | struct intel_ring_buffer *ring = NULL; | ||
| 2125 | struct timespec timeout_stack, *timeout = NULL; | ||
| 2126 | u32 seqno = 0; | ||
| 2127 | int ret = 0; | ||
| 2128 | |||
| 2129 | if (args->timeout_ns >= 0) { | ||
| 2130 | timeout_stack = ns_to_timespec(args->timeout_ns); | ||
| 2131 | timeout = &timeout_stack; | ||
| 2132 | } | ||
| 2133 | |||
| 2134 | ret = i915_mutex_lock_interruptible(dev); | ||
| 2135 | if (ret) | ||
| 2136 | return ret; | ||
| 2137 | |||
| 2138 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->bo_handle)); | ||
| 2139 | if (&obj->base == NULL) { | ||
| 2140 | mutex_unlock(&dev->struct_mutex); | ||
| 2141 | return -ENOENT; | ||
| 2142 | } | ||
| 2143 | |||
| 2144 | /* Need to make sure the object gets inactive eventually. */ | ||
| 2145 | ret = i915_gem_object_flush_active(obj); | ||
| 2146 | if (ret) | ||
| 2147 | goto out; | ||
| 2148 | |||
| 2149 | if (obj->active) { | ||
| 2150 | seqno = obj->last_rendering_seqno; | ||
| 2151 | ring = obj->ring; | ||
| 2152 | } | ||
| 2153 | |||
| 2154 | if (seqno == 0) | ||
| 2155 | goto out; | ||
| 2156 | |||
| 2157 | /* Do this after OLR check to make sure we make forward progress polling | ||
| 2158 | * on this IOCTL with a 0 timeout (like busy ioctl) | ||
| 2159 | */ | ||
| 2160 | if (!args->timeout_ns) { | ||
| 2161 | ret = -ETIME; | ||
| 2162 | goto out; | ||
| 2163 | } | ||
| 2164 | |||
| 2165 | drm_gem_object_unreference(&obj->base); | ||
| 2166 | mutex_unlock(&dev->struct_mutex); | ||
| 2167 | |||
| 2168 | ret = __wait_seqno(ring, seqno, true, timeout); | ||
| 2169 | if (timeout) { | ||
| 2170 | WARN_ON(!timespec_valid(timeout)); | ||
| 2171 | args->timeout_ns = timespec_to_ns(timeout); | ||
| 2172 | } | ||
| 2173 | return ret; | ||
| 2174 | |||
| 2175 | out: | ||
| 2176 | drm_gem_object_unreference(&obj->base); | ||
| 2177 | mutex_unlock(&dev->struct_mutex); | ||
| 2178 | return ret; | ||
| 2179 | } | ||
| 2180 | |||
| 2181 | /** | ||
| 1988 | * i915_gem_object_sync - sync an object to a ring. | 2182 | * i915_gem_object_sync - sync an object to a ring. |
| 1989 | * | 2183 | * |
| 1990 | * @obj: object which may be in use on another ring. | 2184 | * @obj: object which may be in use on another ring. |
| @@ -2160,7 +2354,7 @@ static int i915_ring_idle(struct intel_ring_buffer *ring) | |||
| 2160 | return ret; | 2354 | return ret; |
| 2161 | } | 2355 | } |
| 2162 | 2356 | ||
| 2163 | return i915_wait_request(ring, i915_gem_next_request_seqno(ring)); | 2357 | return i915_wait_seqno(ring, i915_gem_next_request_seqno(ring)); |
| 2164 | } | 2358 | } |
| 2165 | 2359 | ||
| 2166 | int i915_gpu_idle(struct drm_device *dev) | 2360 | int i915_gpu_idle(struct drm_device *dev) |
| @@ -2178,6 +2372,10 @@ int i915_gpu_idle(struct drm_device *dev) | |||
| 2178 | /* Is the device fubar? */ | 2372 | /* Is the device fubar? */ |
| 2179 | if (WARN_ON(!list_empty(&ring->gpu_write_list))) | 2373 | if (WARN_ON(!list_empty(&ring->gpu_write_list))) |
| 2180 | return -EBUSY; | 2374 | return -EBUSY; |
| 2375 | |||
| 2376 | ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); | ||
| 2377 | if (ret) | ||
| 2378 | return ret; | ||
| 2181 | } | 2379 | } |
| 2182 | 2380 | ||
| 2183 | return 0; | 2381 | return 0; |
| @@ -2364,7 +2562,7 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj) | |||
| 2364 | } | 2562 | } |
| 2365 | 2563 | ||
| 2366 | if (obj->last_fenced_seqno) { | 2564 | if (obj->last_fenced_seqno) { |
| 2367 | ret = i915_wait_request(obj->ring, obj->last_fenced_seqno); | 2565 | ret = i915_wait_seqno(obj->ring, obj->last_fenced_seqno); |
| 2368 | if (ret) | 2566 | if (ret) |
| 2369 | return ret; | 2567 | return ret; |
| 2370 | 2568 | ||
| @@ -2551,8 +2749,8 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, | |||
| 2551 | if (map_and_fenceable) | 2749 | if (map_and_fenceable) |
| 2552 | free_space = | 2750 | free_space = |
| 2553 | drm_mm_search_free_in_range(&dev_priv->mm.gtt_space, | 2751 | drm_mm_search_free_in_range(&dev_priv->mm.gtt_space, |
| 2554 | size, alignment, 0, | 2752 | size, alignment, |
| 2555 | dev_priv->mm.gtt_mappable_end, | 2753 | 0, dev_priv->mm.gtt_mappable_end, |
| 2556 | 0); | 2754 | 0); |
| 2557 | else | 2755 | else |
| 2558 | free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, | 2756 | free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, |
| @@ -2563,7 +2761,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, | |||
| 2563 | obj->gtt_space = | 2761 | obj->gtt_space = |
| 2564 | drm_mm_get_block_range_generic(free_space, | 2762 | drm_mm_get_block_range_generic(free_space, |
| 2565 | size, alignment, 0, | 2763 | size, alignment, 0, |
| 2566 | dev_priv->mm.gtt_mappable_end, | 2764 | 0, dev_priv->mm.gtt_mappable_end, |
| 2567 | 0); | 2765 | 0); |
| 2568 | else | 2766 | else |
| 2569 | obj->gtt_space = | 2767 | obj->gtt_space = |
| @@ -3030,7 +3228,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) | |||
| 3030 | if (seqno == 0) | 3228 | if (seqno == 0) |
| 3031 | return 0; | 3229 | return 0; |
| 3032 | 3230 | ||
| 3033 | ret = __wait_seqno(ring, seqno, true); | 3231 | ret = __wait_seqno(ring, seqno, true, NULL); |
| 3034 | if (ret == 0) | 3232 | if (ret == 0) |
| 3035 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); | 3233 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); |
| 3036 | 3234 | ||
| @@ -3199,30 +3397,9 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
| 3199 | * become non-busy without any further actions, therefore emit any | 3397 | * become non-busy without any further actions, therefore emit any |
| 3200 | * necessary flushes here. | 3398 | * necessary flushes here. |
| 3201 | */ | 3399 | */ |
| 3202 | args->busy = obj->active; | 3400 | ret = i915_gem_object_flush_active(obj); |
| 3203 | if (args->busy) { | ||
| 3204 | /* Unconditionally flush objects, even when the gpu still uses this | ||
| 3205 | * object. Userspace calling this function indicates that it wants to | ||
| 3206 | * use this buffer rather sooner than later, so issuing the required | ||
| 3207 | * flush earlier is beneficial. | ||
| 3208 | */ | ||
| 3209 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { | ||
| 3210 | ret = i915_gem_flush_ring(obj->ring, | ||
| 3211 | 0, obj->base.write_domain); | ||
| 3212 | } else { | ||
| 3213 | ret = i915_gem_check_olr(obj->ring, | ||
| 3214 | obj->last_rendering_seqno); | ||
| 3215 | } | ||
| 3216 | 3401 | ||
| 3217 | /* Update the active list for the hardware's current position. | 3402 | args->busy = obj->active; |
| 3218 | * Otherwise this only updates on a delayed timer or when irqs | ||
| 3219 | * are actually unmasked, and our working set ends up being | ||
| 3220 | * larger than required. | ||
| 3221 | */ | ||
| 3222 | i915_gem_retire_requests_ring(obj->ring); | ||
| 3223 | |||
| 3224 | args->busy = obj->active; | ||
| 3225 | } | ||
| 3226 | 3403 | ||
| 3227 | drm_gem_object_unreference(&obj->base); | 3404 | drm_gem_object_unreference(&obj->base); |
| 3228 | unlock: | 3405 | unlock: |
| @@ -3435,6 +3612,38 @@ i915_gem_idle(struct drm_device *dev) | |||
| 3435 | return 0; | 3612 | return 0; |
| 3436 | } | 3613 | } |
| 3437 | 3614 | ||
| 3615 | void i915_gem_l3_remap(struct drm_device *dev) | ||
| 3616 | { | ||
| 3617 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 3618 | u32 misccpctl; | ||
| 3619 | int i; | ||
| 3620 | |||
| 3621 | if (!IS_IVYBRIDGE(dev)) | ||
| 3622 | return; | ||
| 3623 | |||
| 3624 | if (!dev_priv->mm.l3_remap_info) | ||
| 3625 | return; | ||
| 3626 | |||
| 3627 | misccpctl = I915_READ(GEN7_MISCCPCTL); | ||
| 3628 | I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); | ||
| 3629 | POSTING_READ(GEN7_MISCCPCTL); | ||
| 3630 | |||
| 3631 | for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) { | ||
| 3632 | u32 remap = I915_READ(GEN7_L3LOG_BASE + i); | ||
| 3633 | if (remap && remap != dev_priv->mm.l3_remap_info[i/4]) | ||
| 3634 | DRM_DEBUG("0x%x was already programmed to %x\n", | ||
| 3635 | GEN7_L3LOG_BASE + i, remap); | ||
| 3636 | if (remap && !dev_priv->mm.l3_remap_info[i/4]) | ||
| 3637 | DRM_DEBUG_DRIVER("Clearing remapped register\n"); | ||
| 3638 | I915_WRITE(GEN7_L3LOG_BASE + i, dev_priv->mm.l3_remap_info[i/4]); | ||
| 3639 | } | ||
| 3640 | |||
| 3641 | /* Make sure all the writes land before disabling dop clock gating */ | ||
| 3642 | POSTING_READ(GEN7_L3LOG_BASE); | ||
| 3643 | |||
| 3644 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); | ||
| 3645 | } | ||
| 3646 | |||
| 3438 | void i915_gem_init_swizzling(struct drm_device *dev) | 3647 | void i915_gem_init_swizzling(struct drm_device *dev) |
| 3439 | { | 3648 | { |
| 3440 | drm_i915_private_t *dev_priv = dev->dev_private; | 3649 | drm_i915_private_t *dev_priv = dev->dev_private; |
| @@ -3518,12 +3727,33 @@ void i915_gem_init_ppgtt(struct drm_device *dev) | |||
| 3518 | } | 3727 | } |
| 3519 | } | 3728 | } |
| 3520 | 3729 | ||
| 3730 | static bool | ||
| 3731 | intel_enable_blt(struct drm_device *dev) | ||
| 3732 | { | ||
| 3733 | if (!HAS_BLT(dev)) | ||
| 3734 | return false; | ||
| 3735 | |||
| 3736 | /* The blitter was dysfunctional on early prototypes */ | ||
| 3737 | if (IS_GEN6(dev) && dev->pdev->revision < 8) { | ||
| 3738 | DRM_INFO("BLT not supported on this pre-production hardware;" | ||
| 3739 | " graphics performance will be degraded.\n"); | ||
| 3740 | return false; | ||
| 3741 | } | ||
| 3742 | |||
| 3743 | return true; | ||
| 3744 | } | ||
| 3745 | |||
| 3521 | int | 3746 | int |
| 3522 | i915_gem_init_hw(struct drm_device *dev) | 3747 | i915_gem_init_hw(struct drm_device *dev) |
| 3523 | { | 3748 | { |
| 3524 | drm_i915_private_t *dev_priv = dev->dev_private; | 3749 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 3525 | int ret; | 3750 | int ret; |
| 3526 | 3751 | ||
| 3752 | if (!intel_enable_gtt()) | ||
| 3753 | return -EIO; | ||
| 3754 | |||
| 3755 | i915_gem_l3_remap(dev); | ||
| 3756 | |||
| 3527 | i915_gem_init_swizzling(dev); | 3757 | i915_gem_init_swizzling(dev); |
| 3528 | 3758 | ||
| 3529 | ret = intel_init_render_ring_buffer(dev); | 3759 | ret = intel_init_render_ring_buffer(dev); |
| @@ -3536,7 +3766,7 @@ i915_gem_init_hw(struct drm_device *dev) | |||
| 3536 | goto cleanup_render_ring; | 3766 | goto cleanup_render_ring; |
| 3537 | } | 3767 | } |
| 3538 | 3768 | ||
| 3539 | if (HAS_BLT(dev)) { | 3769 | if (intel_enable_blt(dev)) { |
| 3540 | ret = intel_init_blt_ring_buffer(dev); | 3770 | ret = intel_init_blt_ring_buffer(dev); |
| 3541 | if (ret) | 3771 | if (ret) |
| 3542 | goto cleanup_bsd_ring; | 3772 | goto cleanup_bsd_ring; |
| @@ -3544,6 +3774,11 @@ i915_gem_init_hw(struct drm_device *dev) | |||
| 3544 | 3774 | ||
| 3545 | dev_priv->next_seqno = 1; | 3775 | dev_priv->next_seqno = 1; |
| 3546 | 3776 | ||
| 3777 | /* | ||
| 3778 | * XXX: There was some w/a described somewhere suggesting loading | ||
| 3779 | * contexts before PPGTT. | ||
| 3780 | */ | ||
| 3781 | i915_gem_context_init(dev); | ||
| 3547 | i915_gem_init_ppgtt(dev); | 3782 | i915_gem_init_ppgtt(dev); |
| 3548 | 3783 | ||
| 3549 | return 0; | 3784 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c new file mode 100644 index 000000000000..da8b01fb1bf8 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
| @@ -0,0 +1,536 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2011-2012 Intel Corporation | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| 21 | * IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Ben Widawsky <ben@bwidawsk.net> | ||
| 25 | * | ||
| 26 | */ | ||
| 27 | |||
| 28 | /* | ||
| 29 | * This file implements HW context support. On gen5+ a HW context consists of an | ||
| 30 | * opaque GPU object which is referenced at times of context saves and restores. | ||
| 31 | * With RC6 enabled, the context is also referenced as the GPU enters and exists | ||
| 32 | * from RC6 (GPU has it's own internal power context, except on gen5). Though | ||
| 33 | * something like a context does exist for the media ring, the code only | ||
| 34 | * supports contexts for the render ring. | ||
| 35 | * | ||
| 36 | * In software, there is a distinction between contexts created by the user, | ||
| 37 | * and the default HW context. The default HW context is used by GPU clients | ||
| 38 | * that do not request setup of their own hardware context. The default | ||
| 39 | * context's state is never restored to help prevent programming errors. This | ||
| 40 | * would happen if a client ran and piggy-backed off another clients GPU state. | ||
| 41 | * The default context only exists to give the GPU some offset to load as the | ||
| 42 | * current to invoke a save of the context we actually care about. In fact, the | ||
| 43 | * code could likely be constructed, albeit in a more complicated fashion, to | ||
| 44 | * never use the default context, though that limits the driver's ability to | ||
| 45 | * swap out, and/or destroy other contexts. | ||
| 46 | * | ||
| 47 | * All other contexts are created as a request by the GPU client. These contexts | ||
| 48 | * store GPU state, and thus allow GPU clients to not re-emit state (and | ||
| 49 | * potentially query certain state) at any time. The kernel driver makes | ||
| 50 | * certain that the appropriate commands are inserted. | ||
| 51 | * | ||
| 52 | * The context life cycle is semi-complicated in that context BOs may live | ||
| 53 | * longer than the context itself because of the way the hardware, and object | ||
| 54 | * tracking works. Below is a very crude representation of the state machine | ||
| 55 | * describing the context life. | ||
| 56 | * refcount pincount active | ||
| 57 | * S0: initial state 0 0 0 | ||
| 58 | * S1: context created 1 0 0 | ||
| 59 | * S2: context is currently running 2 1 X | ||
| 60 | * S3: GPU referenced, but not current 2 0 1 | ||
| 61 | * S4: context is current, but destroyed 1 1 0 | ||
| 62 | * S5: like S3, but destroyed 1 0 1 | ||
| 63 | * | ||
| 64 | * The most common (but not all) transitions: | ||
| 65 | * S0->S1: client creates a context | ||
| 66 | * S1->S2: client submits execbuf with context | ||
| 67 | * S2->S3: other clients submits execbuf with context | ||
| 68 | * S3->S1: context object was retired | ||
| 69 | * S3->S2: clients submits another execbuf | ||
| 70 | * S2->S4: context destroy called with current context | ||
| 71 | * S3->S5->S0: destroy path | ||
| 72 | * S4->S5->S0: destroy path on current context | ||
| 73 | * | ||
| 74 | * There are two confusing terms used above: | ||
| 75 | * The "current context" means the context which is currently running on the | ||
| 76 | * GPU. The GPU has loaded it's state already and has stored away the gtt | ||
| 77 | * offset of the BO. The GPU is not actively referencing the data at this | ||
| 78 | * offset, but it will on the next context switch. The only way to avoid this | ||
| 79 | * is to do a GPU reset. | ||
| 80 | * | ||
| 81 | * An "active context' is one which was previously the "current context" and is | ||
| 82 | * on the active list waiting for the next context switch to occur. Until this | ||
| 83 | * happens, the object must remain at the same gtt offset. It is therefore | ||
| 84 | * possible to destroy a context, but it is still active. | ||
| 85 | * | ||
| 86 | */ | ||
| 87 | |||
| 88 | #include "drmP.h" | ||
| 89 | #include "i915_drm.h" | ||
| 90 | #include "i915_drv.h" | ||
| 91 | |||
| 92 | /* This is a HW constraint. The value below is the largest known requirement | ||
| 93 | * I've seen in a spec to date, and that was a workaround for a non-shipping | ||
| 94 | * part. It should be safe to decrease this, but it's more future proof as is. | ||
| 95 | */ | ||
| 96 | #define CONTEXT_ALIGN (64<<10) | ||
| 97 | |||
| 98 | static struct i915_hw_context * | ||
| 99 | i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); | ||
| 100 | static int do_switch(struct drm_i915_gem_object *from_obj, | ||
| 101 | struct i915_hw_context *to, u32 seqno); | ||
| 102 | |||
| 103 | static int get_context_size(struct drm_device *dev) | ||
| 104 | { | ||
| 105 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 106 | int ret; | ||
| 107 | u32 reg; | ||
| 108 | |||
| 109 | switch (INTEL_INFO(dev)->gen) { | ||
| 110 | case 6: | ||
| 111 | reg = I915_READ(CXT_SIZE); | ||
| 112 | ret = GEN6_CXT_TOTAL_SIZE(reg) * 64; | ||
| 113 | break; | ||
| 114 | case 7: | ||
| 115 | reg = I915_READ(GEN7_CXT_SIZE); | ||
| 116 | ret = GEN7_CXT_TOTAL_SIZE(reg) * 64; | ||
| 117 | break; | ||
| 118 | default: | ||
| 119 | BUG(); | ||
| 120 | } | ||
| 121 | |||
| 122 | return ret; | ||
| 123 | } | ||
| 124 | |||
| 125 | static void do_destroy(struct i915_hw_context *ctx) | ||
| 126 | { | ||
| 127 | struct drm_device *dev = ctx->obj->base.dev; | ||
| 128 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 129 | |||
| 130 | if (ctx->file_priv) | ||
| 131 | idr_remove(&ctx->file_priv->context_idr, ctx->id); | ||
| 132 | else | ||
| 133 | BUG_ON(ctx != dev_priv->ring[RCS].default_context); | ||
| 134 | |||
| 135 | drm_gem_object_unreference(&ctx->obj->base); | ||
| 136 | kfree(ctx); | ||
| 137 | } | ||
| 138 | |||
| 139 | static struct i915_hw_context * | ||
| 140 | create_hw_context(struct drm_device *dev, | ||
| 141 | struct drm_i915_file_private *file_priv) | ||
| 142 | { | ||
| 143 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 144 | struct i915_hw_context *ctx; | ||
| 145 | int ret, id; | ||
| 146 | |||
| 147 | ctx = kzalloc(sizeof(struct drm_i915_file_private), GFP_KERNEL); | ||
| 148 | if (ctx == NULL) | ||
| 149 | return ERR_PTR(-ENOMEM); | ||
| 150 | |||
| 151 | ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); | ||
| 152 | if (ctx->obj == NULL) { | ||
| 153 | kfree(ctx); | ||
| 154 | DRM_DEBUG_DRIVER("Context object allocated failed\n"); | ||
| 155 | return ERR_PTR(-ENOMEM); | ||
| 156 | } | ||
| 157 | |||
| 158 | /* The ring associated with the context object is handled by the normal | ||
| 159 | * object tracking code. We give an initial ring value simple to pass an | ||
| 160 | * assertion in the context switch code. | ||
| 161 | */ | ||
| 162 | ctx->ring = &dev_priv->ring[RCS]; | ||
| 163 | |||
| 164 | /* Default context will never have a file_priv */ | ||
| 165 | if (file_priv == NULL) | ||
| 166 | return ctx; | ||
| 167 | |||
| 168 | ctx->file_priv = file_priv; | ||
| 169 | |||
| 170 | again: | ||
| 171 | if (idr_pre_get(&file_priv->context_idr, GFP_KERNEL) == 0) { | ||
| 172 | ret = -ENOMEM; | ||
| 173 | DRM_DEBUG_DRIVER("idr allocation failed\n"); | ||
| 174 | goto err_out; | ||
| 175 | } | ||
| 176 | |||
| 177 | ret = idr_get_new_above(&file_priv->context_idr, ctx, | ||
| 178 | DEFAULT_CONTEXT_ID + 1, &id); | ||
| 179 | if (ret == 0) | ||
| 180 | ctx->id = id; | ||
| 181 | |||
| 182 | if (ret == -EAGAIN) | ||
| 183 | goto again; | ||
| 184 | else if (ret) | ||
| 185 | goto err_out; | ||
| 186 | |||
| 187 | return ctx; | ||
| 188 | |||
| 189 | err_out: | ||
| 190 | do_destroy(ctx); | ||
| 191 | return ERR_PTR(ret); | ||
| 192 | } | ||
| 193 | |||
| 194 | static inline bool is_default_context(struct i915_hw_context *ctx) | ||
| 195 | { | ||
| 196 | return (ctx == ctx->ring->default_context); | ||
| 197 | } | ||
| 198 | |||
| 199 | /** | ||
| 200 | * The default context needs to exist per ring that uses contexts. It stores the | ||
| 201 | * context state of the GPU for applications that don't utilize HW contexts, as | ||
| 202 | * well as an idle case. | ||
| 203 | */ | ||
| 204 | static int create_default_context(struct drm_i915_private *dev_priv) | ||
| 205 | { | ||
| 206 | struct i915_hw_context *ctx; | ||
| 207 | int ret; | ||
| 208 | |||
| 209 | BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); | ||
| 210 | |||
| 211 | ctx = create_hw_context(dev_priv->dev, NULL); | ||
| 212 | if (IS_ERR(ctx)) | ||
| 213 | return PTR_ERR(ctx); | ||
| 214 | |||
| 215 | /* We may need to do things with the shrinker which require us to | ||
| 216 | * immediately switch back to the default context. This can cause a | ||
| 217 | * problem as pinning the default context also requires GTT space which | ||
| 218 | * may not be available. To avoid this we always pin the | ||
| 219 | * default context. | ||
| 220 | */ | ||
| 221 | dev_priv->ring[RCS].default_context = ctx; | ||
| 222 | ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false); | ||
| 223 | if (ret) { | ||
| 224 | do_destroy(ctx); | ||
| 225 | return ret; | ||
| 226 | } | ||
| 227 | |||
| 228 | ret = do_switch(NULL, ctx, 0); | ||
| 229 | if (ret) { | ||
| 230 | i915_gem_object_unpin(ctx->obj); | ||
| 231 | do_destroy(ctx); | ||
| 232 | } else { | ||
| 233 | DRM_DEBUG_DRIVER("Default HW context loaded\n"); | ||
| 234 | } | ||
| 235 | |||
| 236 | return ret; | ||
| 237 | } | ||
| 238 | |||
| 239 | void i915_gem_context_init(struct drm_device *dev) | ||
| 240 | { | ||
| 241 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 242 | uint32_t ctx_size; | ||
| 243 | |||
| 244 | if (!HAS_HW_CONTEXTS(dev)) { | ||
| 245 | dev_priv->hw_contexts_disabled = true; | ||
| 246 | return; | ||
| 247 | } | ||
| 248 | |||
| 249 | /* If called from reset, or thaw... we've been here already */ | ||
| 250 | if (dev_priv->hw_contexts_disabled || | ||
| 251 | dev_priv->ring[RCS].default_context) | ||
| 252 | return; | ||
| 253 | |||
| 254 | ctx_size = get_context_size(dev); | ||
| 255 | dev_priv->hw_context_size = get_context_size(dev); | ||
| 256 | dev_priv->hw_context_size = round_up(dev_priv->hw_context_size, 4096); | ||
| 257 | |||
| 258 | if (ctx_size <= 0 || ctx_size > (1<<20)) { | ||
| 259 | dev_priv->hw_contexts_disabled = true; | ||
| 260 | return; | ||
| 261 | } | ||
| 262 | |||
| 263 | if (create_default_context(dev_priv)) { | ||
| 264 | dev_priv->hw_contexts_disabled = true; | ||
| 265 | return; | ||
| 266 | } | ||
| 267 | |||
| 268 | DRM_DEBUG_DRIVER("HW context support initialized\n"); | ||
| 269 | } | ||
| 270 | |||
| 271 | void i915_gem_context_fini(struct drm_device *dev) | ||
| 272 | { | ||
| 273 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 274 | |||
| 275 | if (dev_priv->hw_contexts_disabled) | ||
| 276 | return; | ||
| 277 | |||
| 278 | /* The only known way to stop the gpu from accessing the hw context is | ||
| 279 | * to reset it. Do this as the very last operation to avoid confusing | ||
| 280 | * other code, leading to spurious errors. */ | ||
| 281 | intel_gpu_reset(dev); | ||
| 282 | |||
| 283 | i915_gem_object_unpin(dev_priv->ring[RCS].default_context->obj); | ||
| 284 | |||
| 285 | do_destroy(dev_priv->ring[RCS].default_context); | ||
| 286 | } | ||
| 287 | |||
| 288 | static int context_idr_cleanup(int id, void *p, void *data) | ||
| 289 | { | ||
| 290 | struct i915_hw_context *ctx = p; | ||
| 291 | |||
| 292 | BUG_ON(id == DEFAULT_CONTEXT_ID); | ||
| 293 | |||
| 294 | do_destroy(ctx); | ||
| 295 | |||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | |||
| 299 | void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) | ||
| 300 | { | ||
| 301 | struct drm_i915_file_private *file_priv = file->driver_priv; | ||
| 302 | |||
| 303 | mutex_lock(&dev->struct_mutex); | ||
| 304 | idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); | ||
| 305 | idr_destroy(&file_priv->context_idr); | ||
| 306 | mutex_unlock(&dev->struct_mutex); | ||
| 307 | } | ||
| 308 | |||
| 309 | static struct i915_hw_context * | ||
| 310 | i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) | ||
| 311 | { | ||
| 312 | return (struct i915_hw_context *)idr_find(&file_priv->context_idr, id); | ||
| 313 | } | ||
| 314 | |||
| 315 | static inline int | ||
| 316 | mi_set_context(struct intel_ring_buffer *ring, | ||
| 317 | struct i915_hw_context *new_context, | ||
| 318 | u32 hw_flags) | ||
| 319 | { | ||
| 320 | int ret; | ||
| 321 | |||
| 322 | /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB | ||
| 323 | * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value | ||
| 324 | * explicitly, so we rely on the value at ring init, stored in | ||
| 325 | * itlb_before_ctx_switch. | ||
| 326 | */ | ||
| 327 | if (IS_GEN6(ring->dev) && ring->itlb_before_ctx_switch) { | ||
| 328 | ret = ring->flush(ring, 0, 0); | ||
| 329 | if (ret) | ||
| 330 | return ret; | ||
| 331 | } | ||
| 332 | |||
| 333 | ret = intel_ring_begin(ring, 6); | ||
| 334 | if (ret) | ||
| 335 | return ret; | ||
| 336 | |||
| 337 | if (IS_GEN7(ring->dev)) | ||
| 338 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); | ||
| 339 | else | ||
| 340 | intel_ring_emit(ring, MI_NOOP); | ||
| 341 | |||
| 342 | intel_ring_emit(ring, MI_NOOP); | ||
| 343 | intel_ring_emit(ring, MI_SET_CONTEXT); | ||
| 344 | intel_ring_emit(ring, new_context->obj->gtt_offset | | ||
| 345 | MI_MM_SPACE_GTT | | ||
| 346 | MI_SAVE_EXT_STATE_EN | | ||
| 347 | MI_RESTORE_EXT_STATE_EN | | ||
| 348 | hw_flags); | ||
| 349 | /* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */ | ||
| 350 | intel_ring_emit(ring, MI_NOOP); | ||
| 351 | |||
| 352 | if (IS_GEN7(ring->dev)) | ||
| 353 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); | ||
| 354 | else | ||
| 355 | intel_ring_emit(ring, MI_NOOP); | ||
| 356 | |||
| 357 | intel_ring_advance(ring); | ||
| 358 | |||
| 359 | return ret; | ||
| 360 | } | ||
| 361 | |||
| 362 | static int do_switch(struct drm_i915_gem_object *from_obj, | ||
| 363 | struct i915_hw_context *to, | ||
| 364 | u32 seqno) | ||
| 365 | { | ||
| 366 | struct intel_ring_buffer *ring = NULL; | ||
| 367 | u32 hw_flags = 0; | ||
| 368 | int ret; | ||
| 369 | |||
| 370 | BUG_ON(to == NULL); | ||
| 371 | BUG_ON(from_obj != NULL && from_obj->pin_count == 0); | ||
| 372 | |||
| 373 | ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false); | ||
| 374 | if (ret) | ||
| 375 | return ret; | ||
| 376 | |||
| 377 | /* Clear this page out of any CPU caches for coherent swap-in/out. Note | ||
| 378 | * that thanks to write = false in this call and us not setting any gpu | ||
| 379 | * write domains when putting a context object onto the active list | ||
| 380 | * (when switching away from it), this won't block. | ||
| 381 | * XXX: We need a real interface to do this instead of trickery. */ | ||
| 382 | ret = i915_gem_object_set_to_gtt_domain(to->obj, false); | ||
| 383 | if (ret) { | ||
| 384 | i915_gem_object_unpin(to->obj); | ||
| 385 | return ret; | ||
| 386 | } | ||
| 387 | |||
| 388 | if (!to->obj->has_global_gtt_mapping) | ||
| 389 | i915_gem_gtt_bind_object(to->obj, to->obj->cache_level); | ||
| 390 | |||
| 391 | if (!to->is_initialized || is_default_context(to)) | ||
| 392 | hw_flags |= MI_RESTORE_INHIBIT; | ||
| 393 | else if (WARN_ON_ONCE(from_obj == to->obj)) /* not yet expected */ | ||
| 394 | hw_flags |= MI_FORCE_RESTORE; | ||
| 395 | |||
| 396 | ring = to->ring; | ||
| 397 | ret = mi_set_context(ring, to, hw_flags); | ||
| 398 | if (ret) { | ||
| 399 | i915_gem_object_unpin(to->obj); | ||
| 400 | return ret; | ||
| 401 | } | ||
| 402 | |||
| 403 | /* The backing object for the context is done after switching to the | ||
| 404 | * *next* context. Therefore we cannot retire the previous context until | ||
| 405 | * the next context has already started running. In fact, the below code | ||
| 406 | * is a bit suboptimal because the retiring can occur simply after the | ||
| 407 | * MI_SET_CONTEXT instead of when the next seqno has completed. | ||
| 408 | */ | ||
| 409 | if (from_obj != NULL) { | ||
| 410 | from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION; | ||
| 411 | i915_gem_object_move_to_active(from_obj, ring, seqno); | ||
| 412 | /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the | ||
| 413 | * whole damn pipeline, we don't need to explicitly mark the | ||
| 414 | * object dirty. The only exception is that the context must be | ||
| 415 | * correct in case the object gets swapped out. Ideally we'd be | ||
| 416 | * able to defer doing this until we know the object would be | ||
| 417 | * swapped, but there is no way to do that yet. | ||
| 418 | */ | ||
| 419 | from_obj->dirty = 1; | ||
| 420 | BUG_ON(from_obj->ring != to->ring); | ||
| 421 | i915_gem_object_unpin(from_obj); | ||
| 422 | |||
| 423 | drm_gem_object_unreference(&from_obj->base); | ||
| 424 | } | ||
| 425 | |||
| 426 | drm_gem_object_reference(&to->obj->base); | ||
| 427 | ring->last_context_obj = to->obj; | ||
| 428 | to->is_initialized = true; | ||
| 429 | |||
| 430 | return 0; | ||
| 431 | } | ||
| 432 | |||
| 433 | /** | ||
| 434 | * i915_switch_context() - perform a GPU context switch. | ||
| 435 | * @ring: ring for which we'll execute the context switch | ||
| 436 | * @file_priv: file_priv associated with the context, may be NULL | ||
| 437 | * @id: context id number | ||
| 438 | * @seqno: sequence number by which the new context will be switched to | ||
| 439 | * @flags: | ||
| 440 | * | ||
| 441 | * The context life cycle is simple. The context refcount is incremented and | ||
| 442 | * decremented by 1 and create and destroy. If the context is in use by the GPU, | ||
| 443 | * it will have a refoucnt > 1. This allows us to destroy the context abstract | ||
| 444 | * object while letting the normal object tracking destroy the backing BO. | ||
| 445 | */ | ||
| 446 | int i915_switch_context(struct intel_ring_buffer *ring, | ||
| 447 | struct drm_file *file, | ||
| 448 | int to_id) | ||
| 449 | { | ||
| 450 | struct drm_i915_private *dev_priv = ring->dev->dev_private; | ||
| 451 | struct drm_i915_file_private *file_priv = NULL; | ||
| 452 | struct i915_hw_context *to; | ||
| 453 | struct drm_i915_gem_object *from_obj = ring->last_context_obj; | ||
| 454 | int ret; | ||
| 455 | |||
| 456 | if (dev_priv->hw_contexts_disabled) | ||
| 457 | return 0; | ||
| 458 | |||
| 459 | if (ring != &dev_priv->ring[RCS]) | ||
| 460 | return 0; | ||
| 461 | |||
| 462 | if (file) | ||
| 463 | file_priv = file->driver_priv; | ||
| 464 | |||
| 465 | if (to_id == DEFAULT_CONTEXT_ID) { | ||
| 466 | to = ring->default_context; | ||
| 467 | } else { | ||
| 468 | to = i915_gem_context_get(file_priv, to_id); | ||
| 469 | if (to == NULL) | ||
| 470 | return -ENOENT; | ||
| 471 | } | ||
| 472 | |||
| 473 | if (from_obj == to->obj) | ||
| 474 | return 0; | ||
| 475 | |||
| 476 | return do_switch(from_obj, to, i915_gem_next_request_seqno(to->ring)); | ||
| 477 | } | ||
| 478 | |||
| 479 | int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, | ||
| 480 | struct drm_file *file) | ||
| 481 | { | ||
| 482 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 483 | struct drm_i915_gem_context_create *args = data; | ||
| 484 | struct drm_i915_file_private *file_priv = file->driver_priv; | ||
| 485 | struct i915_hw_context *ctx; | ||
| 486 | int ret; | ||
| 487 | |||
| 488 | if (!(dev->driver->driver_features & DRIVER_GEM)) | ||
| 489 | return -ENODEV; | ||
| 490 | |||
| 491 | if (dev_priv->hw_contexts_disabled) | ||
| 492 | return -ENODEV; | ||
| 493 | |||
| 494 | ret = i915_mutex_lock_interruptible(dev); | ||
| 495 | if (ret) | ||
| 496 | return ret; | ||
| 497 | |||
| 498 | ctx = create_hw_context(dev, file_priv); | ||
| 499 | mutex_unlock(&dev->struct_mutex); | ||
| 500 | if (IS_ERR(ctx)) | ||
| 501 | return PTR_ERR(ctx); | ||
| 502 | |||
| 503 | args->ctx_id = ctx->id; | ||
| 504 | DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id); | ||
| 505 | |||
| 506 | return 0; | ||
| 507 | } | ||
| 508 | |||
| 509 | int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, | ||
| 510 | struct drm_file *file) | ||
| 511 | { | ||
| 512 | struct drm_i915_gem_context_destroy *args = data; | ||
| 513 | struct drm_i915_file_private *file_priv = file->driver_priv; | ||
| 514 | struct i915_hw_context *ctx; | ||
| 515 | int ret; | ||
| 516 | |||
| 517 | if (!(dev->driver->driver_features & DRIVER_GEM)) | ||
| 518 | return -ENODEV; | ||
| 519 | |||
| 520 | ret = i915_mutex_lock_interruptible(dev); | ||
| 521 | if (ret) | ||
| 522 | return ret; | ||
| 523 | |||
| 524 | ctx = i915_gem_context_get(file_priv, args->ctx_id); | ||
| 525 | if (!ctx) { | ||
| 526 | mutex_unlock(&dev->struct_mutex); | ||
| 527 | return -ENOENT; | ||
| 528 | } | ||
| 529 | |||
| 530 | do_destroy(ctx); | ||
| 531 | |||
| 532 | mutex_unlock(&dev->struct_mutex); | ||
| 533 | |||
| 534 | DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id); | ||
| 535 | return 0; | ||
| 536 | } | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index a4f6aaabca99..bddf7bed183f 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c | |||
| @@ -132,7 +132,8 @@ i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle) | |||
| 132 | __func__, obj, obj->gtt_offset, handle, | 132 | __func__, obj, obj->gtt_offset, handle, |
| 133 | obj->size / 1024); | 133 | obj->size / 1024); |
| 134 | 134 | ||
| 135 | gtt_mapping = ioremap(dev->agp->base + obj->gtt_offset, obj->base.size); | 135 | gtt_mapping = ioremap(dev_priv->mm.gtt_base_addr + obj->gtt_offset, |
| 136 | obj->base.size); | ||
| 136 | if (gtt_mapping == NULL) { | 137 | if (gtt_mapping == NULL) { |
| 137 | DRM_ERROR("failed to map GTT space\n"); | 138 | DRM_ERROR("failed to map GTT space\n"); |
| 138 | return; | 139 | return; |
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index ae7c24e12e52..eba0308f10e3 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
| @@ -78,11 +78,12 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, | |||
| 78 | 78 | ||
| 79 | INIT_LIST_HEAD(&unwind_list); | 79 | INIT_LIST_HEAD(&unwind_list); |
| 80 | if (mappable) | 80 | if (mappable) |
| 81 | drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space, min_size, | 81 | drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space, |
| 82 | alignment, 0, | 82 | min_size, alignment, 0, |
| 83 | dev_priv->mm.gtt_mappable_end); | 83 | 0, dev_priv->mm.gtt_mappable_end); |
| 84 | else | 84 | else |
| 85 | drm_mm_init_scan(&dev_priv->mm.gtt_space, min_size, alignment); | 85 | drm_mm_init_scan(&dev_priv->mm.gtt_space, |
| 86 | min_size, alignment, 0); | ||
| 86 | 87 | ||
| 87 | /* First see if there is a large enough contiguous idle region... */ | 88 | /* First see if there is a large enough contiguous idle region... */ |
| 88 | list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) { | 89 | list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) { |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 974a9f1068a3..5af631e788c8 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
| @@ -810,33 +810,16 @@ err: | |||
| 810 | return ret; | 810 | return ret; |
| 811 | } | 811 | } |
| 812 | 812 | ||
| 813 | static int | 813 | static void |
| 814 | i915_gem_execbuffer_flush(struct drm_device *dev, | 814 | i915_gem_execbuffer_flush(struct drm_device *dev, |
| 815 | uint32_t invalidate_domains, | 815 | uint32_t invalidate_domains, |
| 816 | uint32_t flush_domains, | 816 | uint32_t flush_domains) |
| 817 | uint32_t flush_rings) | ||
| 818 | { | 817 | { |
| 819 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 820 | int i, ret; | ||
| 821 | |||
| 822 | if (flush_domains & I915_GEM_DOMAIN_CPU) | 818 | if (flush_domains & I915_GEM_DOMAIN_CPU) |
| 823 | intel_gtt_chipset_flush(); | 819 | intel_gtt_chipset_flush(); |
| 824 | 820 | ||
| 825 | if (flush_domains & I915_GEM_DOMAIN_GTT) | 821 | if (flush_domains & I915_GEM_DOMAIN_GTT) |
| 826 | wmb(); | 822 | wmb(); |
| 827 | |||
| 828 | if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { | ||
| 829 | for (i = 0; i < I915_NUM_RINGS; i++) | ||
| 830 | if (flush_rings & (1 << i)) { | ||
| 831 | ret = i915_gem_flush_ring(&dev_priv->ring[i], | ||
| 832 | invalidate_domains, | ||
| 833 | flush_domains); | ||
| 834 | if (ret) | ||
| 835 | return ret; | ||
| 836 | } | ||
| 837 | } | ||
| 838 | |||
| 839 | return 0; | ||
| 840 | } | 823 | } |
| 841 | 824 | ||
| 842 | static int | 825 | static int |
| @@ -885,12 +868,9 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, | |||
| 885 | i915_gem_object_set_to_gpu_domain(obj, ring, &cd); | 868 | i915_gem_object_set_to_gpu_domain(obj, ring, &cd); |
| 886 | 869 | ||
| 887 | if (cd.invalidate_domains | cd.flush_domains) { | 870 | if (cd.invalidate_domains | cd.flush_domains) { |
| 888 | ret = i915_gem_execbuffer_flush(ring->dev, | 871 | i915_gem_execbuffer_flush(ring->dev, |
| 889 | cd.invalidate_domains, | 872 | cd.invalidate_domains, |
| 890 | cd.flush_domains, | 873 | cd.flush_domains); |
| 891 | cd.flush_rings); | ||
| 892 | if (ret) | ||
| 893 | return ret; | ||
| 894 | } | 874 | } |
| 895 | 875 | ||
| 896 | if (cd.flips) { | 876 | if (cd.flips) { |
| @@ -905,6 +885,16 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, | |||
| 905 | return ret; | 885 | return ret; |
| 906 | } | 886 | } |
| 907 | 887 | ||
| 888 | /* Unconditionally invalidate gpu caches and ensure that we do flush | ||
| 889 | * any residual writes from the previous batch. | ||
| 890 | */ | ||
| 891 | ret = i915_gem_flush_ring(ring, | ||
| 892 | I915_GEM_GPU_DOMAINS, | ||
| 893 | ring->gpu_caches_dirty ? I915_GEM_GPU_DOMAINS : 0); | ||
| 894 | if (ret) | ||
| 895 | return ret; | ||
| 896 | |||
| 897 | ring->gpu_caches_dirty = false; | ||
| 908 | return 0; | 898 | return 0; |
| 909 | } | 899 | } |
| 910 | 900 | ||
| @@ -983,26 +973,13 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev, | |||
| 983 | struct intel_ring_buffer *ring) | 973 | struct intel_ring_buffer *ring) |
| 984 | { | 974 | { |
| 985 | struct drm_i915_gem_request *request; | 975 | struct drm_i915_gem_request *request; |
| 986 | u32 invalidate; | ||
| 987 | 976 | ||
| 988 | /* | 977 | /* Unconditionally force add_request to emit a full flush. */ |
| 989 | * Ensure that the commands in the batch buffer are | 978 | ring->gpu_caches_dirty = true; |
| 990 | * finished before the interrupt fires. | ||
| 991 | * | ||
| 992 | * The sampler always gets flushed on i965 (sigh). | ||
| 993 | */ | ||
| 994 | invalidate = I915_GEM_DOMAIN_COMMAND; | ||
| 995 | if (INTEL_INFO(dev)->gen >= 4) | ||
| 996 | invalidate |= I915_GEM_DOMAIN_SAMPLER; | ||
| 997 | if (ring->flush(ring, invalidate, 0)) { | ||
| 998 | i915_gem_next_request_seqno(ring); | ||
| 999 | return; | ||
| 1000 | } | ||
| 1001 | 979 | ||
| 1002 | /* Add a breadcrumb for the completion of the batch buffer */ | 980 | /* Add a breadcrumb for the completion of the batch buffer */ |
| 1003 | request = kzalloc(sizeof(*request), GFP_KERNEL); | 981 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
| 1004 | if (request == NULL || i915_add_request(ring, file, request)) { | 982 | if (request == NULL || i915_add_request(ring, file, request)) { |
| 1005 | i915_gem_next_request_seqno(ring); | ||
| 1006 | kfree(request); | 983 | kfree(request); |
| 1007 | } | 984 | } |
| 1008 | } | 985 | } |
| @@ -1044,6 +1021,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 1044 | struct drm_i915_gem_object *batch_obj; | 1021 | struct drm_i915_gem_object *batch_obj; |
| 1045 | struct drm_clip_rect *cliprects = NULL; | 1022 | struct drm_clip_rect *cliprects = NULL; |
| 1046 | struct intel_ring_buffer *ring; | 1023 | struct intel_ring_buffer *ring; |
| 1024 | u32 ctx_id = i915_execbuffer2_get_context_id(*args); | ||
| 1047 | u32 exec_start, exec_len; | 1025 | u32 exec_start, exec_len; |
| 1048 | u32 seqno; | 1026 | u32 seqno; |
| 1049 | u32 mask; | 1027 | u32 mask; |
| @@ -1065,9 +1043,19 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 1065 | break; | 1043 | break; |
| 1066 | case I915_EXEC_BSD: | 1044 | case I915_EXEC_BSD: |
| 1067 | ring = &dev_priv->ring[VCS]; | 1045 | ring = &dev_priv->ring[VCS]; |
| 1046 | if (ctx_id != 0) { | ||
| 1047 | DRM_DEBUG("Ring %s doesn't support contexts\n", | ||
| 1048 | ring->name); | ||
| 1049 | return -EPERM; | ||
| 1050 | } | ||
| 1068 | break; | 1051 | break; |
| 1069 | case I915_EXEC_BLT: | 1052 | case I915_EXEC_BLT: |
| 1070 | ring = &dev_priv->ring[BCS]; | 1053 | ring = &dev_priv->ring[BCS]; |
| 1054 | if (ctx_id != 0) { | ||
| 1055 | DRM_DEBUG("Ring %s doesn't support contexts\n", | ||
| 1056 | ring->name); | ||
| 1057 | return -EPERM; | ||
| 1058 | } | ||
| 1071 | break; | 1059 | break; |
| 1072 | default: | 1060 | default: |
| 1073 | DRM_DEBUG("execbuf with unknown ring: %d\n", | 1061 | DRM_DEBUG("execbuf with unknown ring: %d\n", |
| @@ -1240,6 +1228,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 1240 | } | 1228 | } |
| 1241 | } | 1229 | } |
| 1242 | 1230 | ||
| 1231 | ret = i915_switch_context(ring, file, ctx_id); | ||
| 1232 | if (ret) | ||
| 1233 | goto err; | ||
| 1234 | |||
| 1243 | if (ring == &dev_priv->ring[RCS] && | 1235 | if (ring == &dev_priv->ring[RCS] && |
| 1244 | mode != dev_priv->relative_constants_mode) { | 1236 | mode != dev_priv->relative_constants_mode) { |
| 1245 | ret = intel_ring_begin(ring, 4); | 1237 | ret = intel_ring_begin(ring, 4); |
| @@ -1367,6 +1359,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 1367 | exec2.num_cliprects = args->num_cliprects; | 1359 | exec2.num_cliprects = args->num_cliprects; |
| 1368 | exec2.cliprects_ptr = args->cliprects_ptr; | 1360 | exec2.cliprects_ptr = args->cliprects_ptr; |
| 1369 | exec2.flags = I915_EXEC_RENDER; | 1361 | exec2.flags = I915_EXEC_RENDER; |
| 1362 | i915_execbuffer2_set_context_id(exec2, 0); | ||
| 1370 | 1363 | ||
| 1371 | ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); | 1364 | ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); |
| 1372 | if (!ret) { | 1365 | if (!ret) { |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ed3224c37423..8a3828528b9d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -375,6 +375,86 @@ static void gen6_pm_rps_work(struct work_struct *work) | |||
| 375 | mutex_unlock(&dev_priv->dev->struct_mutex); | 375 | mutex_unlock(&dev_priv->dev->struct_mutex); |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | |||
| 379 | /** | ||
| 380 | * ivybridge_parity_work - Workqueue called when a parity error interrupt | ||
| 381 | * occurred. | ||
| 382 | * @work: workqueue struct | ||
| 383 | * | ||
| 384 | * Doesn't actually do anything except notify userspace. As a consequence of | ||
| 385 | * this event, userspace should try to remap the bad rows since statistically | ||
| 386 | * it is likely the same row is more likely to go bad again. | ||
| 387 | */ | ||
| 388 | static void ivybridge_parity_work(struct work_struct *work) | ||
| 389 | { | ||
| 390 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, | ||
| 391 | parity_error_work); | ||
| 392 | u32 error_status, row, bank, subbank; | ||
| 393 | char *parity_event[5]; | ||
| 394 | uint32_t misccpctl; | ||
| 395 | unsigned long flags; | ||
| 396 | |||
| 397 | /* We must turn off DOP level clock gating to access the L3 registers. | ||
| 398 | * In order to prevent a get/put style interface, acquire struct mutex | ||
| 399 | * any time we access those registers. | ||
| 400 | */ | ||
| 401 | mutex_lock(&dev_priv->dev->struct_mutex); | ||
| 402 | |||
| 403 | misccpctl = I915_READ(GEN7_MISCCPCTL); | ||
| 404 | I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); | ||
| 405 | POSTING_READ(GEN7_MISCCPCTL); | ||
| 406 | |||
| 407 | error_status = I915_READ(GEN7_L3CDERRST1); | ||
| 408 | row = GEN7_PARITY_ERROR_ROW(error_status); | ||
| 409 | bank = GEN7_PARITY_ERROR_BANK(error_status); | ||
| 410 | subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); | ||
| 411 | |||
| 412 | I915_WRITE(GEN7_L3CDERRST1, GEN7_PARITY_ERROR_VALID | | ||
| 413 | GEN7_L3CDERRST1_ENABLE); | ||
| 414 | POSTING_READ(GEN7_L3CDERRST1); | ||
| 415 | |||
| 416 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); | ||
| 417 | |||
| 418 | spin_lock_irqsave(&dev_priv->irq_lock, flags); | ||
| 419 | dev_priv->gt_irq_mask &= ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT; | ||
| 420 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); | ||
| 421 | spin_unlock_irqrestore(&dev_priv->irq_lock, flags); | ||
| 422 | |||
| 423 | mutex_unlock(&dev_priv->dev->struct_mutex); | ||
| 424 | |||
| 425 | parity_event[0] = "L3_PARITY_ERROR=1"; | ||
| 426 | parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); | ||
| 427 | parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); | ||
| 428 | parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); | ||
| 429 | parity_event[4] = NULL; | ||
| 430 | |||
| 431 | kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj, | ||
| 432 | KOBJ_CHANGE, parity_event); | ||
| 433 | |||
| 434 | DRM_DEBUG("Parity error: Row = %d, Bank = %d, Sub bank = %d.\n", | ||
| 435 | row, bank, subbank); | ||
| 436 | |||
| 437 | kfree(parity_event[3]); | ||
| 438 | kfree(parity_event[2]); | ||
| 439 | kfree(parity_event[1]); | ||
| 440 | } | ||
| 441 | |||
| 442 | static void ivybridge_handle_parity_error(struct drm_device *dev) | ||
| 443 | { | ||
| 444 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
| 445 | unsigned long flags; | ||
| 446 | |||
| 447 | if (!IS_IVYBRIDGE(dev)) | ||
| 448 | return; | ||
| 449 | |||
| 450 | spin_lock_irqsave(&dev_priv->irq_lock, flags); | ||
| 451 | dev_priv->gt_irq_mask |= GT_GEN7_L3_PARITY_ERROR_INTERRUPT; | ||
| 452 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); | ||
| 453 | spin_unlock_irqrestore(&dev_priv->irq_lock, flags); | ||
| 454 | |||
| 455 | queue_work(dev_priv->wq, &dev_priv->parity_error_work); | ||
| 456 | } | ||
| 457 | |||
| 378 | static void snb_gt_irq_handler(struct drm_device *dev, | 458 | static void snb_gt_irq_handler(struct drm_device *dev, |
| 379 | struct drm_i915_private *dev_priv, | 459 | struct drm_i915_private *dev_priv, |
| 380 | u32 gt_iir) | 460 | u32 gt_iir) |
| @@ -394,6 +474,9 @@ static void snb_gt_irq_handler(struct drm_device *dev, | |||
| 394 | DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir); | 474 | DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir); |
| 395 | i915_handle_error(dev, false); | 475 | i915_handle_error(dev, false); |
| 396 | } | 476 | } |
| 477 | |||
| 478 | if (gt_iir & GT_GEN7_L3_PARITY_ERROR_INTERRUPT) | ||
| 479 | ivybridge_handle_parity_error(dev); | ||
| 397 | } | 480 | } |
| 398 | 481 | ||
| 399 | static void gen6_queue_rps_work(struct drm_i915_private *dev_priv, | 482 | static void gen6_queue_rps_work(struct drm_i915_private *dev_priv, |
| @@ -429,15 +512,10 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) | |||
| 429 | unsigned long irqflags; | 512 | unsigned long irqflags; |
| 430 | int pipe; | 513 | int pipe; |
| 431 | u32 pipe_stats[I915_MAX_PIPES]; | 514 | u32 pipe_stats[I915_MAX_PIPES]; |
| 432 | u32 vblank_status; | ||
| 433 | int vblank = 0; | ||
| 434 | bool blc_event; | 515 | bool blc_event; |
| 435 | 516 | ||
| 436 | atomic_inc(&dev_priv->irq_received); | 517 | atomic_inc(&dev_priv->irq_received); |
| 437 | 518 | ||
| 438 | vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS | | ||
| 439 | PIPE_VBLANK_INTERRUPT_STATUS; | ||
| 440 | |||
| 441 | while (true) { | 519 | while (true) { |
| 442 | iir = I915_READ(VLV_IIR); | 520 | iir = I915_READ(VLV_IIR); |
| 443 | gt_iir = I915_READ(GTIIR); | 521 | gt_iir = I915_READ(GTIIR); |
| @@ -467,6 +545,16 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) | |||
| 467 | } | 545 | } |
| 468 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 546 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 469 | 547 | ||
| 548 | for_each_pipe(pipe) { | ||
| 549 | if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) | ||
| 550 | drm_handle_vblank(dev, pipe); | ||
| 551 | |||
| 552 | if (pipe_stats[pipe] & PLANE_FLIPDONE_INT_STATUS_VLV) { | ||
| 553 | intel_prepare_page_flip(dev, pipe); | ||
| 554 | intel_finish_page_flip(dev, pipe); | ||
| 555 | } | ||
| 556 | } | ||
| 557 | |||
| 470 | /* Consume port. Then clear IIR or we'll miss events */ | 558 | /* Consume port. Then clear IIR or we'll miss events */ |
| 471 | if (iir & I915_DISPLAY_PORT_INTERRUPT) { | 559 | if (iir & I915_DISPLAY_PORT_INTERRUPT) { |
| 472 | u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); | 560 | u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); |
| @@ -481,19 +569,6 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) | |||
| 481 | I915_READ(PORT_HOTPLUG_STAT); | 569 | I915_READ(PORT_HOTPLUG_STAT); |
| 482 | } | 570 | } |
| 483 | 571 | ||
| 484 | |||
| 485 | if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) { | ||
| 486 | drm_handle_vblank(dev, 0); | ||
| 487 | vblank++; | ||
| 488 | intel_finish_page_flip(dev, 0); | ||
| 489 | } | ||
| 490 | |||
| 491 | if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) { | ||
| 492 | drm_handle_vblank(dev, 1); | ||
| 493 | vblank++; | ||
| 494 | intel_finish_page_flip(dev, 0); | ||
| 495 | } | ||
| 496 | |||
| 497 | if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) | 572 | if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) |
| 498 | blc_event = true; | 573 | blc_event = true; |
| 499 | 574 | ||
| @@ -991,6 +1066,7 @@ static void i915_record_ring_state(struct drm_device *dev, | |||
| 991 | struct drm_i915_private *dev_priv = dev->dev_private; | 1066 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 992 | 1067 | ||
| 993 | if (INTEL_INFO(dev)->gen >= 6) { | 1068 | if (INTEL_INFO(dev)->gen >= 6) { |
| 1069 | error->rc_psmi[ring->id] = I915_READ(ring->mmio_base + 0x50); | ||
| 994 | error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring)); | 1070 | error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring)); |
| 995 | error->semaphore_mboxes[ring->id][0] | 1071 | error->semaphore_mboxes[ring->id][0] |
| 996 | = I915_READ(RING_SYNC_0(ring->mmio_base)); | 1072 | = I915_READ(RING_SYNC_0(ring->mmio_base)); |
| @@ -1104,6 +1180,7 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
| 1104 | kref_init(&error->ref); | 1180 | kref_init(&error->ref); |
| 1105 | error->eir = I915_READ(EIR); | 1181 | error->eir = I915_READ(EIR); |
| 1106 | error->pgtbl_er = I915_READ(PGTBL_ER); | 1182 | error->pgtbl_er = I915_READ(PGTBL_ER); |
| 1183 | error->ccid = I915_READ(CCID); | ||
| 1107 | 1184 | ||
| 1108 | if (HAS_PCH_SPLIT(dev)) | 1185 | if (HAS_PCH_SPLIT(dev)) |
| 1109 | error->ier = I915_READ(DEIER) | I915_READ(GTIER); | 1186 | error->ier = I915_READ(DEIER) | I915_READ(GTIER); |
| @@ -1426,23 +1503,20 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe) | |||
| 1426 | { | 1503 | { |
| 1427 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1504 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 1428 | unsigned long irqflags; | 1505 | unsigned long irqflags; |
| 1429 | u32 dpfl, imr; | 1506 | u32 imr; |
| 1430 | 1507 | ||
| 1431 | if (!i915_pipe_enabled(dev, pipe)) | 1508 | if (!i915_pipe_enabled(dev, pipe)) |
| 1432 | return -EINVAL; | 1509 | return -EINVAL; |
| 1433 | 1510 | ||
| 1434 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 1511 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
| 1435 | dpfl = I915_READ(VLV_DPFLIPSTAT); | ||
| 1436 | imr = I915_READ(VLV_IMR); | 1512 | imr = I915_READ(VLV_IMR); |
| 1437 | if (pipe == 0) { | 1513 | if (pipe == 0) |
| 1438 | dpfl |= PIPEA_VBLANK_INT_EN; | ||
| 1439 | imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; | 1514 | imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; |
| 1440 | } else { | 1515 | else |
| 1441 | dpfl |= PIPEA_VBLANK_INT_EN; | ||
| 1442 | imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; | 1516 | imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; |
| 1443 | } | ||
| 1444 | I915_WRITE(VLV_DPFLIPSTAT, dpfl); | ||
| 1445 | I915_WRITE(VLV_IMR, imr); | 1517 | I915_WRITE(VLV_IMR, imr); |
| 1518 | i915_enable_pipestat(dev_priv, pipe, | ||
| 1519 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | ||
| 1446 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1520 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 1447 | 1521 | ||
| 1448 | return 0; | 1522 | return 0; |
| @@ -1492,20 +1566,17 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe) | |||
| 1492 | { | 1566 | { |
| 1493 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1567 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 1494 | unsigned long irqflags; | 1568 | unsigned long irqflags; |
| 1495 | u32 dpfl, imr; | 1569 | u32 imr; |
| 1496 | 1570 | ||
| 1497 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 1571 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
| 1498 | dpfl = I915_READ(VLV_DPFLIPSTAT); | 1572 | i915_disable_pipestat(dev_priv, pipe, |
| 1573 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | ||
| 1499 | imr = I915_READ(VLV_IMR); | 1574 | imr = I915_READ(VLV_IMR); |
| 1500 | if (pipe == 0) { | 1575 | if (pipe == 0) |
| 1501 | dpfl &= ~PIPEA_VBLANK_INT_EN; | ||
| 1502 | imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; | 1576 | imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; |
| 1503 | } else { | 1577 | else |
| 1504 | dpfl &= ~PIPEB_VBLANK_INT_EN; | ||
| 1505 | imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; | 1578 | imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; |
| 1506 | } | ||
| 1507 | I915_WRITE(VLV_IMR, imr); | 1579 | I915_WRITE(VLV_IMR, imr); |
| 1508 | I915_WRITE(VLV_DPFLIPSTAT, dpfl); | ||
| 1509 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1580 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 1510 | } | 1581 | } |
| 1511 | 1582 | ||
| @@ -1648,7 +1719,6 @@ static void ironlake_irq_preinstall(struct drm_device *dev) | |||
| 1648 | 1719 | ||
| 1649 | atomic_set(&dev_priv->irq_received, 0); | 1720 | atomic_set(&dev_priv->irq_received, 0); |
| 1650 | 1721 | ||
| 1651 | |||
| 1652 | I915_WRITE(HWSTAM, 0xeffe); | 1722 | I915_WRITE(HWSTAM, 0xeffe); |
| 1653 | 1723 | ||
| 1654 | /* XXX hotplug from PCH */ | 1724 | /* XXX hotplug from PCH */ |
| @@ -1811,13 +1881,13 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) | |||
| 1811 | DE_PIPEA_VBLANK_IVB); | 1881 | DE_PIPEA_VBLANK_IVB); |
| 1812 | POSTING_READ(DEIER); | 1882 | POSTING_READ(DEIER); |
| 1813 | 1883 | ||
| 1814 | dev_priv->gt_irq_mask = ~0; | 1884 | dev_priv->gt_irq_mask = ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT; |
| 1815 | 1885 | ||
| 1816 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | 1886 | I915_WRITE(GTIIR, I915_READ(GTIIR)); |
| 1817 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); | 1887 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); |
| 1818 | 1888 | ||
| 1819 | render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT | | 1889 | render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT | |
| 1820 | GEN6_BLITTER_USER_INTERRUPT; | 1890 | GEN6_BLITTER_USER_INTERRUPT | GT_GEN7_L3_PARITY_ERROR_INTERRUPT; |
| 1821 | I915_WRITE(GTIER, render_irqs); | 1891 | I915_WRITE(GTIER, render_irqs); |
| 1822 | POSTING_READ(GTIER); | 1892 | POSTING_READ(GTIER); |
| 1823 | 1893 | ||
| @@ -1840,16 +1910,24 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) | |||
| 1840 | static int valleyview_irq_postinstall(struct drm_device *dev) | 1910 | static int valleyview_irq_postinstall(struct drm_device *dev) |
| 1841 | { | 1911 | { |
| 1842 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1912 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 1843 | u32 render_irqs; | ||
| 1844 | u32 enable_mask; | 1913 | u32 enable_mask; |
| 1845 | u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); | 1914 | u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); |
| 1915 | u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV; | ||
| 1846 | u16 msid; | 1916 | u16 msid; |
| 1847 | 1917 | ||
| 1848 | enable_mask = I915_DISPLAY_PORT_INTERRUPT; | 1918 | enable_mask = I915_DISPLAY_PORT_INTERRUPT; |
| 1849 | enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | | 1919 | enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | |
| 1920 | I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | | ||
| 1921 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | | ||
| 1850 | I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; | 1922 | I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; |
| 1851 | 1923 | ||
| 1852 | dev_priv->irq_mask = ~enable_mask; | 1924 | /* |
| 1925 | *Leave vblank interrupts masked initially. enable/disable will | ||
| 1926 | * toggle them based on usage. | ||
| 1927 | */ | ||
| 1928 | dev_priv->irq_mask = (~enable_mask) | | ||
| 1929 | I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | | ||
| 1930 | I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; | ||
| 1853 | 1931 | ||
| 1854 | dev_priv->pipestat[0] = 0; | 1932 | dev_priv->pipestat[0] = 0; |
| 1855 | dev_priv->pipestat[1] = 0; | 1933 | dev_priv->pipestat[1] = 0; |
| @@ -1868,26 +1946,27 @@ static int valleyview_irq_postinstall(struct drm_device *dev) | |||
| 1868 | I915_WRITE(PIPESTAT(1), 0xffff); | 1946 | I915_WRITE(PIPESTAT(1), 0xffff); |
| 1869 | POSTING_READ(VLV_IER); | 1947 | POSTING_READ(VLV_IER); |
| 1870 | 1948 | ||
| 1949 | i915_enable_pipestat(dev_priv, 0, pipestat_enable); | ||
| 1950 | i915_enable_pipestat(dev_priv, 1, pipestat_enable); | ||
| 1951 | |||
| 1871 | I915_WRITE(VLV_IIR, 0xffffffff); | 1952 | I915_WRITE(VLV_IIR, 0xffffffff); |
| 1872 | I915_WRITE(VLV_IIR, 0xffffffff); | 1953 | I915_WRITE(VLV_IIR, 0xffffffff); |
| 1873 | 1954 | ||
| 1874 | render_irqs = GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT | | 1955 | dev_priv->gt_irq_mask = ~0; |
| 1875 | GT_GEN6_BLT_CS_ERROR_INTERRUPT | | ||
| 1876 | GT_GEN6_BLT_USER_INTERRUPT | | ||
| 1877 | GT_GEN6_BSD_USER_INTERRUPT | | ||
| 1878 | GT_GEN6_BSD_CS_ERROR_INTERRUPT | | ||
| 1879 | GT_GEN7_L3_PARITY_ERROR_INTERRUPT | | ||
| 1880 | GT_PIPE_NOTIFY | | ||
| 1881 | GT_RENDER_CS_ERROR_INTERRUPT | | ||
| 1882 | GT_SYNC_STATUS | | ||
| 1883 | GT_USER_INTERRUPT; | ||
| 1884 | |||
| 1885 | dev_priv->gt_irq_mask = ~render_irqs; | ||
| 1886 | 1956 | ||
| 1887 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | 1957 | I915_WRITE(GTIIR, I915_READ(GTIIR)); |
| 1888 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | 1958 | I915_WRITE(GTIIR, I915_READ(GTIIR)); |
| 1889 | I915_WRITE(GTIMR, 0); | 1959 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); |
| 1890 | I915_WRITE(GTIER, render_irqs); | 1960 | I915_WRITE(GTIER, GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT | |
| 1961 | GT_GEN6_BLT_CS_ERROR_INTERRUPT | | ||
| 1962 | GT_GEN6_BLT_USER_INTERRUPT | | ||
| 1963 | GT_GEN6_BSD_USER_INTERRUPT | | ||
| 1964 | GT_GEN6_BSD_CS_ERROR_INTERRUPT | | ||
| 1965 | GT_GEN7_L3_PARITY_ERROR_INTERRUPT | | ||
| 1966 | GT_PIPE_NOTIFY | | ||
| 1967 | GT_RENDER_CS_ERROR_INTERRUPT | | ||
| 1968 | GT_SYNC_STATUS | | ||
| 1969 | GT_USER_INTERRUPT); | ||
| 1891 | POSTING_READ(GTIER); | 1970 | POSTING_READ(GTIER); |
| 1892 | 1971 | ||
| 1893 | /* ack & enable invalid PTE error interrupts */ | 1972 | /* ack & enable invalid PTE error interrupts */ |
| @@ -2166,9 +2245,9 @@ static int i915_irq_postinstall(struct drm_device *dev) | |||
| 2166 | hotplug_en |= HDMIC_HOTPLUG_INT_EN; | 2245 | hotplug_en |= HDMIC_HOTPLUG_INT_EN; |
| 2167 | if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) | 2246 | if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) |
| 2168 | hotplug_en |= HDMID_HOTPLUG_INT_EN; | 2247 | hotplug_en |= HDMID_HOTPLUG_INT_EN; |
| 2169 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) | 2248 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915) |
| 2170 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; | 2249 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; |
| 2171 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) | 2250 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915) |
| 2172 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; | 2251 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; |
| 2173 | if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { | 2252 | if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { |
| 2174 | hotplug_en |= CRT_HOTPLUG_INT_EN; | 2253 | hotplug_en |= CRT_HOTPLUG_INT_EN; |
| @@ -2328,10 +2407,8 @@ static void i965_irq_preinstall(struct drm_device * dev) | |||
| 2328 | 2407 | ||
| 2329 | atomic_set(&dev_priv->irq_received, 0); | 2408 | atomic_set(&dev_priv->irq_received, 0); |
| 2330 | 2409 | ||
| 2331 | if (I915_HAS_HOTPLUG(dev)) { | 2410 | I915_WRITE(PORT_HOTPLUG_EN, 0); |
| 2332 | I915_WRITE(PORT_HOTPLUG_EN, 0); | 2411 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); |
| 2333 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | ||
| 2334 | } | ||
| 2335 | 2412 | ||
| 2336 | I915_WRITE(HWSTAM, 0xeffe); | 2413 | I915_WRITE(HWSTAM, 0xeffe); |
| 2337 | for_each_pipe(pipe) | 2414 | for_each_pipe(pipe) |
| @@ -2344,11 +2421,13 @@ static void i965_irq_preinstall(struct drm_device * dev) | |||
| 2344 | static int i965_irq_postinstall(struct drm_device *dev) | 2421 | static int i965_irq_postinstall(struct drm_device *dev) |
| 2345 | { | 2422 | { |
| 2346 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 2423 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 2424 | u32 hotplug_en; | ||
| 2347 | u32 enable_mask; | 2425 | u32 enable_mask; |
| 2348 | u32 error_mask; | 2426 | u32 error_mask; |
| 2349 | 2427 | ||
| 2350 | /* Unmask the interrupts that we always want on. */ | 2428 | /* Unmask the interrupts that we always want on. */ |
| 2351 | dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT | | 2429 | dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT | |
| 2430 | I915_DISPLAY_PORT_INTERRUPT | | ||
| 2352 | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | | 2431 | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | |
| 2353 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | | 2432 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | |
| 2354 | I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | | 2433 | I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | |
| @@ -2364,13 +2443,6 @@ static int i965_irq_postinstall(struct drm_device *dev) | |||
| 2364 | dev_priv->pipestat[0] = 0; | 2443 | dev_priv->pipestat[0] = 0; |
| 2365 | dev_priv->pipestat[1] = 0; | 2444 | dev_priv->pipestat[1] = 0; |
| 2366 | 2445 | ||
| 2367 | if (I915_HAS_HOTPLUG(dev)) { | ||
| 2368 | /* Enable in IER... */ | ||
| 2369 | enable_mask |= I915_DISPLAY_PORT_INTERRUPT; | ||
| 2370 | /* and unmask in IMR */ | ||
| 2371 | dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; | ||
| 2372 | } | ||
| 2373 | |||
| 2374 | /* | 2446 | /* |
| 2375 | * Enable some error detection, note the instruction error mask | 2447 | * Enable some error detection, note the instruction error mask |
| 2376 | * bit is reserved, so we leave it masked. | 2448 | * bit is reserved, so we leave it masked. |
| @@ -2390,36 +2462,40 @@ static int i965_irq_postinstall(struct drm_device *dev) | |||
| 2390 | I915_WRITE(IER, enable_mask); | 2462 | I915_WRITE(IER, enable_mask); |
| 2391 | POSTING_READ(IER); | 2463 | POSTING_READ(IER); |
| 2392 | 2464 | ||
| 2393 | if (I915_HAS_HOTPLUG(dev)) { | 2465 | /* Note HDMI and DP share hotplug bits */ |
| 2394 | u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); | 2466 | hotplug_en = 0; |
| 2395 | 2467 | if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) | |
| 2396 | /* Note HDMI and DP share bits */ | 2468 | hotplug_en |= HDMIB_HOTPLUG_INT_EN; |
| 2397 | if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) | 2469 | if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) |
| 2398 | hotplug_en |= HDMIB_HOTPLUG_INT_EN; | 2470 | hotplug_en |= HDMIC_HOTPLUG_INT_EN; |
| 2399 | if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) | 2471 | if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) |
| 2400 | hotplug_en |= HDMIC_HOTPLUG_INT_EN; | 2472 | hotplug_en |= HDMID_HOTPLUG_INT_EN; |
| 2401 | if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) | 2473 | if (IS_G4X(dev)) { |
| 2402 | hotplug_en |= HDMID_HOTPLUG_INT_EN; | 2474 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X) |
| 2403 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) | ||
| 2404 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; | 2475 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; |
| 2405 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) | 2476 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_G4X) |
| 2406 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; | 2477 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; |
| 2407 | if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { | 2478 | } else { |
| 2408 | hotplug_en |= CRT_HOTPLUG_INT_EN; | 2479 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I965) |
| 2480 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; | ||
| 2481 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I965) | ||
| 2482 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; | ||
| 2483 | } | ||
| 2484 | if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { | ||
| 2485 | hotplug_en |= CRT_HOTPLUG_INT_EN; | ||
| 2409 | 2486 | ||
| 2410 | /* Programming the CRT detection parameters tends | 2487 | /* Programming the CRT detection parameters tends |
| 2411 | to generate a spurious hotplug event about three | 2488 | to generate a spurious hotplug event about three |
| 2412 | seconds later. So just do it once. | 2489 | seconds later. So just do it once. |
| 2413 | */ | 2490 | */ |
| 2414 | if (IS_G4X(dev)) | 2491 | if (IS_G4X(dev)) |
| 2415 | hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; | 2492 | hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; |
| 2416 | hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; | 2493 | hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; |
| 2417 | } | 2494 | } |
| 2418 | 2495 | ||
| 2419 | /* Ignore TV since it's buggy */ | 2496 | /* Ignore TV since it's buggy */ |
| 2420 | 2497 | ||
| 2421 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); | 2498 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); |
| 2422 | } | ||
| 2423 | 2499 | ||
| 2424 | intel_opregion_enable_asle(dev); | 2500 | intel_opregion_enable_asle(dev); |
| 2425 | 2501 | ||
| @@ -2477,8 +2553,7 @@ static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS) | |||
| 2477 | ret = IRQ_HANDLED; | 2553 | ret = IRQ_HANDLED; |
| 2478 | 2554 | ||
| 2479 | /* Consume port. Then clear IIR or we'll miss events */ | 2555 | /* Consume port. Then clear IIR or we'll miss events */ |
| 2480 | if ((I915_HAS_HOTPLUG(dev)) && | 2556 | if (iir & I915_DISPLAY_PORT_INTERRUPT) { |
| 2481 | (iir & I915_DISPLAY_PORT_INTERRUPT)) { | ||
| 2482 | u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); | 2557 | u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); |
| 2483 | 2558 | ||
| 2484 | DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", | 2559 | DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", |
| @@ -2551,10 +2626,8 @@ static void i965_irq_uninstall(struct drm_device * dev) | |||
| 2551 | if (!dev_priv) | 2626 | if (!dev_priv) |
| 2552 | return; | 2627 | return; |
| 2553 | 2628 | ||
| 2554 | if (I915_HAS_HOTPLUG(dev)) { | 2629 | I915_WRITE(PORT_HOTPLUG_EN, 0); |
| 2555 | I915_WRITE(PORT_HOTPLUG_EN, 0); | 2630 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); |
| 2556 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | ||
| 2557 | } | ||
| 2558 | 2631 | ||
| 2559 | I915_WRITE(HWSTAM, 0xffffffff); | 2632 | I915_WRITE(HWSTAM, 0xffffffff); |
| 2560 | for_each_pipe(pipe) | 2633 | for_each_pipe(pipe) |
| @@ -2575,6 +2648,7 @@ void intel_irq_init(struct drm_device *dev) | |||
| 2575 | INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); | 2648 | INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); |
| 2576 | INIT_WORK(&dev_priv->error_work, i915_error_work_func); | 2649 | INIT_WORK(&dev_priv->error_work, i915_error_work_func); |
| 2577 | INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); | 2650 | INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); |
| 2651 | INIT_WORK(&dev_priv->parity_error_work, ivybridge_parity_work); | ||
| 2578 | 2652 | ||
| 2579 | dev->driver->get_vblank_counter = i915_get_vblank_counter; | 2653 | dev->driver->get_vblank_counter = i915_get_vblank_counter; |
| 2580 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ | 2654 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 48d5e8e051cf..acc99b21e0b6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -217,6 +217,9 @@ | |||
| 217 | #define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) | 217 | #define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) |
| 218 | #define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) | 218 | #define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) |
| 219 | #define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) | 219 | #define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) |
| 220 | #define MI_ARB_ON_OFF MI_INSTR(0x08, 0) | ||
| 221 | #define MI_ARB_ENABLE (1<<0) | ||
| 222 | #define MI_ARB_DISABLE (0<<0) | ||
| 220 | 223 | ||
| 221 | #define MI_SET_CONTEXT MI_INSTR(0x18, 0) | 224 | #define MI_SET_CONTEXT MI_INSTR(0x18, 0) |
| 222 | #define MI_MM_SPACE_GTT (1<<8) | 225 | #define MI_MM_SPACE_GTT (1<<8) |
| @@ -299,6 +302,7 @@ | |||
| 299 | #define DISPLAY_PLANE_B (1<<20) | 302 | #define DISPLAY_PLANE_B (1<<20) |
| 300 | #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2)) | 303 | #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2)) |
| 301 | #define PIPE_CONTROL_CS_STALL (1<<20) | 304 | #define PIPE_CONTROL_CS_STALL (1<<20) |
| 305 | #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) | ||
| 302 | #define PIPE_CONTROL_QW_WRITE (1<<14) | 306 | #define PIPE_CONTROL_QW_WRITE (1<<14) |
| 303 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) | 307 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) |
| 304 | #define PIPE_CONTROL_WRITE_FLUSH (1<<12) | 308 | #define PIPE_CONTROL_WRITE_FLUSH (1<<12) |
| @@ -686,10 +690,10 @@ | |||
| 686 | #define GEN6_BLITTER_FBC_NOTIFY (1<<3) | 690 | #define GEN6_BLITTER_FBC_NOTIFY (1<<3) |
| 687 | 691 | ||
| 688 | #define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050 | 692 | #define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050 |
| 689 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK (1 << 16) | 693 | #define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0) |
| 690 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE (1 << 0) | 694 | #define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2) |
| 691 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0 | 695 | #define GEN6_BSD_SLEEP_INDICATOR (1 << 3) |
| 692 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3) | 696 | #define GEN6_BSD_GO_INDICATOR (1 << 4) |
| 693 | 697 | ||
| 694 | #define GEN6_BSD_HWSTAM 0x12098 | 698 | #define GEN6_BSD_HWSTAM 0x12098 |
| 695 | #define GEN6_BSD_IMR 0x120a8 | 699 | #define GEN6_BSD_IMR 0x120a8 |
| @@ -908,6 +912,7 @@ | |||
| 908 | #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ | 912 | #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ |
| 909 | #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ | 913 | #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ |
| 910 | #define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ | 914 | #define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ |
| 915 | #define DPLL_LOCK_VLV (1<<15) | ||
| 911 | #define DPLL_INTEGRATED_CLOCK_VLV (1<<13) | 916 | #define DPLL_INTEGRATED_CLOCK_VLV (1<<13) |
| 912 | 917 | ||
| 913 | #define SRX_INDEX 0x3c4 | 918 | #define SRX_INDEX 0x3c4 |
| @@ -1453,6 +1458,10 @@ | |||
| 1453 | #define DDRMPLL1 0X12c20 | 1458 | #define DDRMPLL1 0X12c20 |
| 1454 | #define PEG_BAND_GAP_DATA 0x14d68 | 1459 | #define PEG_BAND_GAP_DATA 0x14d68 |
| 1455 | 1460 | ||
| 1461 | #define GEN6_GT_THREAD_STATUS_REG 0x13805c | ||
| 1462 | #define GEN6_GT_THREAD_STATUS_CORE_MASK 0x7 | ||
| 1463 | #define GEN6_GT_THREAD_STATUS_CORE_MASK_HSW (0x7 | (0x07 << 16)) | ||
| 1464 | |||
| 1456 | #define GEN6_GT_PERF_STATUS 0x145948 | 1465 | #define GEN6_GT_PERF_STATUS 0x145948 |
| 1457 | #define GEN6_RP_STATE_LIMITS 0x145994 | 1466 | #define GEN6_RP_STATE_LIMITS 0x145994 |
| 1458 | #define GEN6_RP_STATE_CAP 0x145998 | 1467 | #define GEN6_RP_STATE_CAP 0x145998 |
| @@ -1462,6 +1471,31 @@ | |||
| 1462 | */ | 1471 | */ |
| 1463 | #define CCID 0x2180 | 1472 | #define CCID 0x2180 |
| 1464 | #define CCID_EN (1<<0) | 1473 | #define CCID_EN (1<<0) |
| 1474 | #define CXT_SIZE 0x21a0 | ||
| 1475 | #define GEN6_CXT_POWER_SIZE(cxt_reg) ((cxt_reg >> 24) & 0x3f) | ||
| 1476 | #define GEN6_CXT_RING_SIZE(cxt_reg) ((cxt_reg >> 18) & 0x3f) | ||
| 1477 | #define GEN6_CXT_RENDER_SIZE(cxt_reg) ((cxt_reg >> 12) & 0x3f) | ||
| 1478 | #define GEN6_CXT_EXTENDED_SIZE(cxt_reg) ((cxt_reg >> 6) & 0x3f) | ||
| 1479 | #define GEN6_CXT_PIPELINE_SIZE(cxt_reg) ((cxt_reg >> 0) & 0x3f) | ||
| 1480 | #define GEN6_CXT_TOTAL_SIZE(cxt_reg) (GEN6_CXT_POWER_SIZE(cxt_reg) + \ | ||
| 1481 | GEN6_CXT_RING_SIZE(cxt_reg) + \ | ||
| 1482 | GEN6_CXT_RENDER_SIZE(cxt_reg) + \ | ||
| 1483 | GEN6_CXT_EXTENDED_SIZE(cxt_reg) + \ | ||
| 1484 | GEN6_CXT_PIPELINE_SIZE(cxt_reg)) | ||
| 1485 | #define GEN7_CXT_SIZE 0x21a8 | ||
| 1486 | #define GEN7_CXT_POWER_SIZE(ctx_reg) ((ctx_reg >> 25) & 0x7f) | ||
| 1487 | #define GEN7_CXT_RING_SIZE(ctx_reg) ((ctx_reg >> 22) & 0x7) | ||
| 1488 | #define GEN7_CXT_RENDER_SIZE(ctx_reg) ((ctx_reg >> 16) & 0x3f) | ||
| 1489 | #define GEN7_CXT_EXTENDED_SIZE(ctx_reg) ((ctx_reg >> 9) & 0x7f) | ||
| 1490 | #define GEN7_CXT_GT1_SIZE(ctx_reg) ((ctx_reg >> 6) & 0x7) | ||
| 1491 | #define GEN7_CXT_VFSTATE_SIZE(ctx_reg) ((ctx_reg >> 0) & 0x3f) | ||
| 1492 | #define GEN7_CXT_TOTAL_SIZE(ctx_reg) (GEN7_CXT_POWER_SIZE(ctx_reg) + \ | ||
| 1493 | GEN7_CXT_RING_SIZE(ctx_reg) + \ | ||
| 1494 | GEN7_CXT_RENDER_SIZE(ctx_reg) + \ | ||
| 1495 | GEN7_CXT_EXTENDED_SIZE(ctx_reg) + \ | ||
| 1496 | GEN7_CXT_GT1_SIZE(ctx_reg) + \ | ||
| 1497 | GEN7_CXT_VFSTATE_SIZE(ctx_reg)) | ||
| 1498 | |||
| 1465 | /* | 1499 | /* |
| 1466 | * Overlay regs | 1500 | * Overlay regs |
| 1467 | */ | 1501 | */ |
| @@ -1566,20 +1600,34 @@ | |||
| 1566 | #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) | 1600 | #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) |
| 1567 | 1601 | ||
| 1568 | #define PORT_HOTPLUG_STAT 0x61114 | 1602 | #define PORT_HOTPLUG_STAT 0x61114 |
| 1569 | #define HDMIB_HOTPLUG_INT_STATUS (1 << 29) | 1603 | /* HDMI/DP bits are gen4+ */ |
| 1570 | #define DPB_HOTPLUG_INT_STATUS (1 << 29) | 1604 | #define DPB_HOTPLUG_LIVE_STATUS (1 << 29) |
| 1571 | #define HDMIC_HOTPLUG_INT_STATUS (1 << 28) | 1605 | #define DPC_HOTPLUG_LIVE_STATUS (1 << 28) |
| 1572 | #define DPC_HOTPLUG_INT_STATUS (1 << 28) | 1606 | #define DPD_HOTPLUG_LIVE_STATUS (1 << 27) |
| 1573 | #define HDMID_HOTPLUG_INT_STATUS (1 << 27) | 1607 | #define DPD_HOTPLUG_INT_STATUS (3 << 21) |
| 1574 | #define DPD_HOTPLUG_INT_STATUS (1 << 27) | 1608 | #define DPC_HOTPLUG_INT_STATUS (3 << 19) |
| 1609 | #define DPB_HOTPLUG_INT_STATUS (3 << 17) | ||
| 1610 | /* HDMI bits are shared with the DP bits */ | ||
| 1611 | #define HDMIB_HOTPLUG_LIVE_STATUS (1 << 29) | ||
| 1612 | #define HDMIC_HOTPLUG_LIVE_STATUS (1 << 28) | ||
| 1613 | #define HDMID_HOTPLUG_LIVE_STATUS (1 << 27) | ||
| 1614 | #define HDMID_HOTPLUG_INT_STATUS (3 << 21) | ||
| 1615 | #define HDMIC_HOTPLUG_INT_STATUS (3 << 19) | ||
| 1616 | #define HDMIB_HOTPLUG_INT_STATUS (3 << 17) | ||
| 1617 | /* CRT/TV common between gen3+ */ | ||
| 1575 | #define CRT_HOTPLUG_INT_STATUS (1 << 11) | 1618 | #define CRT_HOTPLUG_INT_STATUS (1 << 11) |
| 1576 | #define TV_HOTPLUG_INT_STATUS (1 << 10) | 1619 | #define TV_HOTPLUG_INT_STATUS (1 << 10) |
| 1577 | #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) | 1620 | #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) |
| 1578 | #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) | 1621 | #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) |
| 1579 | #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) | 1622 | #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) |
| 1580 | #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) | 1623 | #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) |
| 1581 | #define SDVOC_HOTPLUG_INT_STATUS (1 << 7) | 1624 | /* SDVO is different across gen3/4 */ |
| 1582 | #define SDVOB_HOTPLUG_INT_STATUS (1 << 6) | 1625 | #define SDVOC_HOTPLUG_INT_STATUS_G4X (1 << 3) |
| 1626 | #define SDVOB_HOTPLUG_INT_STATUS_G4X (1 << 2) | ||
| 1627 | #define SDVOC_HOTPLUG_INT_STATUS_I965 (3 << 4) | ||
| 1628 | #define SDVOB_HOTPLUG_INT_STATUS_I965 (3 << 2) | ||
| 1629 | #define SDVOC_HOTPLUG_INT_STATUS_I915 (1 << 7) | ||
| 1630 | #define SDVOB_HOTPLUG_INT_STATUS_I915 (1 << 6) | ||
| 1583 | 1631 | ||
| 1584 | /* SDVO port control */ | 1632 | /* SDVO port control */ |
| 1585 | #define SDVOB 0x61140 | 1633 | #define SDVOB 0x61140 |
| @@ -1711,8 +1759,10 @@ | |||
| 1711 | #define VIDEO_DIP_PORT_C (2 << 29) | 1759 | #define VIDEO_DIP_PORT_C (2 << 29) |
| 1712 | #define VIDEO_DIP_PORT_D (3 << 29) | 1760 | #define VIDEO_DIP_PORT_D (3 << 29) |
| 1713 | #define VIDEO_DIP_PORT_MASK (3 << 29) | 1761 | #define VIDEO_DIP_PORT_MASK (3 << 29) |
| 1762 | #define VIDEO_DIP_ENABLE_GCP (1 << 25) | ||
| 1714 | #define VIDEO_DIP_ENABLE_AVI (1 << 21) | 1763 | #define VIDEO_DIP_ENABLE_AVI (1 << 21) |
| 1715 | #define VIDEO_DIP_ENABLE_VENDOR (2 << 21) | 1764 | #define VIDEO_DIP_ENABLE_VENDOR (2 << 21) |
| 1765 | #define VIDEO_DIP_ENABLE_GAMUT (4 << 21) | ||
| 1716 | #define VIDEO_DIP_ENABLE_SPD (8 << 21) | 1766 | #define VIDEO_DIP_ENABLE_SPD (8 << 21) |
| 1717 | #define VIDEO_DIP_SELECT_AVI (0 << 19) | 1767 | #define VIDEO_DIP_SELECT_AVI (0 << 19) |
| 1718 | #define VIDEO_DIP_SELECT_VENDOR (1 << 19) | 1768 | #define VIDEO_DIP_SELECT_VENDOR (1 << 19) |
| @@ -1723,7 +1773,11 @@ | |||
| 1723 | #define VIDEO_DIP_FREQ_2VSYNC (2 << 16) | 1773 | #define VIDEO_DIP_FREQ_2VSYNC (2 << 16) |
| 1724 | #define VIDEO_DIP_FREQ_MASK (3 << 16) | 1774 | #define VIDEO_DIP_FREQ_MASK (3 << 16) |
| 1725 | /* HSW and later: */ | 1775 | /* HSW and later: */ |
| 1776 | #define VIDEO_DIP_ENABLE_VSC_HSW (1 << 20) | ||
| 1777 | #define VIDEO_DIP_ENABLE_GCP_HSW (1 << 16) | ||
| 1726 | #define VIDEO_DIP_ENABLE_AVI_HSW (1 << 12) | 1778 | #define VIDEO_DIP_ENABLE_AVI_HSW (1 << 12) |
| 1779 | #define VIDEO_DIP_ENABLE_VS_HSW (1 << 8) | ||
| 1780 | #define VIDEO_DIP_ENABLE_GMP_HSW (1 << 4) | ||
| 1727 | #define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) | 1781 | #define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) |
| 1728 | 1782 | ||
| 1729 | /* Panel power sequencing */ | 1783 | /* Panel power sequencing */ |
| @@ -1795,18 +1849,35 @@ | |||
| 1795 | #define PFIT_AUTO_RATIOS 0x61238 | 1849 | #define PFIT_AUTO_RATIOS 0x61238 |
| 1796 | 1850 | ||
| 1797 | /* Backlight control */ | 1851 | /* Backlight control */ |
| 1798 | #define BLC_PWM_CTL 0x61254 | ||
| 1799 | #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) | ||
| 1800 | #define BLC_PWM_CTL2 0x61250 /* 965+ only */ | 1852 | #define BLC_PWM_CTL2 0x61250 /* 965+ only */ |
| 1801 | #define BLM_COMBINATION_MODE (1 << 30) | 1853 | #define BLM_PWM_ENABLE (1 << 31) |
| 1854 | #define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */ | ||
| 1855 | #define BLM_PIPE_SELECT (1 << 29) | ||
| 1856 | #define BLM_PIPE_SELECT_IVB (3 << 29) | ||
| 1857 | #define BLM_PIPE_A (0 << 29) | ||
| 1858 | #define BLM_PIPE_B (1 << 29) | ||
| 1859 | #define BLM_PIPE_C (2 << 29) /* ivb + */ | ||
| 1860 | #define BLM_PIPE(pipe) ((pipe) << 29) | ||
| 1861 | #define BLM_POLARITY_I965 (1 << 28) /* gen4 only */ | ||
| 1862 | #define BLM_PHASE_IN_INTERUPT_STATUS (1 << 26) | ||
| 1863 | #define BLM_PHASE_IN_ENABLE (1 << 25) | ||
| 1864 | #define BLM_PHASE_IN_INTERUPT_ENABL (1 << 24) | ||
| 1865 | #define BLM_PHASE_IN_TIME_BASE_SHIFT (16) | ||
| 1866 | #define BLM_PHASE_IN_TIME_BASE_MASK (0xff << 16) | ||
| 1867 | #define BLM_PHASE_IN_COUNT_SHIFT (8) | ||
| 1868 | #define BLM_PHASE_IN_COUNT_MASK (0xff << 8) | ||
| 1869 | #define BLM_PHASE_IN_INCR_SHIFT (0) | ||
| 1870 | #define BLM_PHASE_IN_INCR_MASK (0xff << 0) | ||
| 1871 | #define BLC_PWM_CTL 0x61254 | ||
| 1802 | /* | 1872 | /* |
| 1803 | * This is the most significant 15 bits of the number of backlight cycles in a | 1873 | * This is the most significant 15 bits of the number of backlight cycles in a |
| 1804 | * complete cycle of the modulated backlight control. | 1874 | * complete cycle of the modulated backlight control. |
| 1805 | * | 1875 | * |
| 1806 | * The actual value is this field multiplied by two. | 1876 | * The actual value is this field multiplied by two. |
| 1807 | */ | 1877 | */ |
| 1808 | #define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) | 1878 | #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) |
| 1809 | #define BLM_LEGACY_MODE (1 << 16) | 1879 | #define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) |
| 1880 | #define BLM_LEGACY_MODE (1 << 16) /* gen2 only */ | ||
| 1810 | /* | 1881 | /* |
| 1811 | * This is the number of cycles out of the backlight modulation cycle for which | 1882 | * This is the number of cycles out of the backlight modulation cycle for which |
| 1812 | * the backlight is on. | 1883 | * the backlight is on. |
| @@ -1816,9 +1887,24 @@ | |||
| 1816 | */ | 1887 | */ |
| 1817 | #define BACKLIGHT_DUTY_CYCLE_SHIFT (0) | 1888 | #define BACKLIGHT_DUTY_CYCLE_SHIFT (0) |
| 1818 | #define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) | 1889 | #define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) |
| 1890 | #define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe) | ||
| 1891 | #define BLM_POLARITY_PNV (1 << 0) /* pnv only */ | ||
| 1819 | 1892 | ||
| 1820 | #define BLC_HIST_CTL 0x61260 | 1893 | #define BLC_HIST_CTL 0x61260 |
| 1821 | 1894 | ||
| 1895 | /* New registers for PCH-split platforms. Safe where new bits show up, the | ||
| 1896 | * register layout machtes with gen4 BLC_PWM_CTL[12]. */ | ||
| 1897 | #define BLC_PWM_CPU_CTL2 0x48250 | ||
| 1898 | #define BLC_PWM_CPU_CTL 0x48254 | ||
| 1899 | |||
| 1900 | /* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is | ||
| 1901 | * like the normal CTL from gen4 and earlier. Hooray for confusing naming. */ | ||
| 1902 | #define BLC_PWM_PCH_CTL1 0xc8250 | ||
| 1903 | #define BLM_PCH_PWM_ENABLE (1 << 31) | ||
| 1904 | #define BLM_PCH_OVERRIDE_ENABLE (1 << 30) | ||
| 1905 | #define BLM_PCH_POLARITY (1 << 29) | ||
| 1906 | #define BLC_PWM_PCH_CTL2 0xc8254 | ||
| 1907 | |||
| 1822 | /* TV port control */ | 1908 | /* TV port control */ |
| 1823 | #define TV_CTL 0x68000 | 1909 | #define TV_CTL 0x68000 |
| 1824 | /** Enables the TV encoder */ | 1910 | /** Enables the TV encoder */ |
| @@ -2583,13 +2669,13 @@ | |||
| 2583 | #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) | 2669 | #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) |
| 2584 | 2670 | ||
| 2585 | #define VLV_DPFLIPSTAT 0x70028 | 2671 | #define VLV_DPFLIPSTAT 0x70028 |
| 2586 | #define PIPEB_LINE_COMPARE_STATUS (1<<29) | 2672 | #define PIPEB_LINE_COMPARE_INT_EN (1<<29) |
| 2587 | #define PIPEB_HLINE_INT_EN (1<<28) | 2673 | #define PIPEB_HLINE_INT_EN (1<<28) |
| 2588 | #define PIPEB_VBLANK_INT_EN (1<<27) | 2674 | #define PIPEB_VBLANK_INT_EN (1<<27) |
| 2589 | #define SPRITED_FLIPDONE_INT_EN (1<<26) | 2675 | #define SPRITED_FLIPDONE_INT_EN (1<<26) |
| 2590 | #define SPRITEC_FLIPDONE_INT_EN (1<<25) | 2676 | #define SPRITEC_FLIPDONE_INT_EN (1<<25) |
| 2591 | #define PLANEB_FLIPDONE_INT_EN (1<<24) | 2677 | #define PLANEB_FLIPDONE_INT_EN (1<<24) |
| 2592 | #define PIPEA_LINE_COMPARE_STATUS (1<<21) | 2678 | #define PIPEA_LINE_COMPARE_INT_EN (1<<21) |
| 2593 | #define PIPEA_HLINE_INT_EN (1<<20) | 2679 | #define PIPEA_HLINE_INT_EN (1<<20) |
| 2594 | #define PIPEA_VBLANK_INT_EN (1<<19) | 2680 | #define PIPEA_VBLANK_INT_EN (1<<19) |
| 2595 | #define SPRITEB_FLIPDONE_INT_EN (1<<18) | 2681 | #define SPRITEB_FLIPDONE_INT_EN (1<<18) |
| @@ -2897,13 +2983,14 @@ | |||
| 2897 | #define DSPSIZE(plane) _PIPE(plane, _DSPASIZE, _DSPBSIZE) | 2983 | #define DSPSIZE(plane) _PIPE(plane, _DSPASIZE, _DSPBSIZE) |
| 2898 | #define DSPSURF(plane) _PIPE(plane, _DSPASURF, _DSPBSURF) | 2984 | #define DSPSURF(plane) _PIPE(plane, _DSPASURF, _DSPBSURF) |
| 2899 | #define DSPTILEOFF(plane) _PIPE(plane, _DSPATILEOFF, _DSPBTILEOFF) | 2985 | #define DSPTILEOFF(plane) _PIPE(plane, _DSPATILEOFF, _DSPBTILEOFF) |
| 2986 | #define DSPLINOFF(plane) DSPADDR(plane) | ||
| 2900 | 2987 | ||
| 2901 | /* Display/Sprite base address macros */ | 2988 | /* Display/Sprite base address macros */ |
| 2902 | #define DISP_BASEADDR_MASK (0xfffff000) | 2989 | #define DISP_BASEADDR_MASK (0xfffff000) |
| 2903 | #define I915_LO_DISPBASE(val) (val & ~DISP_BASEADDR_MASK) | 2990 | #define I915_LO_DISPBASE(val) (val & ~DISP_BASEADDR_MASK) |
| 2904 | #define I915_HI_DISPBASE(val) (val & DISP_BASEADDR_MASK) | 2991 | #define I915_HI_DISPBASE(val) (val & DISP_BASEADDR_MASK) |
| 2905 | #define I915_MODIFY_DISPBASE(reg, gfx_addr) \ | 2992 | #define I915_MODIFY_DISPBASE(reg, gfx_addr) \ |
| 2906 | (I915_WRITE(reg, gfx_addr | I915_LO_DISPBASE(I915_READ(reg)))) | 2993 | (I915_WRITE((reg), (gfx_addr) | I915_LO_DISPBASE(I915_READ(reg)))) |
| 2907 | 2994 | ||
| 2908 | /* VBIOS flags */ | 2995 | /* VBIOS flags */ |
| 2909 | #define SWF00 0x71410 | 2996 | #define SWF00 0x71410 |
| @@ -3771,6 +3858,9 @@ | |||
| 3771 | #define _FDI_RXA_TUSIZE2 0xf0038 | 3858 | #define _FDI_RXA_TUSIZE2 0xf0038 |
| 3772 | #define _FDI_RXB_TUSIZE1 0xf1030 | 3859 | #define _FDI_RXB_TUSIZE1 0xf1030 |
| 3773 | #define _FDI_RXB_TUSIZE2 0xf1038 | 3860 | #define _FDI_RXB_TUSIZE2 0xf1038 |
| 3861 | #define FDI_RX_TP1_TO_TP2_48 (2<<20) | ||
| 3862 | #define FDI_RX_TP1_TO_TP2_64 (3<<20) | ||
| 3863 | #define FDI_RX_FDI_DELAY_90 (0x90<<0) | ||
| 3774 | #define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC) | 3864 | #define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC) |
| 3775 | #define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1) | 3865 | #define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1) |
| 3776 | #define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2) | 3866 | #define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2) |
| @@ -3824,7 +3914,6 @@ | |||
| 3824 | #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) | 3914 | #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) |
| 3825 | 3915 | ||
| 3826 | /* or SDVOB */ | 3916 | /* or SDVOB */ |
| 3827 | #define VLV_HDMIB 0x61140 | ||
| 3828 | #define HDMIB 0xe1140 | 3917 | #define HDMIB 0xe1140 |
| 3829 | #define PORT_ENABLE (1 << 31) | 3918 | #define PORT_ENABLE (1 << 31) |
| 3830 | #define TRANSCODER(pipe) ((pipe) << 30) | 3919 | #define TRANSCODER(pipe) ((pipe) << 30) |
| @@ -3855,20 +3944,18 @@ | |||
| 3855 | #define PCH_LVDS 0xe1180 | 3944 | #define PCH_LVDS 0xe1180 |
| 3856 | #define LVDS_DETECTED (1 << 1) | 3945 | #define LVDS_DETECTED (1 << 1) |
| 3857 | 3946 | ||
| 3858 | #define BLC_PWM_CPU_CTL2 0x48250 | 3947 | /* vlv has 2 sets of panel control regs. */ |
| 3859 | #define PWM_ENABLE (1 << 31) | 3948 | #define PIPEA_PP_STATUS 0x61200 |
| 3860 | #define PWM_PIPE_A (0 << 29) | 3949 | #define PIPEA_PP_CONTROL 0x61204 |
| 3861 | #define PWM_PIPE_B (1 << 29) | 3950 | #define PIPEA_PP_ON_DELAYS 0x61208 |
| 3862 | #define BLC_PWM_CPU_CTL 0x48254 | 3951 | #define PIPEA_PP_OFF_DELAYS 0x6120c |
| 3952 | #define PIPEA_PP_DIVISOR 0x61210 | ||
| 3863 | 3953 | ||
| 3864 | #define BLC_PWM_PCH_CTL1 0xc8250 | 3954 | #define PIPEB_PP_STATUS 0x61300 |
| 3865 | #define PWM_PCH_ENABLE (1 << 31) | 3955 | #define PIPEB_PP_CONTROL 0x61304 |
| 3866 | #define PWM_POLARITY_ACTIVE_LOW (1 << 29) | 3956 | #define PIPEB_PP_ON_DELAYS 0x61308 |
| 3867 | #define PWM_POLARITY_ACTIVE_HIGH (0 << 29) | 3957 | #define PIPEB_PP_OFF_DELAYS 0x6130c |
| 3868 | #define PWM_POLARITY_ACTIVE_LOW2 (1 << 28) | 3958 | #define PIPEB_PP_DIVISOR 0x61310 |
| 3869 | #define PWM_POLARITY_ACTIVE_HIGH2 (0 << 28) | ||
| 3870 | |||
| 3871 | #define BLC_PWM_PCH_CTL2 0xc8254 | ||
| 3872 | 3959 | ||
| 3873 | #define PCH_PP_STATUS 0xc7200 | 3960 | #define PCH_PP_STATUS 0xc7200 |
| 3874 | #define PCH_PP_CONTROL 0xc7204 | 3961 | #define PCH_PP_CONTROL 0xc7204 |
| @@ -3992,6 +4079,7 @@ | |||
| 3992 | #define FORCEWAKE 0xA18C | 4079 | #define FORCEWAKE 0xA18C |
| 3993 | #define FORCEWAKE_VLV 0x1300b0 | 4080 | #define FORCEWAKE_VLV 0x1300b0 |
| 3994 | #define FORCEWAKE_ACK_VLV 0x1300b4 | 4081 | #define FORCEWAKE_ACK_VLV 0x1300b4 |
| 4082 | #define FORCEWAKE_ACK_HSW 0x130044 | ||
| 3995 | #define FORCEWAKE_ACK 0x130090 | 4083 | #define FORCEWAKE_ACK 0x130090 |
| 3996 | #define FORCEWAKE_MT 0xa188 /* multi-threaded */ | 4084 | #define FORCEWAKE_MT 0xa188 /* multi-threaded */ |
| 3997 | #define FORCEWAKE_MT_ACK 0x130040 | 4085 | #define FORCEWAKE_MT_ACK 0x130040 |
| @@ -4012,10 +4100,15 @@ | |||
| 4012 | # define GEN6_CSUNIT_CLOCK_GATE_DISABLE (1 << 7) | 4100 | # define GEN6_CSUNIT_CLOCK_GATE_DISABLE (1 << 7) |
| 4013 | 4101 | ||
| 4014 | #define GEN6_UCGCTL2 0x9404 | 4102 | #define GEN6_UCGCTL2 0x9404 |
| 4103 | # define GEN7_VDSUNIT_CLOCK_GATE_DISABLE (1 << 30) | ||
| 4104 | # define GEN7_TDLUNIT_CLOCK_GATE_DISABLE (1 << 22) | ||
| 4015 | # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) | 4105 | # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) |
| 4016 | # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) | 4106 | # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) |
| 4017 | # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) | 4107 | # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) |
| 4018 | 4108 | ||
| 4109 | #define GEN7_UCGCTL4 0x940c | ||
| 4110 | #define GEN7_L3BANK2X_CLOCK_GATE_DISABLE (1<<25) | ||
| 4111 | |||
| 4019 | #define GEN6_RPNSWREQ 0xA008 | 4112 | #define GEN6_RPNSWREQ 0xA008 |
| 4020 | #define GEN6_TURBO_DISABLE (1<<31) | 4113 | #define GEN6_TURBO_DISABLE (1<<31) |
| 4021 | #define GEN6_FREQUENCY(x) ((x)<<25) | 4114 | #define GEN6_FREQUENCY(x) ((x)<<25) |
| @@ -4047,6 +4140,7 @@ | |||
| 4047 | #define GEN6_RP_UP_IDLE_MIN (0x1<<3) | 4140 | #define GEN6_RP_UP_IDLE_MIN (0x1<<3) |
| 4048 | #define GEN6_RP_UP_BUSY_AVG (0x2<<3) | 4141 | #define GEN6_RP_UP_BUSY_AVG (0x2<<3) |
| 4049 | #define GEN6_RP_UP_BUSY_CONT (0x4<<3) | 4142 | #define GEN6_RP_UP_BUSY_CONT (0x4<<3) |
| 4143 | #define GEN7_RP_DOWN_IDLE_AVG (0x2<<0) | ||
| 4050 | #define GEN6_RP_DOWN_IDLE_CONT (0x1<<0) | 4144 | #define GEN6_RP_DOWN_IDLE_CONT (0x1<<0) |
| 4051 | #define GEN6_RP_UP_THRESHOLD 0xA02C | 4145 | #define GEN6_RP_UP_THRESHOLD 0xA02C |
| 4052 | #define GEN6_RP_DOWN_THRESHOLD 0xA030 | 4146 | #define GEN6_RP_DOWN_THRESHOLD 0xA030 |
| @@ -4111,6 +4205,26 @@ | |||
| 4111 | #define GEN6_RC6 3 | 4205 | #define GEN6_RC6 3 |
| 4112 | #define GEN6_RC7 4 | 4206 | #define GEN6_RC7 4 |
| 4113 | 4207 | ||
| 4208 | #define GEN7_MISCCPCTL (0x9424) | ||
| 4209 | #define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0) | ||
| 4210 | |||
| 4211 | /* IVYBRIDGE DPF */ | ||
| 4212 | #define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */ | ||
| 4213 | #define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14) | ||
| 4214 | #define GEN7_PARITY_ERROR_VALID (1<<13) | ||
| 4215 | #define GEN7_L3CDERRST1_BANK_MASK (3<<11) | ||
| 4216 | #define GEN7_L3CDERRST1_SUBBANK_MASK (7<<8) | ||
| 4217 | #define GEN7_PARITY_ERROR_ROW(reg) \ | ||
| 4218 | ((reg & GEN7_L3CDERRST1_ROW_MASK) >> 14) | ||
| 4219 | #define GEN7_PARITY_ERROR_BANK(reg) \ | ||
| 4220 | ((reg & GEN7_L3CDERRST1_BANK_MASK) >> 11) | ||
| 4221 | #define GEN7_PARITY_ERROR_SUBBANK(reg) \ | ||
| 4222 | ((reg & GEN7_L3CDERRST1_SUBBANK_MASK) >> 8) | ||
| 4223 | #define GEN7_L3CDERRST1_ENABLE (1<<7) | ||
| 4224 | |||
| 4225 | #define GEN7_L3LOG_BASE 0xB070 | ||
| 4226 | #define GEN7_L3LOG_SIZE 0x80 | ||
| 4227 | |||
| 4114 | #define G4X_AUD_VID_DID 0x62020 | 4228 | #define G4X_AUD_VID_DID 0x62020 |
| 4115 | #define INTEL_AUDIO_DEVCL 0x808629FB | 4229 | #define INTEL_AUDIO_DEVCL 0x808629FB |
| 4116 | #define INTEL_AUDIO_DEVBLC 0x80862801 | 4230 | #define INTEL_AUDIO_DEVBLC 0x80862801 |
| @@ -4177,7 +4291,7 @@ | |||
| 4177 | PIPE_DDI_FUNC_CTL_B) | 4291 | PIPE_DDI_FUNC_CTL_B) |
| 4178 | #define PIPE_DDI_FUNC_ENABLE (1<<31) | 4292 | #define PIPE_DDI_FUNC_ENABLE (1<<31) |
| 4179 | /* Those bits are ignored by pipe EDP since it can only connect to DDI A */ | 4293 | /* Those bits are ignored by pipe EDP since it can only connect to DDI A */ |
| 4180 | #define PIPE_DDI_PORT_MASK (0xf<<28) | 4294 | #define PIPE_DDI_PORT_MASK (7<<28) |
| 4181 | #define PIPE_DDI_SELECT_PORT(x) ((x)<<28) | 4295 | #define PIPE_DDI_SELECT_PORT(x) ((x)<<28) |
| 4182 | #define PIPE_DDI_MODE_SELECT_HDMI (0<<24) | 4296 | #define PIPE_DDI_MODE_SELECT_HDMI (0<<24) |
| 4183 | #define PIPE_DDI_MODE_SELECT_DVI (1<<24) | 4297 | #define PIPE_DDI_MODE_SELECT_DVI (1<<24) |
| @@ -4335,7 +4449,7 @@ | |||
| 4335 | #define PIPE_WM_LINETIME_B 0x45274 | 4449 | #define PIPE_WM_LINETIME_B 0x45274 |
| 4336 | #define PIPE_WM_LINETIME(pipe) _PIPE(pipe, \ | 4450 | #define PIPE_WM_LINETIME(pipe) _PIPE(pipe, \ |
| 4337 | PIPE_WM_LINETIME_A, \ | 4451 | PIPE_WM_LINETIME_A, \ |
| 4338 | PIPE_WM_LINETIME_A) | 4452 | PIPE_WM_LINETIME_B) |
| 4339 | #define PIPE_WM_LINETIME_MASK (0x1ff) | 4453 | #define PIPE_WM_LINETIME_MASK (0x1ff) |
| 4340 | #define PIPE_WM_LINETIME_TIME(x) ((x)) | 4454 | #define PIPE_WM_LINETIME_TIME(x) ((x)) |
| 4341 | #define PIPE_WM_LINETIME_IPS_LINETIME_MASK (0x1ff<<16) | 4455 | #define PIPE_WM_LINETIME_IPS_LINETIME_MASK (0x1ff<<16) |
| @@ -4347,4 +4461,9 @@ | |||
| 4347 | #define SFUSE_STRAP_DDIC_DETECTED (1<<1) | 4461 | #define SFUSE_STRAP_DDIC_DETECTED (1<<1) |
| 4348 | #define SFUSE_STRAP_DDID_DETECTED (1<<0) | 4462 | #define SFUSE_STRAP_DDID_DETECTED (1<<0) |
| 4349 | 4463 | ||
| 4464 | #define WM_DBG 0x45280 | ||
| 4465 | #define WM_DBG_DISALLOW_MULTIPLE_LP (1<<0) | ||
| 4466 | #define WM_DBG_DISALLOW_MAXFIFO (1<<1) | ||
| 4467 | #define WM_DBG_DISALLOW_SPRITE (1<<2) | ||
| 4468 | |||
| 4350 | #endif /* _I915_REG_H_ */ | 4469 | #endif /* _I915_REG_H_ */ |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index a748e5cabe14..4776ccf1b3cd 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
| @@ -828,10 +828,7 @@ int i915_save_state(struct drm_device *dev) | |||
| 828 | dev_priv->saveIMR = I915_READ(IMR); | 828 | dev_priv->saveIMR = I915_READ(IMR); |
| 829 | } | 829 | } |
| 830 | 830 | ||
| 831 | if (IS_IRONLAKE_M(dev)) | 831 | intel_disable_gt_powersave(dev); |
| 832 | ironlake_disable_drps(dev); | ||
| 833 | if (INTEL_INFO(dev)->gen >= 6) | ||
| 834 | gen6_disable_rps(dev); | ||
| 835 | 832 | ||
| 836 | /* Cache mode state */ | 833 | /* Cache mode state */ |
| 837 | dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); | 834 | dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); |
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 79f83445afa0..2f5388af8df9 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 30 | #include <linux/stat.h> | 30 | #include <linux/stat.h> |
| 31 | #include <linux/sysfs.h> | 31 | #include <linux/sysfs.h> |
| 32 | #include "intel_drv.h" | ||
| 32 | #include "i915_drv.h" | 33 | #include "i915_drv.h" |
| 33 | 34 | ||
| 34 | static u32 calc_residency(struct drm_device *dev, const u32 reg) | 35 | static u32 calc_residency(struct drm_device *dev, const u32 reg) |
| @@ -92,20 +93,134 @@ static struct attribute_group rc6_attr_group = { | |||
| 92 | .attrs = rc6_attrs | 93 | .attrs = rc6_attrs |
| 93 | }; | 94 | }; |
| 94 | 95 | ||
| 95 | void i915_setup_sysfs(struct drm_device *dev) | 96 | static int l3_access_valid(struct drm_device *dev, loff_t offset) |
| 97 | { | ||
| 98 | if (!IS_IVYBRIDGE(dev)) | ||
| 99 | return -EPERM; | ||
| 100 | |||
| 101 | if (offset % 4 != 0) | ||
| 102 | return -EINVAL; | ||
| 103 | |||
| 104 | if (offset >= GEN7_L3LOG_SIZE) | ||
| 105 | return -ENXIO; | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static ssize_t | ||
| 111 | i915_l3_read(struct file *filp, struct kobject *kobj, | ||
| 112 | struct bin_attribute *attr, char *buf, | ||
| 113 | loff_t offset, size_t count) | ||
| 114 | { | ||
| 115 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 116 | struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); | ||
| 117 | struct drm_device *drm_dev = dminor->dev; | ||
| 118 | struct drm_i915_private *dev_priv = drm_dev->dev_private; | ||
| 119 | uint32_t misccpctl; | ||
| 120 | int i, ret; | ||
| 121 | |||
| 122 | ret = l3_access_valid(drm_dev, offset); | ||
| 123 | if (ret) | ||
| 124 | return ret; | ||
| 125 | |||
| 126 | ret = i915_mutex_lock_interruptible(drm_dev); | ||
| 127 | if (ret) | ||
| 128 | return ret; | ||
| 129 | |||
| 130 | misccpctl = I915_READ(GEN7_MISCCPCTL); | ||
| 131 | I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); | ||
| 132 | |||
| 133 | for (i = offset; count >= 4 && i < GEN7_L3LOG_SIZE; i += 4, count -= 4) | ||
| 134 | *((uint32_t *)(&buf[i])) = I915_READ(GEN7_L3LOG_BASE + i); | ||
| 135 | |||
| 136 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); | ||
| 137 | |||
| 138 | mutex_unlock(&drm_dev->struct_mutex); | ||
| 139 | |||
| 140 | return i - offset; | ||
| 141 | } | ||
| 142 | |||
| 143 | static ssize_t | ||
| 144 | i915_l3_write(struct file *filp, struct kobject *kobj, | ||
| 145 | struct bin_attribute *attr, char *buf, | ||
| 146 | loff_t offset, size_t count) | ||
| 96 | { | 147 | { |
| 148 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 149 | struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); | ||
| 150 | struct drm_device *drm_dev = dminor->dev; | ||
| 151 | struct drm_i915_private *dev_priv = drm_dev->dev_private; | ||
| 152 | u32 *temp = NULL; /* Just here to make handling failures easy */ | ||
| 97 | int ret; | 153 | int ret; |
| 98 | 154 | ||
| 99 | /* ILK doesn't have any residency information */ | 155 | ret = l3_access_valid(drm_dev, offset); |
| 100 | if (INTEL_INFO(dev)->gen < 6) | 156 | if (ret) |
| 101 | return; | 157 | return ret; |
| 102 | 158 | ||
| 103 | ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group); | 159 | ret = i915_mutex_lock_interruptible(drm_dev); |
| 104 | if (ret) | 160 | if (ret) |
| 105 | DRM_ERROR("sysfs setup failed\n"); | 161 | return ret; |
| 162 | |||
| 163 | if (!dev_priv->mm.l3_remap_info) { | ||
| 164 | temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL); | ||
| 165 | if (!temp) { | ||
| 166 | mutex_unlock(&drm_dev->struct_mutex); | ||
| 167 | return -ENOMEM; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | ret = i915_gpu_idle(drm_dev); | ||
| 172 | if (ret) { | ||
| 173 | kfree(temp); | ||
| 174 | mutex_unlock(&drm_dev->struct_mutex); | ||
| 175 | return ret; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* TODO: Ideally we really want a GPU reset here to make sure errors | ||
| 179 | * aren't propagated. Since I cannot find a stable way to reset the GPU | ||
| 180 | * at this point it is left as a TODO. | ||
| 181 | */ | ||
| 182 | if (temp) | ||
| 183 | dev_priv->mm.l3_remap_info = temp; | ||
| 184 | |||
| 185 | memcpy(dev_priv->mm.l3_remap_info + (offset/4), | ||
| 186 | buf + (offset/4), | ||
| 187 | count); | ||
| 188 | |||
| 189 | i915_gem_l3_remap(drm_dev); | ||
| 190 | |||
| 191 | mutex_unlock(&drm_dev->struct_mutex); | ||
| 192 | |||
| 193 | return count; | ||
| 194 | } | ||
| 195 | |||
| 196 | static struct bin_attribute dpf_attrs = { | ||
| 197 | .attr = {.name = "l3_parity", .mode = (S_IRUSR | S_IWUSR)}, | ||
| 198 | .size = GEN7_L3LOG_SIZE, | ||
| 199 | .read = i915_l3_read, | ||
| 200 | .write = i915_l3_write, | ||
| 201 | .mmap = NULL | ||
| 202 | }; | ||
| 203 | |||
| 204 | void i915_setup_sysfs(struct drm_device *dev) | ||
| 205 | { | ||
| 206 | int ret; | ||
| 207 | |||
| 208 | if (INTEL_INFO(dev)->gen >= 6) { | ||
| 209 | ret = sysfs_merge_group(&dev->primary->kdev.kobj, | ||
| 210 | &rc6_attr_group); | ||
| 211 | if (ret) | ||
| 212 | DRM_ERROR("RC6 residency sysfs setup failed\n"); | ||
| 213 | } | ||
| 214 | |||
| 215 | if (IS_IVYBRIDGE(dev)) { | ||
| 216 | ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs); | ||
| 217 | if (ret) | ||
| 218 | DRM_ERROR("l3 parity sysfs setup failed\n"); | ||
| 219 | } | ||
| 106 | } | 220 | } |
| 107 | 221 | ||
| 108 | void i915_teardown_sysfs(struct drm_device *dev) | 222 | void i915_teardown_sysfs(struct drm_device *dev) |
| 109 | { | 223 | { |
| 224 | device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); | ||
| 110 | sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); | 225 | sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); |
| 111 | } | 226 | } |
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index dac7bba4d9da..fe90b3a84a6d 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h | |||
| @@ -311,9 +311,33 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_retire, | |||
| 311 | TP_ARGS(ring, seqno) | 311 | TP_ARGS(ring, seqno) |
| 312 | ); | 312 | ); |
| 313 | 313 | ||
| 314 | DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_begin, | 314 | TRACE_EVENT(i915_gem_request_wait_begin, |
| 315 | TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), | 315 | TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), |
| 316 | TP_ARGS(ring, seqno) | 316 | TP_ARGS(ring, seqno), |
| 317 | |||
| 318 | TP_STRUCT__entry( | ||
| 319 | __field(u32, dev) | ||
| 320 | __field(u32, ring) | ||
| 321 | __field(u32, seqno) | ||
| 322 | __field(bool, blocking) | ||
| 323 | ), | ||
| 324 | |||
| 325 | /* NB: the blocking information is racy since mutex_is_locked | ||
| 326 | * doesn't check that the current thread holds the lock. The only | ||
| 327 | * other option would be to pass the boolean information of whether | ||
| 328 | * or not the class was blocking down through the stack which is | ||
| 329 | * less desirable. | ||
| 330 | */ | ||
| 331 | TP_fast_assign( | ||
| 332 | __entry->dev = ring->dev->primary->index; | ||
| 333 | __entry->ring = ring->id; | ||
| 334 | __entry->seqno = seqno; | ||
| 335 | __entry->blocking = mutex_is_locked(&ring->dev->struct_mutex); | ||
| 336 | ), | ||
| 337 | |||
| 338 | TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s", | ||
| 339 | __entry->dev, __entry->ring, __entry->seqno, | ||
| 340 | __entry->blocking ? "yes (NB)" : "no") | ||
| 317 | ); | 341 | ); |
| 318 | 342 | ||
| 319 | DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end, | 343 | DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end, |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 353459362f6f..8c6074154bf6 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
| @@ -692,7 +692,7 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = { | |||
| 692 | * | 692 | * |
| 693 | * Returns 0 on success, nonzero on failure. | 693 | * Returns 0 on success, nonzero on failure. |
| 694 | */ | 694 | */ |
| 695 | bool | 695 | int |
| 696 | intel_parse_bios(struct drm_device *dev) | 696 | intel_parse_bios(struct drm_device *dev) |
| 697 | { | 697 | { |
| 698 | struct drm_i915_private *dev_priv = dev->dev_private; | 698 | struct drm_i915_private *dev_priv = dev->dev_private; |
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index dbda6e3bdf07..31c2107e7825 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h | |||
| @@ -476,7 +476,7 @@ struct bdb_edp { | |||
| 476 | } __attribute__ ((packed)); | 476 | } __attribute__ ((packed)); |
| 477 | 477 | ||
| 478 | void intel_setup_bios(struct drm_device *dev); | 478 | void intel_setup_bios(struct drm_device *dev); |
| 479 | bool intel_parse_bios(struct drm_device *dev); | 479 | int intel_parse_bios(struct drm_device *dev); |
| 480 | 480 | ||
| 481 | /* | 481 | /* |
| 482 | * Driver<->VBIOS interaction occurs through scratch bits in | 482 | * Driver<->VBIOS interaction occurs through scratch bits in |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 75a70c46ef1b..7ed4a41c3965 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
| @@ -88,6 +88,9 @@ static void gmch_crt_dpms(struct drm_encoder *encoder, int mode) | |||
| 88 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); | 88 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); |
| 89 | temp &= ~ADPA_DAC_ENABLE; | 89 | temp &= ~ADPA_DAC_ENABLE; |
| 90 | 90 | ||
| 91 | if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON) | ||
| 92 | mode = DRM_MODE_DPMS_OFF; | ||
| 93 | |||
| 91 | switch (mode) { | 94 | switch (mode) { |
| 92 | case DRM_MODE_DPMS_ON: | 95 | case DRM_MODE_DPMS_ON: |
| 93 | temp |= ADPA_DAC_ENABLE; | 96 | temp |= ADPA_DAC_ENABLE; |
| @@ -129,7 +132,7 @@ static int intel_crt_mode_valid(struct drm_connector *connector, | |||
| 129 | } | 132 | } |
| 130 | 133 | ||
| 131 | static bool intel_crt_mode_fixup(struct drm_encoder *encoder, | 134 | static bool intel_crt_mode_fixup(struct drm_encoder *encoder, |
| 132 | struct drm_display_mode *mode, | 135 | const struct drm_display_mode *mode, |
| 133 | struct drm_display_mode *adjusted_mode) | 136 | struct drm_display_mode *adjusted_mode) |
| 134 | { | 137 | { |
| 135 | return true; | 138 | return true; |
| @@ -230,6 +233,42 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) | |||
| 230 | return ret; | 233 | return ret; |
| 231 | } | 234 | } |
| 232 | 235 | ||
| 236 | static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) | ||
| 237 | { | ||
| 238 | struct drm_device *dev = connector->dev; | ||
| 239 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 240 | u32 adpa; | ||
| 241 | bool ret; | ||
| 242 | u32 save_adpa; | ||
| 243 | |||
| 244 | save_adpa = adpa = I915_READ(ADPA); | ||
| 245 | DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa); | ||
| 246 | |||
| 247 | adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER; | ||
| 248 | |||
| 249 | I915_WRITE(ADPA, adpa); | ||
| 250 | |||
| 251 | if (wait_for((I915_READ(ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, | ||
| 252 | 1000)) { | ||
| 253 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); | ||
| 254 | I915_WRITE(ADPA, save_adpa); | ||
| 255 | } | ||
| 256 | |||
| 257 | /* Check the status to see if both blue and green are on now */ | ||
| 258 | adpa = I915_READ(ADPA); | ||
| 259 | if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0) | ||
| 260 | ret = true; | ||
| 261 | else | ||
| 262 | ret = false; | ||
| 263 | |||
| 264 | DRM_DEBUG_KMS("valleyview hotplug adpa=0x%x, result %d\n", adpa, ret); | ||
| 265 | |||
| 266 | /* FIXME: debug force function and remove */ | ||
| 267 | ret = true; | ||
| 268 | |||
| 269 | return ret; | ||
| 270 | } | ||
| 271 | |||
| 233 | /** | 272 | /** |
| 234 | * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. | 273 | * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. |
| 235 | * | 274 | * |
| @@ -249,6 +288,9 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
| 249 | if (HAS_PCH_SPLIT(dev)) | 288 | if (HAS_PCH_SPLIT(dev)) |
| 250 | return intel_ironlake_crt_detect_hotplug(connector); | 289 | return intel_ironlake_crt_detect_hotplug(connector); |
| 251 | 290 | ||
| 291 | if (IS_VALLEYVIEW(dev)) | ||
| 292 | return valleyview_crt_detect_hotplug(connector); | ||
| 293 | |||
| 252 | /* | 294 | /* |
| 253 | * On 4 series desktop, CRT detect sequence need to be done twice | 295 | * On 4 series desktop, CRT detect sequence need to be done twice |
| 254 | * to get a reliable result. | 296 | * to get a reliable result. |
| @@ -288,39 +330,34 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector) | |||
| 288 | { | 330 | { |
| 289 | struct intel_crt *crt = intel_attached_crt(connector); | 331 | struct intel_crt *crt = intel_attached_crt(connector); |
| 290 | struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private; | 332 | struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private; |
| 333 | struct edid *edid; | ||
| 334 | struct i2c_adapter *i2c; | ||
| 291 | 335 | ||
| 292 | /* CRT should always be at 0, but check anyway */ | 336 | BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG); |
| 293 | if (crt->base.type != INTEL_OUTPUT_ANALOG) | 337 | |
| 294 | return false; | 338 | i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); |
| 339 | edid = drm_get_edid(connector, i2c); | ||
| 295 | 340 | ||
| 296 | if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) { | 341 | if (edid) { |
| 297 | struct edid *edid; | 342 | bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL; |
| 298 | bool is_digital = false; | ||
| 299 | struct i2c_adapter *i2c; | ||
| 300 | 343 | ||
| 301 | i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); | ||
| 302 | edid = drm_get_edid(connector, i2c); | ||
| 303 | /* | 344 | /* |
| 304 | * This may be a DVI-I connector with a shared DDC | 345 | * This may be a DVI-I connector with a shared DDC |
| 305 | * link between analog and digital outputs, so we | 346 | * link between analog and digital outputs, so we |
| 306 | * have to check the EDID input spec of the attached device. | 347 | * have to check the EDID input spec of the attached device. |
| 307 | * | ||
| 308 | * On the other hand, what should we do if it is a broken EDID? | ||
| 309 | */ | 348 | */ |
| 310 | if (edid != NULL) { | ||
| 311 | is_digital = edid->input & DRM_EDID_INPUT_DIGITAL; | ||
| 312 | connector->display_info.raw_edid = NULL; | ||
| 313 | kfree(edid); | ||
| 314 | } | ||
| 315 | |||
| 316 | if (!is_digital) { | 349 | if (!is_digital) { |
| 317 | DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n"); | 350 | DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n"); |
| 318 | return true; | 351 | return true; |
| 319 | } else { | ||
| 320 | DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n"); | ||
| 321 | } | 352 | } |
| 353 | |||
| 354 | DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n"); | ||
| 355 | } else { | ||
| 356 | DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [no valid EDID found]\n"); | ||
| 322 | } | 357 | } |
| 323 | 358 | ||
| 359 | kfree(edid); | ||
| 360 | |||
| 324 | return false; | 361 | return false; |
| 325 | } | 362 | } |
| 326 | 363 | ||
| @@ -453,18 +490,27 @@ intel_crt_detect(struct drm_connector *connector, bool force) | |||
| 453 | struct intel_load_detect_pipe tmp; | 490 | struct intel_load_detect_pipe tmp; |
| 454 | 491 | ||
| 455 | if (I915_HAS_HOTPLUG(dev)) { | 492 | if (I915_HAS_HOTPLUG(dev)) { |
| 493 | /* We can not rely on the HPD pin always being correctly wired | ||
| 494 | * up, for example many KVM do not pass it through, and so | ||
| 495 | * only trust an assertion that the monitor is connected. | ||
| 496 | */ | ||
| 456 | if (intel_crt_detect_hotplug(connector)) { | 497 | if (intel_crt_detect_hotplug(connector)) { |
| 457 | DRM_DEBUG_KMS("CRT detected via hotplug\n"); | 498 | DRM_DEBUG_KMS("CRT detected via hotplug\n"); |
| 458 | return connector_status_connected; | 499 | return connector_status_connected; |
| 459 | } else { | 500 | } else |
| 460 | DRM_DEBUG_KMS("CRT not detected via hotplug\n"); | 501 | DRM_DEBUG_KMS("CRT not detected via hotplug\n"); |
| 461 | return connector_status_disconnected; | ||
| 462 | } | ||
| 463 | } | 502 | } |
| 464 | 503 | ||
| 465 | if (intel_crt_detect_ddc(connector)) | 504 | if (intel_crt_detect_ddc(connector)) |
| 466 | return connector_status_connected; | 505 | return connector_status_connected; |
| 467 | 506 | ||
| 507 | /* Load detection is broken on HPD capable machines. Whoever wants a | ||
| 508 | * broken monitor (without edid) to work behind a broken kvm (that fails | ||
| 509 | * to have the right resistors for HP detection) needs to fix this up. | ||
| 510 | * For now just bail out. */ | ||
| 511 | if (I915_HAS_HOTPLUG(dev)) | ||
| 512 | return connector_status_disconnected; | ||
| 513 | |||
| 468 | if (!force) | 514 | if (!force) |
| 469 | return connector->status; | 515 | return connector->status; |
| 470 | 516 | ||
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 46d1e886c692..933c74859172 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
| @@ -170,6 +170,15 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) | |||
| 170 | 170 | ||
| 171 | udelay(600); | 171 | udelay(600); |
| 172 | 172 | ||
| 173 | /* We need to program FDI_RX_MISC with the default TP1 to TP2 | ||
| 174 | * values before enabling the receiver, and configure the delay | ||
| 175 | * for the FDI timing generator to 90h. Luckily, all the other | ||
| 176 | * bits are supposed to be zeroed, so we can write those values | ||
| 177 | * directly. | ||
| 178 | */ | ||
| 179 | I915_WRITE(FDI_RX_MISC(pipe), FDI_RX_TP1_TO_TP2_48 | | ||
| 180 | FDI_RX_FDI_DELAY_90); | ||
| 181 | |||
| 173 | /* Enable CPU FDI Receiver with auto-training */ | 182 | /* Enable CPU FDI Receiver with auto-training */ |
| 174 | reg = FDI_RX_CTL(pipe); | 183 | reg = FDI_RX_CTL(pipe); |
| 175 | I915_WRITE(reg, | 184 | I915_WRITE(reg, |
| @@ -726,8 +735,7 @@ void intel_ddi_mode_set(struct drm_encoder *encoder, | |||
| 726 | 735 | ||
| 727 | I915_WRITE(DDI_FUNC_CTL(pipe), temp); | 736 | I915_WRITE(DDI_FUNC_CTL(pipe), temp); |
| 728 | 737 | ||
| 729 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | 738 | intel_hdmi->set_infoframes(encoder, adjusted_mode); |
| 730 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 731 | } | 739 | } |
| 732 | 740 | ||
| 733 | void intel_ddi_dpms(struct drm_encoder *encoder, int mode) | 741 | void intel_ddi_dpms(struct drm_encoder *encoder, int mode) |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a8538ac0299d..f6159765f1eb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -98,6 +98,11 @@ intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, | |||
| 98 | int target, int refclk, intel_clock_t *match_clock, | 98 | int target, int refclk, intel_clock_t *match_clock, |
| 99 | intel_clock_t *best_clock); | 99 | intel_clock_t *best_clock); |
| 100 | 100 | ||
| 101 | static bool | ||
| 102 | intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
| 103 | int target, int refclk, intel_clock_t *match_clock, | ||
| 104 | intel_clock_t *best_clock); | ||
| 105 | |||
| 101 | static inline u32 /* units of 100MHz */ | 106 | static inline u32 /* units of 100MHz */ |
| 102 | intel_fdi_link_freq(struct drm_device *dev) | 107 | intel_fdi_link_freq(struct drm_device *dev) |
| 103 | { | 108 | { |
| @@ -359,6 +364,48 @@ static const intel_limit_t intel_limits_ironlake_display_port = { | |||
| 359 | .find_pll = intel_find_pll_ironlake_dp, | 364 | .find_pll = intel_find_pll_ironlake_dp, |
| 360 | }; | 365 | }; |
| 361 | 366 | ||
| 367 | static const intel_limit_t intel_limits_vlv_dac = { | ||
| 368 | .dot = { .min = 25000, .max = 270000 }, | ||
| 369 | .vco = { .min = 4000000, .max = 6000000 }, | ||
| 370 | .n = { .min = 1, .max = 7 }, | ||
| 371 | .m = { .min = 22, .max = 450 }, /* guess */ | ||
| 372 | .m1 = { .min = 2, .max = 3 }, | ||
| 373 | .m2 = { .min = 11, .max = 156 }, | ||
| 374 | .p = { .min = 10, .max = 30 }, | ||
| 375 | .p1 = { .min = 2, .max = 3 }, | ||
| 376 | .p2 = { .dot_limit = 270000, | ||
| 377 | .p2_slow = 2, .p2_fast = 20 }, | ||
| 378 | .find_pll = intel_vlv_find_best_pll, | ||
| 379 | }; | ||
| 380 | |||
| 381 | static const intel_limit_t intel_limits_vlv_hdmi = { | ||
| 382 | .dot = { .min = 20000, .max = 165000 }, | ||
| 383 | .vco = { .min = 5994000, .max = 4000000 }, | ||
| 384 | .n = { .min = 1, .max = 7 }, | ||
| 385 | .m = { .min = 60, .max = 300 }, /* guess */ | ||
| 386 | .m1 = { .min = 2, .max = 3 }, | ||
| 387 | .m2 = { .min = 11, .max = 156 }, | ||
| 388 | .p = { .min = 10, .max = 30 }, | ||
| 389 | .p1 = { .min = 2, .max = 3 }, | ||
| 390 | .p2 = { .dot_limit = 270000, | ||
| 391 | .p2_slow = 2, .p2_fast = 20 }, | ||
| 392 | .find_pll = intel_vlv_find_best_pll, | ||
| 393 | }; | ||
| 394 | |||
| 395 | static const intel_limit_t intel_limits_vlv_dp = { | ||
| 396 | .dot = { .min = 162000, .max = 270000 }, | ||
| 397 | .vco = { .min = 5994000, .max = 4000000 }, | ||
| 398 | .n = { .min = 1, .max = 7 }, | ||
| 399 | .m = { .min = 60, .max = 300 }, /* guess */ | ||
| 400 | .m1 = { .min = 2, .max = 3 }, | ||
| 401 | .m2 = { .min = 11, .max = 156 }, | ||
| 402 | .p = { .min = 10, .max = 30 }, | ||
| 403 | .p1 = { .min = 2, .max = 3 }, | ||
| 404 | .p2 = { .dot_limit = 270000, | ||
| 405 | .p2_slow = 2, .p2_fast = 20 }, | ||
| 406 | .find_pll = intel_vlv_find_best_pll, | ||
| 407 | }; | ||
| 408 | |||
| 362 | u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg) | 409 | u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg) |
| 363 | { | 410 | { |
| 364 | unsigned long flags; | 411 | unsigned long flags; |
| @@ -384,6 +431,28 @@ out_unlock: | |||
| 384 | return val; | 431 | return val; |
| 385 | } | 432 | } |
| 386 | 433 | ||
| 434 | static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg, | ||
| 435 | u32 val) | ||
| 436 | { | ||
| 437 | unsigned long flags; | ||
| 438 | |||
| 439 | spin_lock_irqsave(&dev_priv->dpio_lock, flags); | ||
| 440 | if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) { | ||
| 441 | DRM_ERROR("DPIO idle wait timed out\n"); | ||
| 442 | goto out_unlock; | ||
| 443 | } | ||
| 444 | |||
| 445 | I915_WRITE(DPIO_DATA, val); | ||
| 446 | I915_WRITE(DPIO_REG, reg); | ||
| 447 | I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_WRITE | DPIO_PORTID | | ||
| 448 | DPIO_BYTE); | ||
| 449 | if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) | ||
| 450 | DRM_ERROR("DPIO write wait timed out\n"); | ||
| 451 | |||
| 452 | out_unlock: | ||
| 453 | spin_unlock_irqrestore(&dev_priv->dpio_lock, flags); | ||
| 454 | } | ||
| 455 | |||
| 387 | static void vlv_init_dpio(struct drm_device *dev) | 456 | static void vlv_init_dpio(struct drm_device *dev) |
| 388 | { | 457 | { |
| 389 | struct drm_i915_private *dev_priv = dev->dev_private; | 458 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -434,7 +503,7 @@ static bool is_dual_link_lvds(struct drm_i915_private *dev_priv, | |||
| 434 | * register is uninitialized. | 503 | * register is uninitialized. |
| 435 | */ | 504 | */ |
| 436 | val = I915_READ(reg); | 505 | val = I915_READ(reg); |
| 437 | if (!(val & ~LVDS_DETECTED)) | 506 | if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED))) |
| 438 | val = dev_priv->bios_lvds_val; | 507 | val = dev_priv->bios_lvds_val; |
| 439 | dev_priv->lvds_val = val; | 508 | dev_priv->lvds_val = val; |
| 440 | } | 509 | } |
| @@ -510,6 +579,13 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk) | |||
| 510 | limit = &intel_limits_pineview_lvds; | 579 | limit = &intel_limits_pineview_lvds; |
| 511 | else | 580 | else |
| 512 | limit = &intel_limits_pineview_sdvo; | 581 | limit = &intel_limits_pineview_sdvo; |
| 582 | } else if (IS_VALLEYVIEW(dev)) { | ||
| 583 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) | ||
| 584 | limit = &intel_limits_vlv_dac; | ||
| 585 | else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) | ||
| 586 | limit = &intel_limits_vlv_hdmi; | ||
| 587 | else | ||
| 588 | limit = &intel_limits_vlv_dp; | ||
| 513 | } else if (!IS_GEN2(dev)) { | 589 | } else if (!IS_GEN2(dev)) { |
| 514 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 590 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
| 515 | limit = &intel_limits_i9xx_lvds; | 591 | limit = &intel_limits_i9xx_lvds; |
| @@ -551,11 +627,10 @@ static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock | |||
| 551 | bool intel_pipe_has_type(struct drm_crtc *crtc, int type) | 627 | bool intel_pipe_has_type(struct drm_crtc *crtc, int type) |
| 552 | { | 628 | { |
| 553 | struct drm_device *dev = crtc->dev; | 629 | struct drm_device *dev = crtc->dev; |
| 554 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 555 | struct intel_encoder *encoder; | 630 | struct intel_encoder *encoder; |
| 556 | 631 | ||
| 557 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) | 632 | for_each_encoder_on_crtc(dev, crtc, encoder) |
| 558 | if (encoder->base.crtc == crtc && encoder->type == type) | 633 | if (encoder->type == type) |
| 559 | return true; | 634 | return true; |
| 560 | 635 | ||
| 561 | return false; | 636 | return false; |
| @@ -783,6 +858,73 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
| 783 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); | 858 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); |
| 784 | return true; | 859 | return true; |
| 785 | } | 860 | } |
| 861 | static bool | ||
| 862 | intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
| 863 | int target, int refclk, intel_clock_t *match_clock, | ||
| 864 | intel_clock_t *best_clock) | ||
| 865 | { | ||
| 866 | u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2; | ||
| 867 | u32 m, n, fastclk; | ||
| 868 | u32 updrate, minupdate, fracbits, p; | ||
| 869 | unsigned long bestppm, ppm, absppm; | ||
| 870 | int dotclk, flag; | ||
| 871 | |||
| 872 | dotclk = target * 1000; | ||
| 873 | bestppm = 1000000; | ||
| 874 | ppm = absppm = 0; | ||
| 875 | fastclk = dotclk / (2*100); | ||
| 876 | updrate = 0; | ||
| 877 | minupdate = 19200; | ||
| 878 | fracbits = 1; | ||
| 879 | n = p = p1 = p2 = m = m1 = m2 = vco = bestn = 0; | ||
| 880 | bestm1 = bestm2 = bestp1 = bestp2 = 0; | ||
| 881 | |||
| 882 | /* based on hardware requirement, prefer smaller n to precision */ | ||
| 883 | for (n = limit->n.min; n <= ((refclk) / minupdate); n++) { | ||
| 884 | updrate = refclk / n; | ||
| 885 | for (p1 = limit->p1.max; p1 > limit->p1.min; p1--) { | ||
| 886 | for (p2 = limit->p2.p2_fast+1; p2 > 0; p2--) { | ||
| 887 | if (p2 > 10) | ||
| 888 | p2 = p2 - 1; | ||
| 889 | p = p1 * p2; | ||
| 890 | /* based on hardware requirement, prefer bigger m1,m2 values */ | ||
| 891 | for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) { | ||
| 892 | m2 = (((2*(fastclk * p * n / m1 )) + | ||
| 893 | refclk) / (2*refclk)); | ||
| 894 | m = m1 * m2; | ||
| 895 | vco = updrate * m; | ||
| 896 | if (vco >= limit->vco.min && vco < limit->vco.max) { | ||
| 897 | ppm = 1000000 * ((vco / p) - fastclk) / fastclk; | ||
| 898 | absppm = (ppm > 0) ? ppm : (-ppm); | ||
| 899 | if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) { | ||
| 900 | bestppm = 0; | ||
| 901 | flag = 1; | ||
| 902 | } | ||
| 903 | if (absppm < bestppm - 10) { | ||
| 904 | bestppm = absppm; | ||
| 905 | flag = 1; | ||
| 906 | } | ||
| 907 | if (flag) { | ||
| 908 | bestn = n; | ||
| 909 | bestm1 = m1; | ||
| 910 | bestm2 = m2; | ||
| 911 | bestp1 = p1; | ||
| 912 | bestp2 = p2; | ||
| 913 | flag = 0; | ||
| 914 | } | ||
| 915 | } | ||
| 916 | } | ||
| 917 | } | ||
| 918 | } | ||
| 919 | } | ||
| 920 | best_clock->n = bestn; | ||
| 921 | best_clock->m1 = bestm1; | ||
| 922 | best_clock->m2 = bestm2; | ||
| 923 | best_clock->p1 = bestp1; | ||
| 924 | best_clock->p2 = bestp2; | ||
| 925 | |||
| 926 | return true; | ||
| 927 | } | ||
| 786 | 928 | ||
| 787 | static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe) | 929 | static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe) |
| 788 | { | 930 | { |
| @@ -1232,6 +1374,9 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, | |||
| 1232 | WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), | 1374 | WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), |
| 1233 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", | 1375 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", |
| 1234 | reg, pipe_name(pipe)); | 1376 | reg, pipe_name(pipe)); |
| 1377 | |||
| 1378 | WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), | ||
| 1379 | "IBX PCH dp port still using transcoder B\n"); | ||
| 1235 | } | 1380 | } |
| 1236 | 1381 | ||
| 1237 | static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, | 1382 | static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, |
| @@ -1241,6 +1386,9 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, | |||
| 1241 | WARN(hdmi_pipe_enabled(dev_priv, val, pipe), | 1386 | WARN(hdmi_pipe_enabled(dev_priv, val, pipe), |
| 1242 | "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", | 1387 | "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", |
| 1243 | reg, pipe_name(pipe)); | 1388 | reg, pipe_name(pipe)); |
| 1389 | |||
| 1390 | WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), | ||
| 1391 | "IBX PCH hdmi port still using transcoder B\n"); | ||
| 1244 | } | 1392 | } |
| 1245 | 1393 | ||
| 1246 | static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, | 1394 | static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, |
| @@ -1287,7 +1435,7 @@ static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) | |||
| 1287 | u32 val; | 1435 | u32 val; |
| 1288 | 1436 | ||
| 1289 | /* No really, not for ILK+ */ | 1437 | /* No really, not for ILK+ */ |
| 1290 | BUG_ON(dev_priv->info->gen >= 5); | 1438 | BUG_ON(!IS_VALLEYVIEW(dev_priv->dev) && dev_priv->info->gen >= 5); |
| 1291 | 1439 | ||
| 1292 | /* PLL is protected by panel, make sure we can write it */ | 1440 | /* PLL is protected by panel, make sure we can write it */ |
| 1293 | if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev)) | 1441 | if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev)) |
| @@ -1344,7 +1492,7 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value) | |||
| 1344 | unsigned long flags; | 1492 | unsigned long flags; |
| 1345 | 1493 | ||
| 1346 | spin_lock_irqsave(&dev_priv->dpio_lock, flags); | 1494 | spin_lock_irqsave(&dev_priv->dpio_lock, flags); |
| 1347 | if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0, | 1495 | if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, |
| 1348 | 100)) { | 1496 | 100)) { |
| 1349 | DRM_ERROR("timeout waiting for SBI to become ready\n"); | 1497 | DRM_ERROR("timeout waiting for SBI to become ready\n"); |
| 1350 | goto out_unlock; | 1498 | goto out_unlock; |
| @@ -1358,7 +1506,7 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value) | |||
| 1358 | SBI_BUSY | | 1506 | SBI_BUSY | |
| 1359 | SBI_CTL_OP_CRWR); | 1507 | SBI_CTL_OP_CRWR); |
| 1360 | 1508 | ||
| 1361 | if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0, | 1509 | if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0, |
| 1362 | 100)) { | 1510 | 100)) { |
| 1363 | DRM_ERROR("timeout waiting for SBI to complete write transaction\n"); | 1511 | DRM_ERROR("timeout waiting for SBI to complete write transaction\n"); |
| 1364 | goto out_unlock; | 1512 | goto out_unlock; |
| @@ -1372,10 +1520,10 @@ static u32 | |||
| 1372 | intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg) | 1520 | intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg) |
| 1373 | { | 1521 | { |
| 1374 | unsigned long flags; | 1522 | unsigned long flags; |
| 1375 | u32 value; | 1523 | u32 value = 0; |
| 1376 | 1524 | ||
| 1377 | spin_lock_irqsave(&dev_priv->dpio_lock, flags); | 1525 | spin_lock_irqsave(&dev_priv->dpio_lock, flags); |
| 1378 | if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0, | 1526 | if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, |
| 1379 | 100)) { | 1527 | 100)) { |
| 1380 | DRM_ERROR("timeout waiting for SBI to become ready\n"); | 1528 | DRM_ERROR("timeout waiting for SBI to become ready\n"); |
| 1381 | goto out_unlock; | 1529 | goto out_unlock; |
| @@ -1387,7 +1535,7 @@ intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg) | |||
| 1387 | SBI_BUSY | | 1535 | SBI_BUSY | |
| 1388 | SBI_CTL_OP_CRRD); | 1536 | SBI_CTL_OP_CRRD); |
| 1389 | 1537 | ||
| 1390 | if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0, | 1538 | if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0, |
| 1391 | 100)) { | 1539 | 100)) { |
| 1392 | DRM_ERROR("timeout waiting for SBI to complete read transaction\n"); | 1540 | DRM_ERROR("timeout waiting for SBI to complete read transaction\n"); |
| 1393 | goto out_unlock; | 1541 | goto out_unlock; |
| @@ -1824,6 +1972,22 @@ void intel_unpin_fb_obj(struct drm_i915_gem_object *obj) | |||
| 1824 | i915_gem_object_unpin(obj); | 1972 | i915_gem_object_unpin(obj); |
| 1825 | } | 1973 | } |
| 1826 | 1974 | ||
| 1975 | /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel | ||
| 1976 | * is assumed to be a power-of-two. */ | ||
| 1977 | static unsigned long gen4_compute_dspaddr_offset_xtiled(int *x, int *y, | ||
| 1978 | unsigned int bpp, | ||
| 1979 | unsigned int pitch) | ||
| 1980 | { | ||
| 1981 | int tile_rows, tiles; | ||
| 1982 | |||
| 1983 | tile_rows = *y / 8; | ||
| 1984 | *y %= 8; | ||
| 1985 | tiles = *x / (512/bpp); | ||
| 1986 | *x %= 512/bpp; | ||
| 1987 | |||
| 1988 | return tile_rows * pitch * 8 + tiles * 4096; | ||
| 1989 | } | ||
| 1990 | |||
| 1827 | static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 1991 | static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
| 1828 | int x, int y) | 1992 | int x, int y) |
| 1829 | { | 1993 | { |
| @@ -1833,7 +1997,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
| 1833 | struct intel_framebuffer *intel_fb; | 1997 | struct intel_framebuffer *intel_fb; |
| 1834 | struct drm_i915_gem_object *obj; | 1998 | struct drm_i915_gem_object *obj; |
| 1835 | int plane = intel_crtc->plane; | 1999 | int plane = intel_crtc->plane; |
| 1836 | unsigned long Start, Offset; | 2000 | unsigned long linear_offset; |
| 1837 | u32 dspcntr; | 2001 | u32 dspcntr; |
| 1838 | u32 reg; | 2002 | u32 reg; |
| 1839 | 2003 | ||
| @@ -1880,18 +2044,28 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
| 1880 | 2044 | ||
| 1881 | I915_WRITE(reg, dspcntr); | 2045 | I915_WRITE(reg, dspcntr); |
| 1882 | 2046 | ||
| 1883 | Start = obj->gtt_offset; | 2047 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); |
| 1884 | Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); | ||
| 1885 | 2048 | ||
| 1886 | DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", | 2049 | if (INTEL_INFO(dev)->gen >= 4) { |
| 1887 | Start, Offset, x, y, fb->pitches[0]); | 2050 | intel_crtc->dspaddr_offset = |
| 2051 | gen4_compute_dspaddr_offset_xtiled(&x, &y, | ||
| 2052 | fb->bits_per_pixel / 8, | ||
| 2053 | fb->pitches[0]); | ||
| 2054 | linear_offset -= intel_crtc->dspaddr_offset; | ||
| 2055 | } else { | ||
| 2056 | intel_crtc->dspaddr_offset = linear_offset; | ||
| 2057 | } | ||
| 2058 | |||
| 2059 | DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", | ||
| 2060 | obj->gtt_offset, linear_offset, x, y, fb->pitches[0]); | ||
| 1888 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); | 2061 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); |
| 1889 | if (INTEL_INFO(dev)->gen >= 4) { | 2062 | if (INTEL_INFO(dev)->gen >= 4) { |
| 1890 | I915_MODIFY_DISPBASE(DSPSURF(plane), Start); | 2063 | I915_MODIFY_DISPBASE(DSPSURF(plane), |
| 2064 | obj->gtt_offset + intel_crtc->dspaddr_offset); | ||
| 1891 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); | 2065 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); |
| 1892 | I915_WRITE(DSPADDR(plane), Offset); | 2066 | I915_WRITE(DSPLINOFF(plane), linear_offset); |
| 1893 | } else | 2067 | } else |
| 1894 | I915_WRITE(DSPADDR(plane), Start + Offset); | 2068 | I915_WRITE(DSPADDR(plane), obj->gtt_offset + linear_offset); |
| 1895 | POSTING_READ(reg); | 2069 | POSTING_READ(reg); |
| 1896 | 2070 | ||
| 1897 | return 0; | 2071 | return 0; |
| @@ -1906,7 +2080,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc, | |||
| 1906 | struct intel_framebuffer *intel_fb; | 2080 | struct intel_framebuffer *intel_fb; |
| 1907 | struct drm_i915_gem_object *obj; | 2081 | struct drm_i915_gem_object *obj; |
| 1908 | int plane = intel_crtc->plane; | 2082 | int plane = intel_crtc->plane; |
| 1909 | unsigned long Start, Offset; | 2083 | unsigned long linear_offset; |
| 1910 | u32 dspcntr; | 2084 | u32 dspcntr; |
| 1911 | u32 reg; | 2085 | u32 reg; |
| 1912 | 2086 | ||
| @@ -1961,15 +2135,20 @@ static int ironlake_update_plane(struct drm_crtc *crtc, | |||
| 1961 | 2135 | ||
| 1962 | I915_WRITE(reg, dspcntr); | 2136 | I915_WRITE(reg, dspcntr); |
| 1963 | 2137 | ||
| 1964 | Start = obj->gtt_offset; | 2138 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); |
| 1965 | Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); | 2139 | intel_crtc->dspaddr_offset = |
| 2140 | gen4_compute_dspaddr_offset_xtiled(&x, &y, | ||
| 2141 | fb->bits_per_pixel / 8, | ||
| 2142 | fb->pitches[0]); | ||
| 2143 | linear_offset -= intel_crtc->dspaddr_offset; | ||
| 1966 | 2144 | ||
| 1967 | DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", | 2145 | DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", |
| 1968 | Start, Offset, x, y, fb->pitches[0]); | 2146 | obj->gtt_offset, linear_offset, x, y, fb->pitches[0]); |
| 1969 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); | 2147 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); |
| 1970 | I915_MODIFY_DISPBASE(DSPSURF(plane), Start); | 2148 | I915_MODIFY_DISPBASE(DSPSURF(plane), |
| 2149 | obj->gtt_offset + intel_crtc->dspaddr_offset); | ||
| 1971 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); | 2150 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); |
| 1972 | I915_WRITE(DSPADDR(plane), Offset); | 2151 | I915_WRITE(DSPLINOFF(plane), linear_offset); |
| 1973 | POSTING_READ(reg); | 2152 | POSTING_READ(reg); |
| 1974 | 2153 | ||
| 1975 | return 0; | 2154 | return 0; |
| @@ -2656,16 +2835,13 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) | |||
| 2656 | static bool intel_crtc_driving_pch(struct drm_crtc *crtc) | 2835 | static bool intel_crtc_driving_pch(struct drm_crtc *crtc) |
| 2657 | { | 2836 | { |
| 2658 | struct drm_device *dev = crtc->dev; | 2837 | struct drm_device *dev = crtc->dev; |
| 2659 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 2660 | struct intel_encoder *encoder; | 2838 | struct intel_encoder *encoder; |
| 2661 | 2839 | ||
| 2662 | /* | 2840 | /* |
| 2663 | * If there's a non-PCH eDP on this crtc, it must be DP_A, and that | 2841 | * If there's a non-PCH eDP on this crtc, it must be DP_A, and that |
| 2664 | * must be driven by its own crtc; no sharing is possible. | 2842 | * must be driven by its own crtc; no sharing is possible. |
| 2665 | */ | 2843 | */ |
| 2666 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { | 2844 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 2667 | if (encoder->base.crtc != crtc) | ||
| 2668 | continue; | ||
| 2669 | 2845 | ||
| 2670 | /* On Haswell, LPT PCH handles the VGA connection via FDI, and Haswell | 2846 | /* On Haswell, LPT PCH handles the VGA connection via FDI, and Haswell |
| 2671 | * CPU handles all others */ | 2847 | * CPU handles all others */ |
| @@ -3397,7 +3573,7 @@ void intel_encoder_destroy(struct drm_encoder *encoder) | |||
| 3397 | } | 3573 | } |
| 3398 | 3574 | ||
| 3399 | static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, | 3575 | static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, |
| 3400 | struct drm_display_mode *mode, | 3576 | const struct drm_display_mode *mode, |
| 3401 | struct drm_display_mode *adjusted_mode) | 3577 | struct drm_display_mode *adjusted_mode) |
| 3402 | { | 3578 | { |
| 3403 | struct drm_device *dev = crtc->dev; | 3579 | struct drm_device *dev = crtc->dev; |
| @@ -3554,16 +3730,12 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, | |||
| 3554 | { | 3730 | { |
| 3555 | struct drm_device *dev = crtc->dev; | 3731 | struct drm_device *dev = crtc->dev; |
| 3556 | struct drm_i915_private *dev_priv = dev->dev_private; | 3732 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3557 | struct drm_encoder *encoder; | ||
| 3558 | struct drm_connector *connector; | 3733 | struct drm_connector *connector; |
| 3734 | struct intel_encoder *intel_encoder; | ||
| 3559 | unsigned int display_bpc = UINT_MAX, bpc; | 3735 | unsigned int display_bpc = UINT_MAX, bpc; |
| 3560 | 3736 | ||
| 3561 | /* Walk the encoders & connectors on this crtc, get min bpc */ | 3737 | /* Walk the encoders & connectors on this crtc, get min bpc */ |
| 3562 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 3738 | for_each_encoder_on_crtc(dev, crtc, intel_encoder) { |
| 3563 | struct intel_encoder *intel_encoder = to_intel_encoder(encoder); | ||
| 3564 | |||
| 3565 | if (encoder->crtc != crtc) | ||
| 3566 | continue; | ||
| 3567 | 3739 | ||
| 3568 | if (intel_encoder->type == INTEL_OUTPUT_LVDS) { | 3740 | if (intel_encoder->type == INTEL_OUTPUT_LVDS) { |
| 3569 | unsigned int lvds_bpc; | 3741 | unsigned int lvds_bpc; |
| @@ -3595,7 +3767,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, | |||
| 3595 | /* Not one of the known troublemakers, check the EDID */ | 3767 | /* Not one of the known troublemakers, check the EDID */ |
| 3596 | list_for_each_entry(connector, &dev->mode_config.connector_list, | 3768 | list_for_each_entry(connector, &dev->mode_config.connector_list, |
| 3597 | head) { | 3769 | head) { |
| 3598 | if (connector->encoder != encoder) | 3770 | if (connector->encoder != &intel_encoder->base) |
| 3599 | continue; | 3771 | continue; |
| 3600 | 3772 | ||
| 3601 | /* Don't use an invalid EDID bpc value */ | 3773 | /* Don't use an invalid EDID bpc value */ |
| @@ -3666,13 +3838,37 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, | |||
| 3666 | return display_bpc != bpc; | 3838 | return display_bpc != bpc; |
| 3667 | } | 3839 | } |
| 3668 | 3840 | ||
| 3841 | static int vlv_get_refclk(struct drm_crtc *crtc) | ||
| 3842 | { | ||
| 3843 | struct drm_device *dev = crtc->dev; | ||
| 3844 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 3845 | int refclk = 27000; /* for DP & HDMI */ | ||
| 3846 | |||
| 3847 | return 100000; /* only one validated so far */ | ||
| 3848 | |||
| 3849 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { | ||
| 3850 | refclk = 96000; | ||
| 3851 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | ||
| 3852 | if (intel_panel_use_ssc(dev_priv)) | ||
| 3853 | refclk = 100000; | ||
| 3854 | else | ||
| 3855 | refclk = 96000; | ||
| 3856 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { | ||
| 3857 | refclk = 100000; | ||
| 3858 | } | ||
| 3859 | |||
| 3860 | return refclk; | ||
| 3861 | } | ||
| 3862 | |||
| 3669 | static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) | 3863 | static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) |
| 3670 | { | 3864 | { |
| 3671 | struct drm_device *dev = crtc->dev; | 3865 | struct drm_device *dev = crtc->dev; |
| 3672 | struct drm_i915_private *dev_priv = dev->dev_private; | 3866 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3673 | int refclk; | 3867 | int refclk; |
| 3674 | 3868 | ||
| 3675 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && | 3869 | if (IS_VALLEYVIEW(dev)) { |
| 3870 | refclk = vlv_get_refclk(crtc); | ||
| 3871 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && | ||
| 3676 | intel_panel_use_ssc(dev_priv) && num_connectors < 2) { | 3872 | intel_panel_use_ssc(dev_priv) && num_connectors < 2) { |
| 3677 | refclk = dev_priv->lvds_ssc_freq * 1000; | 3873 | refclk = dev_priv->lvds_ssc_freq * 1000; |
| 3678 | DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", | 3874 | DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", |
| @@ -3787,6 +3983,72 @@ static void intel_update_lvds(struct drm_crtc *crtc, intel_clock_t *clock, | |||
| 3787 | I915_WRITE(LVDS, temp); | 3983 | I915_WRITE(LVDS, temp); |
| 3788 | } | 3984 | } |
| 3789 | 3985 | ||
| 3986 | static void vlv_update_pll(struct drm_crtc *crtc, | ||
| 3987 | struct drm_display_mode *mode, | ||
| 3988 | struct drm_display_mode *adjusted_mode, | ||
| 3989 | intel_clock_t *clock, intel_clock_t *reduced_clock, | ||
| 3990 | int refclk, int num_connectors) | ||
| 3991 | { | ||
| 3992 | struct drm_device *dev = crtc->dev; | ||
| 3993 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 3994 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 3995 | int pipe = intel_crtc->pipe; | ||
| 3996 | u32 dpll, mdiv, pdiv; | ||
| 3997 | u32 bestn, bestm1, bestm2, bestp1, bestp2; | ||
| 3998 | bool is_hdmi; | ||
| 3999 | |||
| 4000 | is_hdmi = intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI); | ||
| 4001 | |||
| 4002 | bestn = clock->n; | ||
| 4003 | bestm1 = clock->m1; | ||
| 4004 | bestm2 = clock->m2; | ||
| 4005 | bestp1 = clock->p1; | ||
| 4006 | bestp2 = clock->p2; | ||
| 4007 | |||
| 4008 | /* Enable DPIO clock input */ | ||
| 4009 | dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | | ||
| 4010 | DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV; | ||
| 4011 | I915_WRITE(DPLL(pipe), dpll); | ||
| 4012 | POSTING_READ(DPLL(pipe)); | ||
| 4013 | |||
| 4014 | mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); | ||
| 4015 | mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT)); | ||
| 4016 | mdiv |= ((bestn << DPIO_N_SHIFT)); | ||
| 4017 | mdiv |= (1 << DPIO_POST_DIV_SHIFT); | ||
| 4018 | mdiv |= (1 << DPIO_K_SHIFT); | ||
| 4019 | mdiv |= DPIO_ENABLE_CALIBRATION; | ||
| 4020 | intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); | ||
| 4021 | |||
| 4022 | intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000); | ||
| 4023 | |||
| 4024 | pdiv = DPIO_REFSEL_OVERRIDE | (5 << DPIO_PLL_MODESEL_SHIFT) | | ||
| 4025 | (3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) | | ||
| 4026 | (8 << DPIO_DRIVER_CTL_SHIFT) | (5 << DPIO_CLK_BIAS_CTL_SHIFT); | ||
| 4027 | intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv); | ||
| 4028 | |||
| 4029 | intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x009f0051); | ||
| 4030 | |||
| 4031 | dpll |= DPLL_VCO_ENABLE; | ||
| 4032 | I915_WRITE(DPLL(pipe), dpll); | ||
| 4033 | POSTING_READ(DPLL(pipe)); | ||
| 4034 | if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) | ||
| 4035 | DRM_ERROR("DPLL %d failed to lock\n", pipe); | ||
| 4036 | |||
| 4037 | if (is_hdmi) { | ||
| 4038 | u32 temp = intel_mode_get_pixel_multiplier(adjusted_mode); | ||
| 4039 | |||
| 4040 | if (temp > 1) | ||
| 4041 | temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; | ||
| 4042 | else | ||
| 4043 | temp = 0; | ||
| 4044 | |||
| 4045 | I915_WRITE(DPLL_MD(pipe), temp); | ||
| 4046 | POSTING_READ(DPLL_MD(pipe)); | ||
| 4047 | } | ||
| 4048 | |||
| 4049 | intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x641); /* ??? */ | ||
| 4050 | } | ||
| 4051 | |||
| 3790 | static void i9xx_update_pll(struct drm_crtc *crtc, | 4052 | static void i9xx_update_pll(struct drm_crtc *crtc, |
| 3791 | struct drm_display_mode *mode, | 4053 | struct drm_display_mode *mode, |
| 3792 | struct drm_display_mode *adjusted_mode, | 4054 | struct drm_display_mode *adjusted_mode, |
| @@ -3974,15 +4236,11 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
| 3974 | u32 dspcntr, pipeconf, vsyncshift; | 4236 | u32 dspcntr, pipeconf, vsyncshift; |
| 3975 | bool ok, has_reduced_clock = false, is_sdvo = false; | 4237 | bool ok, has_reduced_clock = false, is_sdvo = false; |
| 3976 | bool is_lvds = false, is_tv = false, is_dp = false; | 4238 | bool is_lvds = false, is_tv = false, is_dp = false; |
| 3977 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 3978 | struct intel_encoder *encoder; | 4239 | struct intel_encoder *encoder; |
| 3979 | const intel_limit_t *limit; | 4240 | const intel_limit_t *limit; |
| 3980 | int ret; | 4241 | int ret; |
| 3981 | 4242 | ||
| 3982 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { | 4243 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 3983 | if (encoder->base.crtc != crtc) | ||
| 3984 | continue; | ||
| 3985 | |||
| 3986 | switch (encoder->type) { | 4244 | switch (encoder->type) { |
| 3987 | case INTEL_OUTPUT_LVDS: | 4245 | case INTEL_OUTPUT_LVDS: |
| 3988 | is_lvds = true; | 4246 | is_lvds = true; |
| @@ -4044,6 +4302,9 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4044 | 4302 | ||
| 4045 | if (IS_GEN2(dev)) | 4303 | if (IS_GEN2(dev)) |
| 4046 | i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors); | 4304 | i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors); |
| 4305 | else if (IS_VALLEYVIEW(dev)) | ||
| 4306 | vlv_update_pll(crtc, mode,adjusted_mode, &clock, NULL, | ||
| 4307 | refclk, num_connectors); | ||
| 4047 | else | 4308 | else |
| 4048 | i9xx_update_pll(crtc, mode, adjusted_mode, &clock, | 4309 | i9xx_update_pll(crtc, mode, adjusted_mode, &clock, |
| 4049 | has_reduced_clock ? &reduced_clock : NULL, | 4310 | has_reduced_clock ? &reduced_clock : NULL, |
| @@ -4282,15 +4543,11 @@ static int ironlake_get_refclk(struct drm_crtc *crtc) | |||
| 4282 | struct drm_device *dev = crtc->dev; | 4543 | struct drm_device *dev = crtc->dev; |
| 4283 | struct drm_i915_private *dev_priv = dev->dev_private; | 4544 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 4284 | struct intel_encoder *encoder; | 4545 | struct intel_encoder *encoder; |
| 4285 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 4286 | struct intel_encoder *edp_encoder = NULL; | 4546 | struct intel_encoder *edp_encoder = NULL; |
| 4287 | int num_connectors = 0; | 4547 | int num_connectors = 0; |
| 4288 | bool is_lvds = false; | 4548 | bool is_lvds = false; |
| 4289 | 4549 | ||
| 4290 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { | 4550 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 4291 | if (encoder->base.crtc != crtc) | ||
| 4292 | continue; | ||
| 4293 | |||
| 4294 | switch (encoder->type) { | 4551 | switch (encoder->type) { |
| 4295 | case INTEL_OUTPUT_LVDS: | 4552 | case INTEL_OUTPUT_LVDS: |
| 4296 | is_lvds = true; | 4553 | is_lvds = true; |
| @@ -4327,7 +4584,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4327 | u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; | 4584 | u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; |
| 4328 | bool ok, has_reduced_clock = false, is_sdvo = false; | 4585 | bool ok, has_reduced_clock = false, is_sdvo = false; |
| 4329 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; | 4586 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; |
| 4330 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 4331 | struct intel_encoder *encoder, *edp_encoder = NULL; | 4587 | struct intel_encoder *encoder, *edp_encoder = NULL; |
| 4332 | const intel_limit_t *limit; | 4588 | const intel_limit_t *limit; |
| 4333 | int ret; | 4589 | int ret; |
| @@ -4338,10 +4594,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4338 | bool dither; | 4594 | bool dither; |
| 4339 | bool is_cpu_edp = false, is_pch_edp = false; | 4595 | bool is_cpu_edp = false, is_pch_edp = false; |
| 4340 | 4596 | ||
| 4341 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { | 4597 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 4342 | if (encoder->base.crtc != crtc) | ||
| 4343 | continue; | ||
| 4344 | |||
| 4345 | switch (encoder->type) { | 4598 | switch (encoder->type) { |
| 4346 | case INTEL_OUTPUT_LVDS: | 4599 | case INTEL_OUTPUT_LVDS: |
| 4347 | is_lvds = true; | 4600 | is_lvds = true; |
| @@ -4405,25 +4658,10 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4405 | &clock, | 4658 | &clock, |
| 4406 | &reduced_clock); | 4659 | &reduced_clock); |
| 4407 | } | 4660 | } |
| 4408 | /* SDVO TV has fixed PLL values depend on its clock range, | 4661 | |
| 4409 | this mirrors vbios setting. */ | 4662 | if (is_sdvo && is_tv) |
| 4410 | if (is_sdvo && is_tv) { | 4663 | i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock); |
| 4411 | if (adjusted_mode->clock >= 100000 | 4664 | |
| 4412 | && adjusted_mode->clock < 140500) { | ||
| 4413 | clock.p1 = 2; | ||
| 4414 | clock.p2 = 10; | ||
| 4415 | clock.n = 3; | ||
| 4416 | clock.m1 = 16; | ||
| 4417 | clock.m2 = 8; | ||
| 4418 | } else if (adjusted_mode->clock >= 140500 | ||
| 4419 | && adjusted_mode->clock <= 200000) { | ||
| 4420 | clock.p1 = 1; | ||
| 4421 | clock.p2 = 10; | ||
| 4422 | clock.n = 6; | ||
| 4423 | clock.m1 = 12; | ||
| 4424 | clock.m2 = 8; | ||
| 4425 | } | ||
| 4426 | } | ||
| 4427 | 4665 | ||
| 4428 | /* FDI link */ | 4666 | /* FDI link */ |
| 4429 | pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); | 4667 | pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); |
| @@ -4431,16 +4669,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4431 | /* CPU eDP doesn't require FDI link, so just set DP M/N | 4669 | /* CPU eDP doesn't require FDI link, so just set DP M/N |
| 4432 | according to current link config */ | 4670 | according to current link config */ |
| 4433 | if (is_cpu_edp) { | 4671 | if (is_cpu_edp) { |
| 4434 | target_clock = mode->clock; | ||
| 4435 | intel_edp_link_config(edp_encoder, &lane, &link_bw); | 4672 | intel_edp_link_config(edp_encoder, &lane, &link_bw); |
| 4436 | } else { | 4673 | } else { |
| 4437 | /* [e]DP over FDI requires target mode clock | ||
| 4438 | instead of link clock */ | ||
| 4439 | if (is_dp) | ||
| 4440 | target_clock = mode->clock; | ||
| 4441 | else | ||
| 4442 | target_clock = adjusted_mode->clock; | ||
| 4443 | |||
| 4444 | /* FDI is a binary signal running at ~2.7GHz, encoding | 4674 | /* FDI is a binary signal running at ~2.7GHz, encoding |
| 4445 | * each output octet as 10 bits. The actual frequency | 4675 | * each output octet as 10 bits. The actual frequency |
| 4446 | * is stored as a divider into a 100MHz clock, and the | 4676 | * is stored as a divider into a 100MHz clock, and the |
| @@ -4451,6 +4681,14 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4451 | link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; | 4681 | link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; |
| 4452 | } | 4682 | } |
| 4453 | 4683 | ||
| 4684 | /* [e]DP over FDI requires target mode clock instead of link clock. */ | ||
| 4685 | if (edp_encoder) | ||
| 4686 | target_clock = intel_edp_target_clock(edp_encoder, mode); | ||
| 4687 | else if (is_dp) | ||
| 4688 | target_clock = mode->clock; | ||
| 4689 | else | ||
| 4690 | target_clock = adjusted_mode->clock; | ||
| 4691 | |||
| 4454 | /* determine panel color depth */ | 4692 | /* determine panel color depth */ |
| 4455 | temp = I915_READ(PIPECONF(pipe)); | 4693 | temp = I915_READ(PIPECONF(pipe)); |
| 4456 | temp &= ~PIPE_BPC_MASK; | 4694 | temp &= ~PIPE_BPC_MASK; |
| @@ -4662,16 +4900,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4662 | if (is_lvds && has_reduced_clock && i915_powersave) { | 4900 | if (is_lvds && has_reduced_clock && i915_powersave) { |
| 4663 | I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2); | 4901 | I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2); |
| 4664 | intel_crtc->lowfreq_avail = true; | 4902 | intel_crtc->lowfreq_avail = true; |
| 4665 | if (HAS_PIPE_CXSR(dev)) { | ||
| 4666 | DRM_DEBUG_KMS("enabling CxSR downclocking\n"); | ||
| 4667 | pipeconf |= PIPECONF_CXSR_DOWNCLOCK; | ||
| 4668 | } | ||
| 4669 | } else { | 4903 | } else { |
| 4670 | I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp); | 4904 | I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp); |
| 4671 | if (HAS_PIPE_CXSR(dev)) { | ||
| 4672 | DRM_DEBUG_KMS("disabling CxSR downclocking\n"); | ||
| 4673 | pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; | ||
| 4674 | } | ||
| 4675 | } | 4905 | } |
| 4676 | } | 4906 | } |
| 4677 | 4907 | ||
| @@ -5975,7 +6205,6 @@ static int intel_gen2_queue_flip(struct drm_device *dev, | |||
| 5975 | { | 6205 | { |
| 5976 | struct drm_i915_private *dev_priv = dev->dev_private; | 6206 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 5977 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 6207 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 5978 | unsigned long offset; | ||
| 5979 | u32 flip_mask; | 6208 | u32 flip_mask; |
| 5980 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; | 6209 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; |
| 5981 | int ret; | 6210 | int ret; |
| @@ -5984,9 +6213,6 @@ static int intel_gen2_queue_flip(struct drm_device *dev, | |||
| 5984 | if (ret) | 6213 | if (ret) |
| 5985 | goto err; | 6214 | goto err; |
| 5986 | 6215 | ||
| 5987 | /* Offset into the new buffer for cases of shared fbs between CRTCs */ | ||
| 5988 | offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; | ||
| 5989 | |||
| 5990 | ret = intel_ring_begin(ring, 6); | 6216 | ret = intel_ring_begin(ring, 6); |
| 5991 | if (ret) | 6217 | if (ret) |
| 5992 | goto err_unpin; | 6218 | goto err_unpin; |
| @@ -6003,7 +6229,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev, | |||
| 6003 | intel_ring_emit(ring, MI_DISPLAY_FLIP | | 6229 | intel_ring_emit(ring, MI_DISPLAY_FLIP | |
| 6004 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 6230 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
| 6005 | intel_ring_emit(ring, fb->pitches[0]); | 6231 | intel_ring_emit(ring, fb->pitches[0]); |
| 6006 | intel_ring_emit(ring, obj->gtt_offset + offset); | 6232 | intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); |
| 6007 | intel_ring_emit(ring, 0); /* aux display base address, unused */ | 6233 | intel_ring_emit(ring, 0); /* aux display base address, unused */ |
| 6008 | intel_ring_advance(ring); | 6234 | intel_ring_advance(ring); |
| 6009 | return 0; | 6235 | return 0; |
| @@ -6021,7 +6247,6 @@ static int intel_gen3_queue_flip(struct drm_device *dev, | |||
| 6021 | { | 6247 | { |
| 6022 | struct drm_i915_private *dev_priv = dev->dev_private; | 6248 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 6023 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 6249 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 6024 | unsigned long offset; | ||
| 6025 | u32 flip_mask; | 6250 | u32 flip_mask; |
| 6026 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; | 6251 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; |
| 6027 | int ret; | 6252 | int ret; |
| @@ -6030,9 +6255,6 @@ static int intel_gen3_queue_flip(struct drm_device *dev, | |||
| 6030 | if (ret) | 6255 | if (ret) |
| 6031 | goto err; | 6256 | goto err; |
| 6032 | 6257 | ||
| 6033 | /* Offset into the new buffer for cases of shared fbs between CRTCs */ | ||
| 6034 | offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; | ||
| 6035 | |||
| 6036 | ret = intel_ring_begin(ring, 6); | 6258 | ret = intel_ring_begin(ring, 6); |
| 6037 | if (ret) | 6259 | if (ret) |
| 6038 | goto err_unpin; | 6260 | goto err_unpin; |
| @@ -6046,7 +6268,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev, | |||
| 6046 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | | 6268 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | |
| 6047 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 6269 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
| 6048 | intel_ring_emit(ring, fb->pitches[0]); | 6270 | intel_ring_emit(ring, fb->pitches[0]); |
| 6049 | intel_ring_emit(ring, obj->gtt_offset + offset); | 6271 | intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); |
| 6050 | intel_ring_emit(ring, MI_NOOP); | 6272 | intel_ring_emit(ring, MI_NOOP); |
| 6051 | 6273 | ||
| 6052 | intel_ring_advance(ring); | 6274 | intel_ring_advance(ring); |
| @@ -6084,7 +6306,9 @@ static int intel_gen4_queue_flip(struct drm_device *dev, | |||
| 6084 | intel_ring_emit(ring, MI_DISPLAY_FLIP | | 6306 | intel_ring_emit(ring, MI_DISPLAY_FLIP | |
| 6085 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 6307 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
| 6086 | intel_ring_emit(ring, fb->pitches[0]); | 6308 | intel_ring_emit(ring, fb->pitches[0]); |
| 6087 | intel_ring_emit(ring, obj->gtt_offset | obj->tiling_mode); | 6309 | intel_ring_emit(ring, |
| 6310 | (obj->gtt_offset + intel_crtc->dspaddr_offset) | | ||
| 6311 | obj->tiling_mode); | ||
| 6088 | 6312 | ||
| 6089 | /* XXX Enabling the panel-fitter across page-flip is so far | 6313 | /* XXX Enabling the panel-fitter across page-flip is so far |
| 6090 | * untested on non-native modes, so ignore it for now. | 6314 | * untested on non-native modes, so ignore it for now. |
| @@ -6124,7 +6348,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev, | |||
| 6124 | intel_ring_emit(ring, MI_DISPLAY_FLIP | | 6348 | intel_ring_emit(ring, MI_DISPLAY_FLIP | |
| 6125 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 6349 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
| 6126 | intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode); | 6350 | intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode); |
| 6127 | intel_ring_emit(ring, obj->gtt_offset); | 6351 | intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); |
| 6128 | 6352 | ||
| 6129 | /* Contrary to the suggestions in the documentation, | 6353 | /* Contrary to the suggestions in the documentation, |
| 6130 | * "Enable Panel Fitter" does not seem to be required when page | 6354 | * "Enable Panel Fitter" does not seem to be required when page |
| @@ -6187,7 +6411,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, | |||
| 6187 | 6411 | ||
| 6188 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); | 6412 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); |
| 6189 | intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); | 6413 | intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); |
| 6190 | intel_ring_emit(ring, (obj->gtt_offset)); | 6414 | intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); |
| 6191 | intel_ring_emit(ring, (MI_NOOP)); | 6415 | intel_ring_emit(ring, (MI_NOOP)); |
| 6192 | intel_ring_advance(ring); | 6416 | intel_ring_advance(ring); |
| 6193 | return 0; | 6417 | return 0; |
| @@ -6219,6 +6443,19 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
| 6219 | unsigned long flags; | 6443 | unsigned long flags; |
| 6220 | int ret; | 6444 | int ret; |
| 6221 | 6445 | ||
| 6446 | /* Can't change pixel format via MI display flips. */ | ||
| 6447 | if (fb->pixel_format != crtc->fb->pixel_format) | ||
| 6448 | return -EINVAL; | ||
| 6449 | |||
| 6450 | /* | ||
| 6451 | * TILEOFF/LINOFF registers can't be changed via MI display flips. | ||
| 6452 | * Note that pitch changes could also affect these register. | ||
| 6453 | */ | ||
| 6454 | if (INTEL_INFO(dev)->gen > 3 && | ||
| 6455 | (fb->offsets[0] != crtc->fb->offsets[0] || | ||
| 6456 | fb->pitches[0] != crtc->fb->pitches[0])) | ||
| 6457 | return -EINVAL; | ||
| 6458 | |||
| 6222 | work = kzalloc(sizeof *work, GFP_KERNEL); | 6459 | work = kzalloc(sizeof *work, GFP_KERNEL); |
| 6223 | if (work == NULL) | 6460 | if (work == NULL) |
| 6224 | return -ENOMEM; | 6461 | return -ENOMEM; |
| @@ -6249,7 +6486,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
| 6249 | intel_fb = to_intel_framebuffer(fb); | 6486 | intel_fb = to_intel_framebuffer(fb); |
| 6250 | obj = intel_fb->obj; | 6487 | obj = intel_fb->obj; |
| 6251 | 6488 | ||
| 6252 | mutex_lock(&dev->struct_mutex); | 6489 | ret = i915_mutex_lock_interruptible(dev); |
| 6490 | if (ret) | ||
| 6491 | goto cleanup; | ||
| 6253 | 6492 | ||
| 6254 | /* Reference the objects for the scheduled work. */ | 6493 | /* Reference the objects for the scheduled work. */ |
| 6255 | drm_gem_object_reference(&work->old_fb_obj->base); | 6494 | drm_gem_object_reference(&work->old_fb_obj->base); |
| @@ -6284,6 +6523,7 @@ cleanup_pending: | |||
| 6284 | drm_gem_object_unreference(&obj->base); | 6523 | drm_gem_object_unreference(&obj->base); |
| 6285 | mutex_unlock(&dev->struct_mutex); | 6524 | mutex_unlock(&dev->struct_mutex); |
| 6286 | 6525 | ||
| 6526 | cleanup: | ||
| 6287 | spin_lock_irqsave(&dev->event_lock, flags); | 6527 | spin_lock_irqsave(&dev->event_lock, flags); |
| 6288 | intel_crtc->unpin_work = NULL; | 6528 | intel_crtc->unpin_work = NULL; |
| 6289 | spin_unlock_irqrestore(&dev->event_lock, flags); | 6529 | spin_unlock_irqrestore(&dev->event_lock, flags); |
| @@ -6566,7 +6806,24 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 6566 | 6806 | ||
| 6567 | if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED)) | 6807 | if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED)) |
| 6568 | intel_dp_init(dev, PCH_DP_D); | 6808 | intel_dp_init(dev, PCH_DP_D); |
| 6809 | } else if (IS_VALLEYVIEW(dev)) { | ||
| 6810 | int found; | ||
| 6569 | 6811 | ||
| 6812 | if (I915_READ(SDVOB) & PORT_DETECTED) { | ||
| 6813 | /* SDVOB multiplex with HDMIB */ | ||
| 6814 | found = intel_sdvo_init(dev, SDVOB, true); | ||
| 6815 | if (!found) | ||
| 6816 | intel_hdmi_init(dev, SDVOB); | ||
| 6817 | if (!found && (I915_READ(DP_B) & DP_DETECTED)) | ||
| 6818 | intel_dp_init(dev, DP_B); | ||
| 6819 | } | ||
| 6820 | |||
| 6821 | if (I915_READ(SDVOC) & PORT_DETECTED) | ||
| 6822 | intel_hdmi_init(dev, SDVOC); | ||
| 6823 | |||
| 6824 | /* Shares lanes with HDMI on SDVOC */ | ||
| 6825 | if (I915_READ(DP_C) & DP_DETECTED) | ||
| 6826 | intel_dp_init(dev, DP_C); | ||
| 6570 | } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { | 6827 | } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { |
| 6571 | bool found = false; | 6828 | bool found = false; |
| 6572 | 6829 | ||
| @@ -6623,7 +6880,7 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 6623 | /* disable all the possible outputs/crtcs before entering KMS mode */ | 6880 | /* disable all the possible outputs/crtcs before entering KMS mode */ |
| 6624 | drm_helper_disable_unused_functions(dev); | 6881 | drm_helper_disable_unused_functions(dev); |
| 6625 | 6882 | ||
| 6626 | if (HAS_PCH_SPLIT(dev)) | 6883 | if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) |
| 6627 | ironlake_init_pch_refclk(dev); | 6884 | ironlake_init_pch_refclk(dev); |
| 6628 | } | 6885 | } |
| 6629 | 6886 | ||
| @@ -6777,9 +7034,6 @@ static void intel_init_display(struct drm_device *dev) | |||
| 6777 | dev_priv->display.write_eld = ironlake_write_eld; | 7034 | dev_priv->display.write_eld = ironlake_write_eld; |
| 6778 | } else | 7035 | } else |
| 6779 | dev_priv->display.update_wm = NULL; | 7036 | dev_priv->display.update_wm = NULL; |
| 6780 | } else if (IS_VALLEYVIEW(dev)) { | ||
| 6781 | dev_priv->display.force_wake_get = vlv_force_wake_get; | ||
| 6782 | dev_priv->display.force_wake_put = vlv_force_wake_put; | ||
| 6783 | } else if (IS_G4X(dev)) { | 7037 | } else if (IS_G4X(dev)) { |
| 6784 | dev_priv->display.write_eld = g4x_write_eld; | 7038 | dev_priv->display.write_eld = g4x_write_eld; |
| 6785 | } | 7039 | } |
| @@ -6923,20 +7177,18 @@ static void i915_disable_vga(struct drm_device *dev) | |||
| 6923 | 7177 | ||
| 6924 | void intel_modeset_init_hw(struct drm_device *dev) | 7178 | void intel_modeset_init_hw(struct drm_device *dev) |
| 6925 | { | 7179 | { |
| 6926 | struct drm_i915_private *dev_priv = dev->dev_private; | 7180 | /* We attempt to init the necessary power wells early in the initialization |
| 7181 | * time, so the subsystems that expect power to be enabled can work. | ||
| 7182 | */ | ||
| 7183 | intel_init_power_wells(dev); | ||
| 6927 | 7184 | ||
| 6928 | intel_init_clock_gating(dev); | 7185 | intel_prepare_ddi(dev); |
| 6929 | 7186 | ||
| 6930 | if (IS_IRONLAKE_M(dev)) { | 7187 | intel_init_clock_gating(dev); |
| 6931 | ironlake_enable_drps(dev); | ||
| 6932 | ironlake_enable_rc6(dev); | ||
| 6933 | intel_init_emon(dev); | ||
| 6934 | } | ||
| 6935 | 7188 | ||
| 6936 | if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { | 7189 | mutex_lock(&dev->struct_mutex); |
| 6937 | gen6_enable_rps(dev_priv); | 7190 | intel_enable_gt_powersave(dev); |
| 6938 | gen6_update_ring_freq(dev_priv); | 7191 | mutex_unlock(&dev->struct_mutex); |
| 6939 | } | ||
| 6940 | } | 7192 | } |
| 6941 | 7193 | ||
| 6942 | void intel_modeset_init(struct drm_device *dev) | 7194 | void intel_modeset_init(struct drm_device *dev) |
| @@ -6958,8 +7210,6 @@ void intel_modeset_init(struct drm_device *dev) | |||
| 6958 | 7210 | ||
| 6959 | intel_init_pm(dev); | 7211 | intel_init_pm(dev); |
| 6960 | 7212 | ||
| 6961 | intel_prepare_ddi(dev); | ||
| 6962 | |||
| 6963 | intel_init_display(dev); | 7213 | intel_init_display(dev); |
| 6964 | 7214 | ||
| 6965 | if (IS_GEN2(dev)) { | 7215 | if (IS_GEN2(dev)) { |
| @@ -6972,7 +7222,7 @@ void intel_modeset_init(struct drm_device *dev) | |||
| 6972 | dev->mode_config.max_width = 8192; | 7222 | dev->mode_config.max_width = 8192; |
| 6973 | dev->mode_config.max_height = 8192; | 7223 | dev->mode_config.max_height = 8192; |
| 6974 | } | 7224 | } |
| 6975 | dev->mode_config.fb_base = dev->agp->base; | 7225 | dev->mode_config.fb_base = dev_priv->mm.gtt_base_addr; |
| 6976 | 7226 | ||
| 6977 | DRM_DEBUG_KMS("%d display pipe%s available.\n", | 7227 | DRM_DEBUG_KMS("%d display pipe%s available.\n", |
| 6978 | dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : ""); | 7228 | dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : ""); |
| @@ -7025,13 +7275,9 @@ void intel_modeset_cleanup(struct drm_device *dev) | |||
| 7025 | 7275 | ||
| 7026 | intel_disable_fbc(dev); | 7276 | intel_disable_fbc(dev); |
| 7027 | 7277 | ||
| 7028 | if (IS_IRONLAKE_M(dev)) | 7278 | intel_disable_gt_powersave(dev); |
| 7029 | ironlake_disable_drps(dev); | ||
| 7030 | if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) | ||
| 7031 | gen6_disable_rps(dev); | ||
| 7032 | 7279 | ||
| 7033 | if (IS_IRONLAKE_M(dev)) | 7280 | ironlake_teardown_rc6(dev); |
| 7034 | ironlake_disable_rc6(dev); | ||
| 7035 | 7281 | ||
| 7036 | if (IS_VALLEYVIEW(dev)) | 7282 | if (IS_VALLEYVIEW(dev)) |
| 7037 | vlv_init_dpio(dev); | 7283 | vlv_init_dpio(dev); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c0449324143c..0a56b9ab0f58 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -155,6 +155,18 @@ intel_edp_link_config(struct intel_encoder *intel_encoder, | |||
| 155 | *link_bw = 270000; | 155 | *link_bw = 270000; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | int | ||
| 159 | intel_edp_target_clock(struct intel_encoder *intel_encoder, | ||
| 160 | struct drm_display_mode *mode) | ||
| 161 | { | ||
| 162 | struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); | ||
| 163 | |||
| 164 | if (intel_dp->panel_fixed_mode) | ||
| 165 | return intel_dp->panel_fixed_mode->clock; | ||
| 166 | else | ||
| 167 | return mode->clock; | ||
| 168 | } | ||
| 169 | |||
| 158 | static int | 170 | static int |
| 159 | intel_dp_max_lane_count(struct intel_dp *intel_dp) | 171 | intel_dp_max_lane_count(struct intel_dp *intel_dp) |
| 160 | { | 172 | { |
| @@ -225,7 +237,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) | |||
| 225 | static bool | 237 | static bool |
| 226 | intel_dp_adjust_dithering(struct intel_dp *intel_dp, | 238 | intel_dp_adjust_dithering(struct intel_dp *intel_dp, |
| 227 | struct drm_display_mode *mode, | 239 | struct drm_display_mode *mode, |
| 228 | struct drm_display_mode *adjusted_mode) | 240 | bool adjust_mode) |
| 229 | { | 241 | { |
| 230 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); | 242 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); |
| 231 | int max_lanes = intel_dp_max_lane_count(intel_dp); | 243 | int max_lanes = intel_dp_max_lane_count(intel_dp); |
| @@ -239,8 +251,8 @@ intel_dp_adjust_dithering(struct intel_dp *intel_dp, | |||
| 239 | if (mode_rate > max_rate) | 251 | if (mode_rate > max_rate) |
| 240 | return false; | 252 | return false; |
| 241 | 253 | ||
| 242 | if (adjusted_mode) | 254 | if (adjust_mode) |
| 243 | adjusted_mode->private_flags | 255 | mode->private_flags |
| 244 | |= INTEL_MODE_DP_FORCE_6BPC; | 256 | |= INTEL_MODE_DP_FORCE_6BPC; |
| 245 | 257 | ||
| 246 | return true; | 258 | return true; |
| @@ -263,7 +275,7 @@ intel_dp_mode_valid(struct drm_connector *connector, | |||
| 263 | return MODE_PANEL; | 275 | return MODE_PANEL; |
| 264 | } | 276 | } |
| 265 | 277 | ||
| 266 | if (!intel_dp_adjust_dithering(intel_dp, mode, NULL)) | 278 | if (!intel_dp_adjust_dithering(intel_dp, mode, false)) |
| 267 | return MODE_CLOCK_HIGH; | 279 | return MODE_CLOCK_HIGH; |
| 268 | 280 | ||
| 269 | if (mode->clock < 10000) | 281 | if (mode->clock < 10000) |
| @@ -691,7 +703,8 @@ intel_dp_i2c_init(struct intel_dp *intel_dp, | |||
| 691 | } | 703 | } |
| 692 | 704 | ||
| 693 | static bool | 705 | static bool |
| 694 | intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 706 | intel_dp_mode_fixup(struct drm_encoder *encoder, |
| 707 | const struct drm_display_mode *mode, | ||
| 695 | struct drm_display_mode *adjusted_mode) | 708 | struct drm_display_mode *adjusted_mode) |
| 696 | { | 709 | { |
| 697 | struct drm_device *dev = encoder->dev; | 710 | struct drm_device *dev = encoder->dev; |
| @@ -706,28 +719,23 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 706 | intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode); | 719 | intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode); |
| 707 | intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN, | 720 | intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN, |
| 708 | mode, adjusted_mode); | 721 | mode, adjusted_mode); |
| 709 | /* | ||
| 710 | * the mode->clock is used to calculate the Data&Link M/N | ||
| 711 | * of the pipe. For the eDP the fixed clock should be used. | ||
| 712 | */ | ||
| 713 | mode->clock = intel_dp->panel_fixed_mode->clock; | ||
| 714 | } | 722 | } |
| 715 | 723 | ||
| 716 | if (mode->flags & DRM_MODE_FLAG_DBLCLK) | 724 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) |
| 717 | return false; | 725 | return false; |
| 718 | 726 | ||
| 719 | DRM_DEBUG_KMS("DP link computation with max lane count %i " | 727 | DRM_DEBUG_KMS("DP link computation with max lane count %i " |
| 720 | "max bw %02x pixel clock %iKHz\n", | 728 | "max bw %02x pixel clock %iKHz\n", |
| 721 | max_lane_count, bws[max_clock], mode->clock); | 729 | max_lane_count, bws[max_clock], adjusted_mode->clock); |
| 722 | 730 | ||
| 723 | if (!intel_dp_adjust_dithering(intel_dp, mode, adjusted_mode)) | 731 | if (!intel_dp_adjust_dithering(intel_dp, adjusted_mode, true)) |
| 724 | return false; | 732 | return false; |
| 725 | 733 | ||
| 726 | bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; | 734 | bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; |
| 727 | mode_rate = intel_dp_link_required(mode->clock, bpp); | 735 | mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp); |
| 728 | 736 | ||
| 729 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { | 737 | for (clock = 0; clock <= max_clock; clock++) { |
| 730 | for (clock = 0; clock <= max_clock; clock++) { | 738 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { |
| 731 | int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); | 739 | int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); |
| 732 | 740 | ||
| 733 | if (mode_rate <= link_avail) { | 741 | if (mode_rate <= link_avail) { |
| @@ -786,8 +794,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
| 786 | struct drm_display_mode *adjusted_mode) | 794 | struct drm_display_mode *adjusted_mode) |
| 787 | { | 795 | { |
| 788 | struct drm_device *dev = crtc->dev; | 796 | struct drm_device *dev = crtc->dev; |
| 789 | struct drm_mode_config *mode_config = &dev->mode_config; | 797 | struct intel_encoder *encoder; |
| 790 | struct drm_encoder *encoder; | ||
| 791 | struct drm_i915_private *dev_priv = dev->dev_private; | 798 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 792 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 799 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 793 | int lane_count = 4; | 800 | int lane_count = 4; |
| @@ -797,13 +804,9 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
| 797 | /* | 804 | /* |
| 798 | * Find the lane count in the intel_encoder private | 805 | * Find the lane count in the intel_encoder private |
| 799 | */ | 806 | */ |
| 800 | list_for_each_entry(encoder, &mode_config->encoder_list, head) { | 807 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 801 | struct intel_dp *intel_dp; | 808 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 802 | |||
| 803 | if (encoder->crtc != crtc) | ||
| 804 | continue; | ||
| 805 | 809 | ||
| 806 | intel_dp = enc_to_intel_dp(encoder); | ||
| 807 | if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || | 810 | if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || |
| 808 | intel_dp->base.type == INTEL_OUTPUT_EDP) | 811 | intel_dp->base.type == INTEL_OUTPUT_EDP) |
| 809 | { | 812 | { |
| @@ -1768,7 +1771,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
| 1768 | for (i = 0; i < intel_dp->lane_count; i++) | 1771 | for (i = 0; i < intel_dp->lane_count; i++) |
| 1769 | if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) | 1772 | if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) |
| 1770 | break; | 1773 | break; |
| 1771 | if (i == intel_dp->lane_count) { | 1774 | if (i == intel_dp->lane_count && voltage_tries == 5) { |
| 1772 | ++loop_tries; | 1775 | ++loop_tries; |
| 1773 | if (loop_tries == 5) { | 1776 | if (loop_tries == 5) { |
| 1774 | DRM_DEBUG_KMS("too many full retries, give up\n"); | 1777 | DRM_DEBUG_KMS("too many full retries, give up\n"); |
| @@ -1922,7 +1925,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) | |||
| 1922 | DP |= DP_LINK_TRAIN_OFF; | 1925 | DP |= DP_LINK_TRAIN_OFF; |
| 1923 | } | 1926 | } |
| 1924 | 1927 | ||
| 1925 | if (!HAS_PCH_CPT(dev) && | 1928 | if (HAS_PCH_IBX(dev) && |
| 1926 | I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { | 1929 | I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { |
| 1927 | struct drm_crtc *crtc = intel_dp->base.base.crtc; | 1930 | struct drm_crtc *crtc = intel_dp->base.base.crtc; |
| 1928 | 1931 | ||
| @@ -2099,25 +2102,23 @@ g4x_dp_detect(struct intel_dp *intel_dp) | |||
| 2099 | { | 2102 | { |
| 2100 | struct drm_device *dev = intel_dp->base.base.dev; | 2103 | struct drm_device *dev = intel_dp->base.base.dev; |
| 2101 | struct drm_i915_private *dev_priv = dev->dev_private; | 2104 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2102 | uint32_t temp, bit; | 2105 | uint32_t bit; |
| 2103 | 2106 | ||
| 2104 | switch (intel_dp->output_reg) { | 2107 | switch (intel_dp->output_reg) { |
| 2105 | case DP_B: | 2108 | case DP_B: |
| 2106 | bit = DPB_HOTPLUG_INT_STATUS; | 2109 | bit = DPB_HOTPLUG_LIVE_STATUS; |
| 2107 | break; | 2110 | break; |
| 2108 | case DP_C: | 2111 | case DP_C: |
| 2109 | bit = DPC_HOTPLUG_INT_STATUS; | 2112 | bit = DPC_HOTPLUG_LIVE_STATUS; |
| 2110 | break; | 2113 | break; |
| 2111 | case DP_D: | 2114 | case DP_D: |
| 2112 | bit = DPD_HOTPLUG_INT_STATUS; | 2115 | bit = DPD_HOTPLUG_LIVE_STATUS; |
| 2113 | break; | 2116 | break; |
| 2114 | default: | 2117 | default: |
| 2115 | return connector_status_unknown; | 2118 | return connector_status_unknown; |
| 2116 | } | 2119 | } |
| 2117 | 2120 | ||
| 2118 | temp = I915_READ(PORT_HOTPLUG_STAT); | 2121 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0) |
| 2119 | |||
| 2120 | if ((temp & bit) == 0) | ||
| 2121 | return connector_status_disconnected; | 2122 | return connector_status_disconnected; |
| 2122 | 2123 | ||
| 2123 | return intel_dp_detect_dpcd(intel_dp); | 2124 | return intel_dp_detect_dpcd(intel_dp); |
| @@ -2399,16 +2400,11 @@ int | |||
| 2399 | intel_trans_dp_port_sel(struct drm_crtc *crtc) | 2400 | intel_trans_dp_port_sel(struct drm_crtc *crtc) |
| 2400 | { | 2401 | { |
| 2401 | struct drm_device *dev = crtc->dev; | 2402 | struct drm_device *dev = crtc->dev; |
| 2402 | struct drm_mode_config *mode_config = &dev->mode_config; | 2403 | struct intel_encoder *encoder; |
| 2403 | struct drm_encoder *encoder; | ||
| 2404 | |||
| 2405 | list_for_each_entry(encoder, &mode_config->encoder_list, head) { | ||
| 2406 | struct intel_dp *intel_dp; | ||
| 2407 | 2404 | ||
| 2408 | if (encoder->crtc != crtc) | 2405 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 2409 | continue; | 2406 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 2410 | 2407 | ||
| 2411 | intel_dp = enc_to_intel_dp(encoder); | ||
| 2412 | if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || | 2408 | if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || |
| 2413 | intel_dp->base.type == INTEL_OUTPUT_EDP) | 2409 | intel_dp->base.type == INTEL_OUTPUT_EDP) |
| 2414 | return intel_dp->output_reg; | 2410 | return intel_dp->output_reg; |
| @@ -2520,19 +2516,19 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
| 2520 | case DP_B: | 2516 | case DP_B: |
| 2521 | case PCH_DP_B: | 2517 | case PCH_DP_B: |
| 2522 | dev_priv->hotplug_supported_mask |= | 2518 | dev_priv->hotplug_supported_mask |= |
| 2523 | HDMIB_HOTPLUG_INT_STATUS; | 2519 | DPB_HOTPLUG_INT_STATUS; |
| 2524 | name = "DPDDC-B"; | 2520 | name = "DPDDC-B"; |
| 2525 | break; | 2521 | break; |
| 2526 | case DP_C: | 2522 | case DP_C: |
| 2527 | case PCH_DP_C: | 2523 | case PCH_DP_C: |
| 2528 | dev_priv->hotplug_supported_mask |= | 2524 | dev_priv->hotplug_supported_mask |= |
| 2529 | HDMIC_HOTPLUG_INT_STATUS; | 2525 | DPC_HOTPLUG_INT_STATUS; |
| 2530 | name = "DPDDC-C"; | 2526 | name = "DPDDC-C"; |
| 2531 | break; | 2527 | break; |
| 2532 | case DP_D: | 2528 | case DP_D: |
| 2533 | case PCH_DP_D: | 2529 | case PCH_DP_D: |
| 2534 | dev_priv->hotplug_supported_mask |= | 2530 | dev_priv->hotplug_supported_mask |= |
| 2535 | HDMID_HOTPLUG_INT_STATUS; | 2531 | DPD_HOTPLUG_INT_STATUS; |
| 2536 | name = "DPDDC-D"; | 2532 | name = "DPDDC-D"; |
| 2537 | break; | 2533 | break; |
| 2538 | } | 2534 | } |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3e0918834e7e..84353559441c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -169,6 +169,7 @@ struct intel_crtc { | |||
| 169 | u8 lut_r[256], lut_g[256], lut_b[256]; | 169 | u8 lut_r[256], lut_g[256], lut_b[256]; |
| 170 | int dpms_mode; | 170 | int dpms_mode; |
| 171 | bool active; /* is the crtc on? independent of the dpms mode */ | 171 | bool active; /* is the crtc on? independent of the dpms mode */ |
| 172 | bool primary_disabled; /* is the crtc obscured by a plane? */ | ||
| 172 | bool busy; /* is scanout buffer being updated frequently? */ | 173 | bool busy; /* is scanout buffer being updated frequently? */ |
| 173 | struct timer_list idle_timer; | 174 | struct timer_list idle_timer; |
| 174 | bool lowfreq_avail; | 175 | bool lowfreq_avail; |
| @@ -176,6 +177,11 @@ struct intel_crtc { | |||
| 176 | struct intel_unpin_work *unpin_work; | 177 | struct intel_unpin_work *unpin_work; |
| 177 | int fdi_lanes; | 178 | int fdi_lanes; |
| 178 | 179 | ||
| 180 | /* Display surface base address adjustement for pageflips. Note that on | ||
| 181 | * gen4+ this only adjusts up to a tile, offsets within a tile are | ||
| 182 | * handled in the hw itself (with the TILEOFF register). */ | ||
| 183 | unsigned long dspaddr_offset; | ||
| 184 | |||
| 179 | struct drm_i915_gem_object *cursor_bo; | 185 | struct drm_i915_gem_object *cursor_bo; |
| 180 | uint32_t cursor_addr; | 186 | uint32_t cursor_addr; |
| 181 | int16_t cursor_x, cursor_y; | 187 | int16_t cursor_x, cursor_y; |
| @@ -191,7 +197,6 @@ struct intel_plane { | |||
| 191 | struct drm_plane base; | 197 | struct drm_plane base; |
| 192 | enum pipe pipe; | 198 | enum pipe pipe; |
| 193 | struct drm_i915_gem_object *obj; | 199 | struct drm_i915_gem_object *obj; |
| 194 | bool primary_disabled; | ||
| 195 | int max_downscale; | 200 | int max_downscale; |
| 196 | u32 lut_r[1024], lut_g[1024], lut_b[1024]; | 201 | u32 lut_r[1024], lut_g[1024], lut_b[1024]; |
| 197 | void (*update_plane)(struct drm_plane *plane, | 202 | void (*update_plane)(struct drm_plane *plane, |
| @@ -301,6 +306,8 @@ struct intel_hdmi { | |||
| 301 | enum hdmi_force_audio force_audio; | 306 | enum hdmi_force_audio force_audio; |
| 302 | void (*write_infoframe)(struct drm_encoder *encoder, | 307 | void (*write_infoframe)(struct drm_encoder *encoder, |
| 303 | struct dip_infoframe *frame); | 308 | struct dip_infoframe *frame); |
| 309 | void (*set_infoframes)(struct drm_encoder *encoder, | ||
| 310 | struct drm_display_mode *adjusted_mode); | ||
| 304 | }; | 311 | }; |
| 305 | 312 | ||
| 306 | static inline struct drm_crtc * | 313 | static inline struct drm_crtc * |
| @@ -335,7 +342,6 @@ struct intel_fbc_work { | |||
| 335 | }; | 342 | }; |
| 336 | 343 | ||
| 337 | int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); | 344 | int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); |
| 338 | extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus); | ||
| 339 | 345 | ||
| 340 | extern void intel_attach_force_audio_property(struct drm_connector *connector); | 346 | extern void intel_attach_force_audio_property(struct drm_connector *connector); |
| 341 | extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector); | 347 | extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector); |
| @@ -343,9 +349,6 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector) | |||
| 343 | extern void intel_crt_init(struct drm_device *dev); | 349 | extern void intel_crt_init(struct drm_device *dev); |
| 344 | extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); | 350 | extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); |
| 345 | extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); | 351 | extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); |
| 346 | extern void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, | ||
| 347 | struct drm_display_mode *adjusted_mode); | ||
| 348 | extern void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder); | ||
| 349 | extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); | 352 | extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); |
| 350 | extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, | 353 | extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, |
| 351 | bool is_sdvob); | 354 | bool is_sdvob); |
| @@ -360,6 +363,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
| 360 | struct drm_display_mode *adjusted_mode); | 363 | struct drm_display_mode *adjusted_mode); |
| 361 | extern bool intel_dpd_is_edp(struct drm_device *dev); | 364 | extern bool intel_dpd_is_edp(struct drm_device *dev); |
| 362 | extern void intel_edp_link_config(struct intel_encoder *, int *, int *); | 365 | extern void intel_edp_link_config(struct intel_encoder *, int *, int *); |
| 366 | extern int intel_edp_target_clock(struct intel_encoder *, | ||
| 367 | struct drm_display_mode *mode); | ||
| 363 | extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder); | 368 | extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder); |
| 364 | extern int intel_plane_init(struct drm_device *dev, enum pipe pipe); | 369 | extern int intel_plane_init(struct drm_device *dev, enum pipe pipe); |
| 365 | extern void intel_flush_display_plane(struct drm_i915_private *dev_priv, | 370 | extern void intel_flush_display_plane(struct drm_i915_private *dev_priv, |
| @@ -372,13 +377,14 @@ extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, | |||
| 372 | struct drm_display_mode *adjusted_mode); | 377 | struct drm_display_mode *adjusted_mode); |
| 373 | extern void intel_pch_panel_fitting(struct drm_device *dev, | 378 | extern void intel_pch_panel_fitting(struct drm_device *dev, |
| 374 | int fitting_mode, | 379 | int fitting_mode, |
| 375 | struct drm_display_mode *mode, | 380 | const struct drm_display_mode *mode, |
| 376 | struct drm_display_mode *adjusted_mode); | 381 | struct drm_display_mode *adjusted_mode); |
| 377 | extern u32 intel_panel_get_max_backlight(struct drm_device *dev); | 382 | extern u32 intel_panel_get_max_backlight(struct drm_device *dev); |
| 378 | extern u32 intel_panel_get_backlight(struct drm_device *dev); | 383 | extern u32 intel_panel_get_backlight(struct drm_device *dev); |
| 379 | extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); | 384 | extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); |
| 380 | extern int intel_panel_setup_backlight(struct drm_device *dev); | 385 | extern int intel_panel_setup_backlight(struct drm_device *dev); |
| 381 | extern void intel_panel_enable_backlight(struct drm_device *dev); | 386 | extern void intel_panel_enable_backlight(struct drm_device *dev, |
| 387 | enum pipe pipe); | ||
| 382 | extern void intel_panel_disable_backlight(struct drm_device *dev); | 388 | extern void intel_panel_disable_backlight(struct drm_device *dev); |
| 383 | extern void intel_panel_destroy_backlight(struct drm_device *dev); | 389 | extern void intel_panel_destroy_backlight(struct drm_device *dev); |
| 384 | extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); | 390 | extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); |
| @@ -423,9 +429,6 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | |||
| 423 | extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | 429 | extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, |
| 424 | u16 *blue, int regno); | 430 | u16 *blue, int regno); |
| 425 | extern void intel_enable_clock_gating(struct drm_device *dev); | 431 | extern void intel_enable_clock_gating(struct drm_device *dev); |
| 426 | extern void ironlake_disable_rc6(struct drm_device *dev); | ||
| 427 | extern void ironlake_enable_drps(struct drm_device *dev); | ||
| 428 | extern void ironlake_disable_drps(struct drm_device *dev); | ||
| 429 | 432 | ||
| 430 | extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, | 433 | extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, |
| 431 | struct drm_i915_gem_object *obj, | 434 | struct drm_i915_gem_object *obj, |
| @@ -492,10 +495,11 @@ extern void intel_update_fbc(struct drm_device *dev); | |||
| 492 | extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv); | 495 | extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv); |
| 493 | extern void intel_gpu_ips_teardown(void); | 496 | extern void intel_gpu_ips_teardown(void); |
| 494 | 497 | ||
| 495 | extern void gen6_enable_rps(struct drm_i915_private *dev_priv); | 498 | extern void intel_init_power_wells(struct drm_device *dev); |
| 496 | extern void gen6_update_ring_freq(struct drm_i915_private *dev_priv); | 499 | extern void intel_enable_gt_powersave(struct drm_device *dev); |
| 497 | extern void gen6_disable_rps(struct drm_device *dev); | 500 | extern void intel_disable_gt_powersave(struct drm_device *dev); |
| 498 | extern void intel_init_emon(struct drm_device *dev); | 501 | extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv); |
| 502 | extern void ironlake_teardown_rc6(struct drm_device *dev); | ||
| 499 | 503 | ||
| 500 | extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode); | 504 | extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode); |
| 501 | extern void intel_ddi_mode_set(struct drm_encoder *encoder, | 505 | extern void intel_ddi_mode_set(struct drm_encoder *encoder, |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 60ba50b956f2..36c542e5036b 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
| @@ -136,7 +136,7 @@ static int intel_dvo_mode_valid(struct drm_connector *connector, | |||
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | static bool intel_dvo_mode_fixup(struct drm_encoder *encoder, | 138 | static bool intel_dvo_mode_fixup(struct drm_encoder *encoder, |
| 139 | struct drm_display_mode *mode, | 139 | const struct drm_display_mode *mode, |
| 140 | struct drm_display_mode *adjusted_mode) | 140 | struct drm_display_mode *adjusted_mode) |
| 141 | { | 141 | { |
| 142 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); | 142 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index bf8690720a0c..97f673523b97 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
| @@ -65,7 +65,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
| 65 | struct drm_i915_private *dev_priv = dev->dev_private; | 65 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 66 | struct fb_info *info; | 66 | struct fb_info *info; |
| 67 | struct drm_framebuffer *fb; | 67 | struct drm_framebuffer *fb; |
| 68 | struct drm_mode_fb_cmd2 mode_cmd; | 68 | struct drm_mode_fb_cmd2 mode_cmd = {}; |
| 69 | struct drm_i915_gem_object *obj; | 69 | struct drm_i915_gem_object *obj; |
| 70 | struct device *device = &dev->pdev->dev; | 70 | struct device *device = &dev->pdev->dev; |
| 71 | int size, ret; | 71 | int size, ret; |
| @@ -140,7 +140,9 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
| 140 | info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; | 140 | info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; |
| 141 | info->fix.smem_len = size; | 141 | info->fix.smem_len = size; |
| 142 | 142 | ||
| 143 | info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size); | 143 | info->screen_base = |
| 144 | ioremap_wc(dev_priv->mm.gtt_base_addr + obj->gtt_offset, | ||
| 145 | size); | ||
| 144 | if (!info->screen_base) { | 146 | if (!info->screen_base) { |
| 145 | ret = -ENOSPC; | 147 | ret = -ENOSPC; |
| 146 | goto out_unpin; | 148 | goto out_unpin; |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 2ead3bf7c21d..98f602427eb8 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
| @@ -37,6 +37,19 @@ | |||
| 37 | #include "i915_drm.h" | 37 | #include "i915_drm.h" |
| 38 | #include "i915_drv.h" | 38 | #include "i915_drv.h" |
| 39 | 39 | ||
| 40 | static void | ||
| 41 | assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) | ||
| 42 | { | ||
| 43 | struct drm_device *dev = intel_hdmi->base.base.dev; | ||
| 44 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 45 | uint32_t enabled_bits; | ||
| 46 | |||
| 47 | enabled_bits = IS_HASWELL(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; | ||
| 48 | |||
| 49 | WARN(I915_READ(intel_hdmi->sdvox_reg) & enabled_bits, | ||
| 50 | "HDMI port enabled, expecting disabled\n"); | ||
| 51 | } | ||
| 52 | |||
| 40 | struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) | 53 | struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) |
| 41 | { | 54 | { |
| 42 | return container_of(encoder, struct intel_hdmi, base.base); | 55 | return container_of(encoder, struct intel_hdmi, base.base); |
| @@ -121,36 +134,31 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, | |||
| 121 | uint32_t *data = (uint32_t *)frame; | 134 | uint32_t *data = (uint32_t *)frame; |
| 122 | struct drm_device *dev = encoder->dev; | 135 | struct drm_device *dev = encoder->dev; |
| 123 | struct drm_i915_private *dev_priv = dev->dev_private; | 136 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 124 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 125 | u32 val = I915_READ(VIDEO_DIP_CTL); | 137 | u32 val = I915_READ(VIDEO_DIP_CTL); |
| 126 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | 138 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
| 127 | 139 | ||
| 128 | val &= ~VIDEO_DIP_PORT_MASK; | 140 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
| 129 | if (intel_hdmi->sdvox_reg == SDVOB) | ||
| 130 | val |= VIDEO_DIP_PORT_B; | ||
| 131 | else if (intel_hdmi->sdvox_reg == SDVOC) | ||
| 132 | val |= VIDEO_DIP_PORT_C; | ||
| 133 | else | ||
| 134 | return; | ||
| 135 | 141 | ||
| 136 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 142 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
| 137 | val |= g4x_infoframe_index(frame); | 143 | val |= g4x_infoframe_index(frame); |
| 138 | 144 | ||
| 139 | val &= ~g4x_infoframe_enable(frame); | 145 | val &= ~g4x_infoframe_enable(frame); |
| 140 | val |= VIDEO_DIP_ENABLE; | ||
| 141 | 146 | ||
| 142 | I915_WRITE(VIDEO_DIP_CTL, val); | 147 | I915_WRITE(VIDEO_DIP_CTL, val); |
| 143 | 148 | ||
| 149 | mmiowb(); | ||
| 144 | for (i = 0; i < len; i += 4) { | 150 | for (i = 0; i < len; i += 4) { |
| 145 | I915_WRITE(VIDEO_DIP_DATA, *data); | 151 | I915_WRITE(VIDEO_DIP_DATA, *data); |
| 146 | data++; | 152 | data++; |
| 147 | } | 153 | } |
| 154 | mmiowb(); | ||
| 148 | 155 | ||
| 149 | val |= g4x_infoframe_enable(frame); | 156 | val |= g4x_infoframe_enable(frame); |
| 150 | val &= ~VIDEO_DIP_FREQ_MASK; | 157 | val &= ~VIDEO_DIP_FREQ_MASK; |
| 151 | val |= VIDEO_DIP_FREQ_VSYNC; | 158 | val |= VIDEO_DIP_FREQ_VSYNC; |
| 152 | 159 | ||
| 153 | I915_WRITE(VIDEO_DIP_CTL, val); | 160 | I915_WRITE(VIDEO_DIP_CTL, val); |
| 161 | POSTING_READ(VIDEO_DIP_CTL); | ||
| 154 | } | 162 | } |
| 155 | 163 | ||
| 156 | static void ibx_write_infoframe(struct drm_encoder *encoder, | 164 | static void ibx_write_infoframe(struct drm_encoder *encoder, |
| @@ -160,46 +168,32 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, | |||
| 160 | struct drm_device *dev = encoder->dev; | 168 | struct drm_device *dev = encoder->dev; |
| 161 | struct drm_i915_private *dev_priv = dev->dev_private; | 169 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 162 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 170 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
| 163 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 164 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); | 171 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
| 165 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | 172 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
| 166 | u32 val = I915_READ(reg); | 173 | u32 val = I915_READ(reg); |
| 167 | 174 | ||
| 168 | val &= ~VIDEO_DIP_PORT_MASK; | 175 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
| 169 | switch (intel_hdmi->sdvox_reg) { | ||
| 170 | case HDMIB: | ||
| 171 | val |= VIDEO_DIP_PORT_B; | ||
| 172 | break; | ||
| 173 | case HDMIC: | ||
| 174 | val |= VIDEO_DIP_PORT_C; | ||
| 175 | break; | ||
| 176 | case HDMID: | ||
| 177 | val |= VIDEO_DIP_PORT_D; | ||
| 178 | break; | ||
| 179 | default: | ||
| 180 | return; | ||
| 181 | } | ||
| 182 | |||
| 183 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
| 184 | 176 | ||
| 185 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 177 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
| 186 | val |= g4x_infoframe_index(frame); | 178 | val |= g4x_infoframe_index(frame); |
| 187 | 179 | ||
| 188 | val &= ~g4x_infoframe_enable(frame); | 180 | val &= ~g4x_infoframe_enable(frame); |
| 189 | val |= VIDEO_DIP_ENABLE; | ||
| 190 | 181 | ||
| 191 | I915_WRITE(reg, val); | 182 | I915_WRITE(reg, val); |
| 192 | 183 | ||
| 184 | mmiowb(); | ||
| 193 | for (i = 0; i < len; i += 4) { | 185 | for (i = 0; i < len; i += 4) { |
| 194 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); | 186 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); |
| 195 | data++; | 187 | data++; |
| 196 | } | 188 | } |
| 189 | mmiowb(); | ||
| 197 | 190 | ||
| 198 | val |= g4x_infoframe_enable(frame); | 191 | val |= g4x_infoframe_enable(frame); |
| 199 | val &= ~VIDEO_DIP_FREQ_MASK; | 192 | val &= ~VIDEO_DIP_FREQ_MASK; |
| 200 | val |= VIDEO_DIP_FREQ_VSYNC; | 193 | val |= VIDEO_DIP_FREQ_VSYNC; |
| 201 | 194 | ||
| 202 | I915_WRITE(reg, val); | 195 | I915_WRITE(reg, val); |
| 196 | POSTING_READ(reg); | ||
| 203 | } | 197 | } |
| 204 | 198 | ||
| 205 | static void cpt_write_infoframe(struct drm_encoder *encoder, | 199 | static void cpt_write_infoframe(struct drm_encoder *encoder, |
| @@ -213,32 +207,31 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, | |||
| 213 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | 207 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
| 214 | u32 val = I915_READ(reg); | 208 | u32 val = I915_READ(reg); |
| 215 | 209 | ||
| 216 | intel_wait_for_vblank(dev, intel_crtc->pipe); | 210 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
| 217 | 211 | ||
| 218 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 212 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
| 219 | val |= g4x_infoframe_index(frame); | 213 | val |= g4x_infoframe_index(frame); |
| 220 | 214 | ||
| 221 | /* The DIP control register spec says that we need to update the AVI | 215 | /* The DIP control register spec says that we need to update the AVI |
| 222 | * infoframe without clearing its enable bit */ | 216 | * infoframe without clearing its enable bit */ |
| 223 | if (frame->type == DIP_TYPE_AVI) | 217 | if (frame->type != DIP_TYPE_AVI) |
| 224 | val |= VIDEO_DIP_ENABLE_AVI; | ||
| 225 | else | ||
| 226 | val &= ~g4x_infoframe_enable(frame); | 218 | val &= ~g4x_infoframe_enable(frame); |
| 227 | 219 | ||
| 228 | val |= VIDEO_DIP_ENABLE; | ||
| 229 | |||
| 230 | I915_WRITE(reg, val); | 220 | I915_WRITE(reg, val); |
| 231 | 221 | ||
| 222 | mmiowb(); | ||
| 232 | for (i = 0; i < len; i += 4) { | 223 | for (i = 0; i < len; i += 4) { |
| 233 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); | 224 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); |
| 234 | data++; | 225 | data++; |
| 235 | } | 226 | } |
| 227 | mmiowb(); | ||
| 236 | 228 | ||
| 237 | val |= g4x_infoframe_enable(frame); | 229 | val |= g4x_infoframe_enable(frame); |
| 238 | val &= ~VIDEO_DIP_FREQ_MASK; | 230 | val &= ~VIDEO_DIP_FREQ_MASK; |
| 239 | val |= VIDEO_DIP_FREQ_VSYNC; | 231 | val |= VIDEO_DIP_FREQ_VSYNC; |
| 240 | 232 | ||
| 241 | I915_WRITE(reg, val); | 233 | I915_WRITE(reg, val); |
| 234 | POSTING_READ(reg); | ||
| 242 | } | 235 | } |
| 243 | 236 | ||
| 244 | static void vlv_write_infoframe(struct drm_encoder *encoder, | 237 | static void vlv_write_infoframe(struct drm_encoder *encoder, |
| @@ -252,26 +245,28 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, | |||
| 252 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | 245 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
| 253 | u32 val = I915_READ(reg); | 246 | u32 val = I915_READ(reg); |
| 254 | 247 | ||
| 255 | intel_wait_for_vblank(dev, intel_crtc->pipe); | 248 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
| 256 | 249 | ||
| 257 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 250 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
| 258 | val |= g4x_infoframe_index(frame); | 251 | val |= g4x_infoframe_index(frame); |
| 259 | 252 | ||
| 260 | val &= ~g4x_infoframe_enable(frame); | 253 | val &= ~g4x_infoframe_enable(frame); |
| 261 | val |= VIDEO_DIP_ENABLE; | ||
| 262 | 254 | ||
| 263 | I915_WRITE(reg, val); | 255 | I915_WRITE(reg, val); |
| 264 | 256 | ||
| 257 | mmiowb(); | ||
| 265 | for (i = 0; i < len; i += 4) { | 258 | for (i = 0; i < len; i += 4) { |
| 266 | I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data); | 259 | I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data); |
| 267 | data++; | 260 | data++; |
| 268 | } | 261 | } |
| 262 | mmiowb(); | ||
| 269 | 263 | ||
| 270 | val |= g4x_infoframe_enable(frame); | 264 | val |= g4x_infoframe_enable(frame); |
| 271 | val &= ~VIDEO_DIP_FREQ_MASK; | 265 | val &= ~VIDEO_DIP_FREQ_MASK; |
| 272 | val |= VIDEO_DIP_FREQ_VSYNC; | 266 | val |= VIDEO_DIP_FREQ_VSYNC; |
| 273 | 267 | ||
| 274 | I915_WRITE(reg, val); | 268 | I915_WRITE(reg, val); |
| 269 | POSTING_READ(reg); | ||
| 275 | } | 270 | } |
| 276 | 271 | ||
| 277 | static void hsw_write_infoframe(struct drm_encoder *encoder, | 272 | static void hsw_write_infoframe(struct drm_encoder *encoder, |
| @@ -289,18 +284,19 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, | |||
| 289 | if (data_reg == 0) | 284 | if (data_reg == 0) |
| 290 | return; | 285 | return; |
| 291 | 286 | ||
| 292 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
| 293 | |||
| 294 | val &= ~hsw_infoframe_enable(frame); | 287 | val &= ~hsw_infoframe_enable(frame); |
| 295 | I915_WRITE(ctl_reg, val); | 288 | I915_WRITE(ctl_reg, val); |
| 296 | 289 | ||
| 290 | mmiowb(); | ||
| 297 | for (i = 0; i < len; i += 4) { | 291 | for (i = 0; i < len; i += 4) { |
| 298 | I915_WRITE(data_reg + i, *data); | 292 | I915_WRITE(data_reg + i, *data); |
| 299 | data++; | 293 | data++; |
| 300 | } | 294 | } |
| 295 | mmiowb(); | ||
| 301 | 296 | ||
| 302 | val |= hsw_infoframe_enable(frame); | 297 | val |= hsw_infoframe_enable(frame); |
| 303 | I915_WRITE(ctl_reg, val); | 298 | I915_WRITE(ctl_reg, val); |
| 299 | POSTING_READ(ctl_reg); | ||
| 304 | } | 300 | } |
| 305 | 301 | ||
| 306 | static void intel_set_infoframe(struct drm_encoder *encoder, | 302 | static void intel_set_infoframe(struct drm_encoder *encoder, |
| @@ -308,14 +304,11 @@ static void intel_set_infoframe(struct drm_encoder *encoder, | |||
| 308 | { | 304 | { |
| 309 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 305 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
| 310 | 306 | ||
| 311 | if (!intel_hdmi->has_hdmi_sink) | ||
| 312 | return; | ||
| 313 | |||
| 314 | intel_dip_infoframe_csum(frame); | 307 | intel_dip_infoframe_csum(frame); |
| 315 | intel_hdmi->write_infoframe(encoder, frame); | 308 | intel_hdmi->write_infoframe(encoder, frame); |
| 316 | } | 309 | } |
| 317 | 310 | ||
| 318 | void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, | 311 | static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, |
| 319 | struct drm_display_mode *adjusted_mode) | 312 | struct drm_display_mode *adjusted_mode) |
| 320 | { | 313 | { |
| 321 | struct dip_infoframe avi_if = { | 314 | struct dip_infoframe avi_if = { |
| @@ -330,7 +323,7 @@ void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, | |||
| 330 | intel_set_infoframe(encoder, &avi_if); | 323 | intel_set_infoframe(encoder, &avi_if); |
| 331 | } | 324 | } |
| 332 | 325 | ||
| 333 | void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) | 326 | static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) |
| 334 | { | 327 | { |
| 335 | struct dip_infoframe spd_if; | 328 | struct dip_infoframe spd_if; |
| 336 | 329 | ||
| @@ -345,6 +338,223 @@ void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) | |||
| 345 | intel_set_infoframe(encoder, &spd_if); | 338 | intel_set_infoframe(encoder, &spd_if); |
| 346 | } | 339 | } |
| 347 | 340 | ||
| 341 | static void g4x_set_infoframes(struct drm_encoder *encoder, | ||
| 342 | struct drm_display_mode *adjusted_mode) | ||
| 343 | { | ||
| 344 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
| 345 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 346 | u32 reg = VIDEO_DIP_CTL; | ||
| 347 | u32 val = I915_READ(reg); | ||
| 348 | u32 port; | ||
| 349 | |||
| 350 | assert_hdmi_port_disabled(intel_hdmi); | ||
| 351 | |||
| 352 | /* If the registers were not initialized yet, they might be zeroes, | ||
| 353 | * which means we're selecting the AVI DIP and we're setting its | ||
| 354 | * frequency to once. This seems to really confuse the HW and make | ||
| 355 | * things stop working (the register spec says the AVI always needs to | ||
| 356 | * be sent every VSync). So here we avoid writing to the register more | ||
| 357 | * than we need and also explicitly select the AVI DIP and explicitly | ||
| 358 | * set its frequency to every VSync. Avoiding to write it twice seems to | ||
| 359 | * be enough to solve the problem, but being defensive shouldn't hurt us | ||
| 360 | * either. */ | ||
| 361 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; | ||
| 362 | |||
| 363 | if (!intel_hdmi->has_hdmi_sink) { | ||
| 364 | if (!(val & VIDEO_DIP_ENABLE)) | ||
| 365 | return; | ||
| 366 | val &= ~VIDEO_DIP_ENABLE; | ||
| 367 | I915_WRITE(reg, val); | ||
| 368 | POSTING_READ(reg); | ||
| 369 | return; | ||
| 370 | } | ||
| 371 | |||
| 372 | switch (intel_hdmi->sdvox_reg) { | ||
| 373 | case SDVOB: | ||
| 374 | port = VIDEO_DIP_PORT_B; | ||
| 375 | break; | ||
| 376 | case SDVOC: | ||
| 377 | port = VIDEO_DIP_PORT_C; | ||
| 378 | break; | ||
| 379 | default: | ||
| 380 | return; | ||
| 381 | } | ||
| 382 | |||
| 383 | if (port != (val & VIDEO_DIP_PORT_MASK)) { | ||
| 384 | if (val & VIDEO_DIP_ENABLE) { | ||
| 385 | val &= ~VIDEO_DIP_ENABLE; | ||
| 386 | I915_WRITE(reg, val); | ||
| 387 | POSTING_READ(reg); | ||
| 388 | } | ||
| 389 | val &= ~VIDEO_DIP_PORT_MASK; | ||
| 390 | val |= port; | ||
| 391 | } | ||
| 392 | |||
| 393 | val |= VIDEO_DIP_ENABLE; | ||
| 394 | val &= ~VIDEO_DIP_ENABLE_VENDOR; | ||
| 395 | |||
| 396 | I915_WRITE(reg, val); | ||
| 397 | POSTING_READ(reg); | ||
| 398 | |||
| 399 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | ||
| 400 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 401 | } | ||
| 402 | |||
| 403 | static void ibx_set_infoframes(struct drm_encoder *encoder, | ||
| 404 | struct drm_display_mode *adjusted_mode) | ||
| 405 | { | ||
| 406 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
| 407 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 408 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 409 | u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); | ||
| 410 | u32 val = I915_READ(reg); | ||
| 411 | u32 port; | ||
| 412 | |||
| 413 | assert_hdmi_port_disabled(intel_hdmi); | ||
| 414 | |||
| 415 | /* See the big comment in g4x_set_infoframes() */ | ||
| 416 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; | ||
| 417 | |||
| 418 | if (!intel_hdmi->has_hdmi_sink) { | ||
| 419 | if (!(val & VIDEO_DIP_ENABLE)) | ||
| 420 | return; | ||
| 421 | val &= ~VIDEO_DIP_ENABLE; | ||
| 422 | I915_WRITE(reg, val); | ||
| 423 | POSTING_READ(reg); | ||
| 424 | return; | ||
| 425 | } | ||
| 426 | |||
| 427 | switch (intel_hdmi->sdvox_reg) { | ||
| 428 | case HDMIB: | ||
| 429 | port = VIDEO_DIP_PORT_B; | ||
| 430 | break; | ||
| 431 | case HDMIC: | ||
| 432 | port = VIDEO_DIP_PORT_C; | ||
| 433 | break; | ||
| 434 | case HDMID: | ||
| 435 | port = VIDEO_DIP_PORT_D; | ||
| 436 | break; | ||
| 437 | default: | ||
| 438 | return; | ||
| 439 | } | ||
| 440 | |||
| 441 | if (port != (val & VIDEO_DIP_PORT_MASK)) { | ||
| 442 | if (val & VIDEO_DIP_ENABLE) { | ||
| 443 | val &= ~VIDEO_DIP_ENABLE; | ||
| 444 | I915_WRITE(reg, val); | ||
| 445 | POSTING_READ(reg); | ||
| 446 | } | ||
| 447 | val &= ~VIDEO_DIP_PORT_MASK; | ||
| 448 | val |= port; | ||
| 449 | } | ||
| 450 | |||
| 451 | val |= VIDEO_DIP_ENABLE; | ||
| 452 | val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | | ||
| 453 | VIDEO_DIP_ENABLE_GCP); | ||
| 454 | |||
| 455 | I915_WRITE(reg, val); | ||
| 456 | POSTING_READ(reg); | ||
| 457 | |||
| 458 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | ||
| 459 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 460 | } | ||
| 461 | |||
| 462 | static void cpt_set_infoframes(struct drm_encoder *encoder, | ||
| 463 | struct drm_display_mode *adjusted_mode) | ||
| 464 | { | ||
| 465 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
| 466 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 467 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 468 | u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); | ||
| 469 | u32 val = I915_READ(reg); | ||
| 470 | |||
| 471 | assert_hdmi_port_disabled(intel_hdmi); | ||
| 472 | |||
| 473 | /* See the big comment in g4x_set_infoframes() */ | ||
| 474 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; | ||
| 475 | |||
| 476 | if (!intel_hdmi->has_hdmi_sink) { | ||
| 477 | if (!(val & VIDEO_DIP_ENABLE)) | ||
| 478 | return; | ||
| 479 | val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI); | ||
| 480 | I915_WRITE(reg, val); | ||
| 481 | POSTING_READ(reg); | ||
| 482 | return; | ||
| 483 | } | ||
| 484 | |||
| 485 | /* Set both together, unset both together: see the spec. */ | ||
| 486 | val |= VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI; | ||
| 487 | val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | | ||
| 488 | VIDEO_DIP_ENABLE_GCP); | ||
| 489 | |||
| 490 | I915_WRITE(reg, val); | ||
| 491 | POSTING_READ(reg); | ||
| 492 | |||
| 493 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | ||
| 494 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 495 | } | ||
| 496 | |||
| 497 | static void vlv_set_infoframes(struct drm_encoder *encoder, | ||
| 498 | struct drm_display_mode *adjusted_mode) | ||
| 499 | { | ||
| 500 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
| 501 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 502 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 503 | u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); | ||
| 504 | u32 val = I915_READ(reg); | ||
| 505 | |||
| 506 | assert_hdmi_port_disabled(intel_hdmi); | ||
| 507 | |||
| 508 | /* See the big comment in g4x_set_infoframes() */ | ||
| 509 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; | ||
| 510 | |||
| 511 | if (!intel_hdmi->has_hdmi_sink) { | ||
| 512 | if (!(val & VIDEO_DIP_ENABLE)) | ||
| 513 | return; | ||
| 514 | val &= ~VIDEO_DIP_ENABLE; | ||
| 515 | I915_WRITE(reg, val); | ||
| 516 | POSTING_READ(reg); | ||
| 517 | return; | ||
| 518 | } | ||
| 519 | |||
| 520 | val |= VIDEO_DIP_ENABLE; | ||
| 521 | val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | | ||
| 522 | VIDEO_DIP_ENABLE_GCP); | ||
| 523 | |||
| 524 | I915_WRITE(reg, val); | ||
| 525 | POSTING_READ(reg); | ||
| 526 | |||
| 527 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | ||
| 528 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 529 | } | ||
| 530 | |||
| 531 | static void hsw_set_infoframes(struct drm_encoder *encoder, | ||
| 532 | struct drm_display_mode *adjusted_mode) | ||
| 533 | { | ||
| 534 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
| 535 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 536 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 537 | u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); | ||
| 538 | u32 val = I915_READ(reg); | ||
| 539 | |||
| 540 | assert_hdmi_port_disabled(intel_hdmi); | ||
| 541 | |||
| 542 | if (!intel_hdmi->has_hdmi_sink) { | ||
| 543 | I915_WRITE(reg, 0); | ||
| 544 | POSTING_READ(reg); | ||
| 545 | return; | ||
| 546 | } | ||
| 547 | |||
| 548 | val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_GCP_HSW | | ||
| 549 | VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW); | ||
| 550 | |||
| 551 | I915_WRITE(reg, val); | ||
| 552 | POSTING_READ(reg); | ||
| 553 | |||
| 554 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | ||
| 555 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 556 | } | ||
| 557 | |||
| 348 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, | 558 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, |
| 349 | struct drm_display_mode *mode, | 559 | struct drm_display_mode *mode, |
| 350 | struct drm_display_mode *adjusted_mode) | 560 | struct drm_display_mode *adjusted_mode) |
| @@ -355,7 +565,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, | |||
| 355 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 565 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
| 356 | u32 sdvox; | 566 | u32 sdvox; |
| 357 | 567 | ||
| 358 | sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE; | 568 | sdvox = SDVO_ENCODING_HDMI; |
| 359 | if (!HAS_PCH_SPLIT(dev)) | 569 | if (!HAS_PCH_SPLIT(dev)) |
| 360 | sdvox |= intel_hdmi->color_range; | 570 | sdvox |= intel_hdmi->color_range; |
| 361 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) | 571 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
| @@ -382,14 +592,13 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, | |||
| 382 | 592 | ||
| 383 | if (HAS_PCH_CPT(dev)) | 593 | if (HAS_PCH_CPT(dev)) |
| 384 | sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe); | 594 | sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe); |
| 385 | else if (intel_crtc->pipe == 1) | 595 | else if (intel_crtc->pipe == PIPE_B) |
| 386 | sdvox |= SDVO_PIPE_B_SELECT; | 596 | sdvox |= SDVO_PIPE_B_SELECT; |
| 387 | 597 | ||
| 388 | I915_WRITE(intel_hdmi->sdvox_reg, sdvox); | 598 | I915_WRITE(intel_hdmi->sdvox_reg, sdvox); |
| 389 | POSTING_READ(intel_hdmi->sdvox_reg); | 599 | POSTING_READ(intel_hdmi->sdvox_reg); |
| 390 | 600 | ||
| 391 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | 601 | intel_hdmi->set_infoframes(encoder, adjusted_mode); |
| 392 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 393 | } | 602 | } |
| 394 | 603 | ||
| 395 | static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | 604 | static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) |
| @@ -405,6 +614,36 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | |||
| 405 | 614 | ||
| 406 | temp = I915_READ(intel_hdmi->sdvox_reg); | 615 | temp = I915_READ(intel_hdmi->sdvox_reg); |
| 407 | 616 | ||
| 617 | /* HW workaround for IBX, we need to move the port to transcoder A | ||
| 618 | * before disabling it. */ | ||
| 619 | if (HAS_PCH_IBX(dev)) { | ||
| 620 | struct drm_crtc *crtc = encoder->crtc; | ||
| 621 | int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1; | ||
| 622 | |||
| 623 | if (mode != DRM_MODE_DPMS_ON) { | ||
| 624 | if (temp & SDVO_PIPE_B_SELECT) { | ||
| 625 | temp &= ~SDVO_PIPE_B_SELECT; | ||
| 626 | I915_WRITE(intel_hdmi->sdvox_reg, temp); | ||
| 627 | POSTING_READ(intel_hdmi->sdvox_reg); | ||
| 628 | |||
| 629 | /* Again we need to write this twice. */ | ||
| 630 | I915_WRITE(intel_hdmi->sdvox_reg, temp); | ||
| 631 | POSTING_READ(intel_hdmi->sdvox_reg); | ||
| 632 | |||
| 633 | /* Transcoder selection bits only update | ||
| 634 | * effectively on vblank. */ | ||
| 635 | if (crtc) | ||
| 636 | intel_wait_for_vblank(dev, pipe); | ||
| 637 | else | ||
| 638 | msleep(50); | ||
| 639 | } | ||
| 640 | } else { | ||
| 641 | /* Restore the transcoder select bit. */ | ||
| 642 | if (pipe == PIPE_B) | ||
| 643 | enable_bits |= SDVO_PIPE_B_SELECT; | ||
| 644 | } | ||
| 645 | } | ||
| 646 | |||
| 408 | /* HW workaround, need to toggle enable bit off and on for 12bpc, but | 647 | /* HW workaround, need to toggle enable bit off and on for 12bpc, but |
| 409 | * we do this anyway which shows more stable in testing. | 648 | * we do this anyway which shows more stable in testing. |
| 410 | */ | 649 | */ |
| @@ -446,12 +685,33 @@ static int intel_hdmi_mode_valid(struct drm_connector *connector, | |||
| 446 | } | 685 | } |
| 447 | 686 | ||
| 448 | static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | 687 | static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, |
| 449 | struct drm_display_mode *mode, | 688 | const struct drm_display_mode *mode, |
| 450 | struct drm_display_mode *adjusted_mode) | 689 | struct drm_display_mode *adjusted_mode) |
| 451 | { | 690 | { |
| 452 | return true; | 691 | return true; |
| 453 | } | 692 | } |
| 454 | 693 | ||
| 694 | static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi) | ||
| 695 | { | ||
| 696 | struct drm_device *dev = intel_hdmi->base.base.dev; | ||
| 697 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 698 | uint32_t bit; | ||
| 699 | |||
| 700 | switch (intel_hdmi->sdvox_reg) { | ||
| 701 | case SDVOB: | ||
| 702 | bit = HDMIB_HOTPLUG_LIVE_STATUS; | ||
| 703 | break; | ||
| 704 | case SDVOC: | ||
| 705 | bit = HDMIC_HOTPLUG_LIVE_STATUS; | ||
| 706 | break; | ||
| 707 | default: | ||
| 708 | bit = 0; | ||
| 709 | break; | ||
| 710 | } | ||
| 711 | |||
| 712 | return I915_READ(PORT_HOTPLUG_STAT) & bit; | ||
| 713 | } | ||
| 714 | |||
| 455 | static enum drm_connector_status | 715 | static enum drm_connector_status |
| 456 | intel_hdmi_detect(struct drm_connector *connector, bool force) | 716 | intel_hdmi_detect(struct drm_connector *connector, bool force) |
| 457 | { | 717 | { |
| @@ -460,6 +720,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) | |||
| 460 | struct edid *edid; | 720 | struct edid *edid; |
| 461 | enum drm_connector_status status = connector_status_disconnected; | 721 | enum drm_connector_status status = connector_status_disconnected; |
| 462 | 722 | ||
| 723 | if (IS_G4X(connector->dev) && !g4x_hdmi_connected(intel_hdmi)) | ||
| 724 | return status; | ||
| 725 | |||
| 463 | intel_hdmi->has_hdmi_sink = false; | 726 | intel_hdmi->has_hdmi_sink = false; |
| 464 | intel_hdmi->has_audio = false; | 727 | intel_hdmi->has_audio = false; |
| 465 | edid = drm_get_edid(connector, | 728 | edid = drm_get_edid(connector, |
| @@ -633,7 +896,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
| 633 | struct intel_encoder *intel_encoder; | 896 | struct intel_encoder *intel_encoder; |
| 634 | struct intel_connector *intel_connector; | 897 | struct intel_connector *intel_connector; |
| 635 | struct intel_hdmi *intel_hdmi; | 898 | struct intel_hdmi *intel_hdmi; |
| 636 | int i; | ||
| 637 | 899 | ||
| 638 | intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); | 900 | intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); |
| 639 | if (!intel_hdmi) | 901 | if (!intel_hdmi) |
| @@ -710,26 +972,19 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
| 710 | 972 | ||
| 711 | if (!HAS_PCH_SPLIT(dev)) { | 973 | if (!HAS_PCH_SPLIT(dev)) { |
| 712 | intel_hdmi->write_infoframe = g4x_write_infoframe; | 974 | intel_hdmi->write_infoframe = g4x_write_infoframe; |
| 713 | I915_WRITE(VIDEO_DIP_CTL, 0); | 975 | intel_hdmi->set_infoframes = g4x_set_infoframes; |
| 714 | } else if (IS_VALLEYVIEW(dev)) { | 976 | } else if (IS_VALLEYVIEW(dev)) { |
| 715 | intel_hdmi->write_infoframe = vlv_write_infoframe; | 977 | intel_hdmi->write_infoframe = vlv_write_infoframe; |
| 716 | for_each_pipe(i) | 978 | intel_hdmi->set_infoframes = vlv_set_infoframes; |
| 717 | I915_WRITE(VLV_TVIDEO_DIP_CTL(i), 0); | ||
| 718 | } else if (IS_HASWELL(dev)) { | 979 | } else if (IS_HASWELL(dev)) { |
| 719 | /* FIXME: Haswell has a new set of DIP frame registers, but we are | ||
| 720 | * just doing the minimal required for HDMI to work at this stage. | ||
| 721 | */ | ||
| 722 | intel_hdmi->write_infoframe = hsw_write_infoframe; | 980 | intel_hdmi->write_infoframe = hsw_write_infoframe; |
| 723 | for_each_pipe(i) | 981 | intel_hdmi->set_infoframes = hsw_set_infoframes; |
| 724 | I915_WRITE(HSW_TVIDEO_DIP_CTL(i), 0); | ||
| 725 | } else if (HAS_PCH_IBX(dev)) { | 982 | } else if (HAS_PCH_IBX(dev)) { |
| 726 | intel_hdmi->write_infoframe = ibx_write_infoframe; | 983 | intel_hdmi->write_infoframe = ibx_write_infoframe; |
| 727 | for_each_pipe(i) | 984 | intel_hdmi->set_infoframes = ibx_set_infoframes; |
| 728 | I915_WRITE(TVIDEO_DIP_CTL(i), 0); | ||
| 729 | } else { | 985 | } else { |
| 730 | intel_hdmi->write_infoframe = cpt_write_infoframe; | 986 | intel_hdmi->write_infoframe = cpt_write_infoframe; |
| 731 | for_each_pipe(i) | 987 | intel_hdmi->set_infoframes = cpt_set_infoframes; |
| 732 | I915_WRITE(TVIDEO_DIP_CTL(i), 0); | ||
| 733 | } | 988 | } |
| 734 | 989 | ||
| 735 | if (IS_HASWELL(dev)) | 990 | if (IS_HASWELL(dev)) |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 08eb04c787e8..e05c0d3e3440 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -71,6 +71,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector) | |||
| 71 | static void intel_lvds_enable(struct intel_lvds *intel_lvds) | 71 | static void intel_lvds_enable(struct intel_lvds *intel_lvds) |
| 72 | { | 72 | { |
| 73 | struct drm_device *dev = intel_lvds->base.base.dev; | 73 | struct drm_device *dev = intel_lvds->base.base.dev; |
| 74 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_lvds->base.base.crtc); | ||
| 74 | struct drm_i915_private *dev_priv = dev->dev_private; | 75 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 75 | u32 ctl_reg, lvds_reg, stat_reg; | 76 | u32 ctl_reg, lvds_reg, stat_reg; |
| 76 | 77 | ||
| @@ -107,7 +108,7 @@ static void intel_lvds_enable(struct intel_lvds *intel_lvds) | |||
| 107 | if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) | 108 | if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) |
| 108 | DRM_ERROR("timed out waiting for panel to power on\n"); | 109 | DRM_ERROR("timed out waiting for panel to power on\n"); |
| 109 | 110 | ||
| 110 | intel_panel_enable_backlight(dev); | 111 | intel_panel_enable_backlight(dev, intel_crtc->pipe); |
| 111 | } | 112 | } |
| 112 | 113 | ||
| 113 | static void intel_lvds_disable(struct intel_lvds *intel_lvds) | 114 | static void intel_lvds_disable(struct intel_lvds *intel_lvds) |
| @@ -228,14 +229,14 @@ static inline u32 panel_fitter_scaling(u32 source, u32 target) | |||
| 228 | } | 229 | } |
| 229 | 230 | ||
| 230 | static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | 231 | static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, |
| 231 | struct drm_display_mode *mode, | 232 | const struct drm_display_mode *mode, |
| 232 | struct drm_display_mode *adjusted_mode) | 233 | struct drm_display_mode *adjusted_mode) |
| 233 | { | 234 | { |
| 234 | struct drm_device *dev = encoder->dev; | 235 | struct drm_device *dev = encoder->dev; |
| 235 | struct drm_i915_private *dev_priv = dev->dev_private; | 236 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 236 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 237 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
| 237 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); | 238 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); |
| 238 | struct drm_encoder *tmp_encoder; | 239 | struct intel_encoder *tmp_encoder; |
| 239 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; | 240 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
| 240 | int pipe; | 241 | int pipe; |
| 241 | 242 | ||
| @@ -246,8 +247,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
| 246 | } | 247 | } |
| 247 | 248 | ||
| 248 | /* Should never happen!! */ | 249 | /* Should never happen!! */ |
| 249 | list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) { | 250 | for_each_encoder_on_crtc(dev, encoder->crtc, tmp_encoder) { |
| 250 | if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) { | 251 | if (&tmp_encoder->base != encoder) { |
| 251 | DRM_ERROR("Can't enable LVDS and another " | 252 | DRM_ERROR("Can't enable LVDS and another " |
| 252 | "encoder on the same pipe\n"); | 253 | "encoder on the same pipe\n"); |
| 253 | return false; | 254 | return false; |
| @@ -408,13 +409,7 @@ static void intel_lvds_prepare(struct drm_encoder *encoder) | |||
| 408 | { | 409 | { |
| 409 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); | 410 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); |
| 410 | 411 | ||
| 411 | /* | 412 | intel_lvds_disable(intel_lvds); |
| 412 | * Prior to Ironlake, we must disable the pipe if we want to adjust | ||
| 413 | * the panel fitter. However at all other times we can just reset | ||
| 414 | * the registers regardless. | ||
| 415 | */ | ||
| 416 | if (!HAS_PCH_SPLIT(encoder->dev) && intel_lvds->pfit_dirty) | ||
| 417 | intel_lvds_disable(intel_lvds); | ||
| 418 | } | 413 | } |
| 419 | 414 | ||
| 420 | static void intel_lvds_commit(struct drm_encoder *encoder) | 415 | static void intel_lvds_commit(struct drm_encoder *encoder) |
| @@ -777,6 +772,14 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
| 777 | DMI_MATCH(DMI_BOARD_NAME, "MS-7469"), | 772 | DMI_MATCH(DMI_BOARD_NAME, "MS-7469"), |
| 778 | }, | 773 | }, |
| 779 | }, | 774 | }, |
| 775 | { | ||
| 776 | .callback = intel_no_lvds_dmi_callback, | ||
| 777 | .ident = "ZOTAC ZBOXSD-ID12/ID13", | ||
| 778 | .matches = { | ||
| 779 | DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"), | ||
| 780 | DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), | ||
| 781 | }, | ||
| 782 | }, | ||
| 780 | 783 | ||
| 781 | { } /* terminating entry */ | 784 | { } /* terminating entry */ |
| 782 | }; | 785 | }; |
| @@ -967,6 +970,8 @@ bool intel_lvds_init(struct drm_device *dev) | |||
| 967 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); | 970 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); |
| 968 | if (HAS_PCH_SPLIT(dev)) | 971 | if (HAS_PCH_SPLIT(dev)) |
| 969 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); | 972 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
| 973 | else if (IS_GEN4(dev)) | ||
| 974 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); | ||
| 970 | else | 975 | else |
| 971 | intel_encoder->crtc_mask = (1 << 1); | 976 | intel_encoder->crtc_mask = (1 << 1); |
| 972 | 977 | ||
| @@ -1074,35 +1079,14 @@ bool intel_lvds_init(struct drm_device *dev) | |||
| 1074 | goto failed; | 1079 | goto failed; |
| 1075 | 1080 | ||
| 1076 | out: | 1081 | out: |
| 1082 | /* | ||
| 1083 | * Unlock registers and just | ||
| 1084 | * leave them unlocked | ||
| 1085 | */ | ||
| 1077 | if (HAS_PCH_SPLIT(dev)) { | 1086 | if (HAS_PCH_SPLIT(dev)) { |
| 1078 | u32 pwm; | ||
| 1079 | |||
| 1080 | pipe = (I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) ? 1 : 0; | ||
| 1081 | |||
| 1082 | /* make sure PWM is enabled and locked to the LVDS pipe */ | ||
| 1083 | pwm = I915_READ(BLC_PWM_CPU_CTL2); | ||
| 1084 | if (pipe == 0 && (pwm & PWM_PIPE_B)) | ||
| 1085 | I915_WRITE(BLC_PWM_CPU_CTL2, pwm & ~PWM_ENABLE); | ||
| 1086 | if (pipe) | ||
| 1087 | pwm |= PWM_PIPE_B; | ||
| 1088 | else | ||
| 1089 | pwm &= ~PWM_PIPE_B; | ||
| 1090 | I915_WRITE(BLC_PWM_CPU_CTL2, pwm | PWM_ENABLE); | ||
| 1091 | |||
| 1092 | pwm = I915_READ(BLC_PWM_PCH_CTL1); | ||
| 1093 | pwm |= PWM_PCH_ENABLE; | ||
| 1094 | I915_WRITE(BLC_PWM_PCH_CTL1, pwm); | ||
| 1095 | /* | ||
| 1096 | * Unlock registers and just | ||
| 1097 | * leave them unlocked | ||
| 1098 | */ | ||
| 1099 | I915_WRITE(PCH_PP_CONTROL, | 1087 | I915_WRITE(PCH_PP_CONTROL, |
| 1100 | I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); | 1088 | I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); |
| 1101 | } else { | 1089 | } else { |
| 1102 | /* | ||
| 1103 | * Unlock registers and just | ||
| 1104 | * leave them unlocked | ||
| 1105 | */ | ||
| 1106 | I915_WRITE(PP_CONTROL, | 1090 | I915_WRITE(PP_CONTROL, |
| 1107 | I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); | 1091 | I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); |
| 1108 | } | 1092 | } |
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index d67ec3a51e42..45848b9b670b 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c | |||
| @@ -33,34 +33,6 @@ | |||
| 33 | #include "i915_drv.h" | 33 | #include "i915_drv.h" |
| 34 | 34 | ||
| 35 | /** | 35 | /** |
| 36 | * intel_ddc_probe | ||
| 37 | * | ||
| 38 | */ | ||
| 39 | bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus) | ||
| 40 | { | ||
| 41 | struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private; | ||
| 42 | u8 out_buf[] = { 0x0, 0x0}; | ||
| 43 | u8 buf[2]; | ||
| 44 | struct i2c_msg msgs[] = { | ||
| 45 | { | ||
| 46 | .addr = DDC_ADDR, | ||
| 47 | .flags = 0, | ||
| 48 | .len = 1, | ||
| 49 | .buf = out_buf, | ||
| 50 | }, | ||
| 51 | { | ||
| 52 | .addr = DDC_ADDR, | ||
| 53 | .flags = I2C_M_RD, | ||
| 54 | .len = 1, | ||
| 55 | .buf = buf, | ||
| 56 | } | ||
| 57 | }; | ||
| 58 | |||
| 59 | return i2c_transfer(intel_gmbus_get_adapter(dev_priv, ddc_bus), | ||
| 60 | msgs, 2) == 2; | ||
| 61 | } | ||
| 62 | |||
| 63 | /** | ||
| 64 | * intel_ddc_get_modes - get modelist from monitor | 36 | * intel_ddc_get_modes - get modelist from monitor |
| 65 | * @connector: DRM connector device to use | 37 | * @connector: DRM connector device to use |
| 66 | * @adapter: i2c adapter | 38 | * @adapter: i2c adapter |
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 458743da3774..830d0dd610e1 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
| @@ -226,7 +226,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, | |||
| 226 | } | 226 | } |
| 227 | overlay->last_flip_req = request->seqno; | 227 | overlay->last_flip_req = request->seqno; |
| 228 | overlay->flip_tail = tail; | 228 | overlay->flip_tail = tail; |
| 229 | ret = i915_wait_request(ring, overlay->last_flip_req); | 229 | ret = i915_wait_seqno(ring, overlay->last_flip_req); |
| 230 | if (ret) | 230 | if (ret) |
| 231 | return ret; | 231 | return ret; |
| 232 | i915_gem_retire_requests(dev); | 232 | i915_gem_retire_requests(dev); |
| @@ -452,7 +452,7 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) | |||
| 452 | if (overlay->last_flip_req == 0) | 452 | if (overlay->last_flip_req == 0) |
| 453 | return 0; | 453 | return 0; |
| 454 | 454 | ||
| 455 | ret = i915_wait_request(ring, overlay->last_flip_req); | 455 | ret = i915_wait_seqno(ring, overlay->last_flip_req); |
| 456 | if (ret) | 456 | if (ret) |
| 457 | return ret; | 457 | return ret; |
| 458 | i915_gem_retire_requests(dev); | 458 | i915_gem_retire_requests(dev); |
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 2a1625d84a69..10c7d39034e1 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
| @@ -56,7 +56,7 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, | |||
| 56 | void | 56 | void |
| 57 | intel_pch_panel_fitting(struct drm_device *dev, | 57 | intel_pch_panel_fitting(struct drm_device *dev, |
| 58 | int fitting_mode, | 58 | int fitting_mode, |
| 59 | struct drm_display_mode *mode, | 59 | const struct drm_display_mode *mode, |
| 60 | struct drm_display_mode *adjusted_mode) | 60 | struct drm_display_mode *adjusted_mode) |
| 61 | { | 61 | { |
| 62 | struct drm_i915_private *dev_priv = dev->dev_private; | 62 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -287,9 +287,24 @@ void intel_panel_disable_backlight(struct drm_device *dev) | |||
| 287 | 287 | ||
| 288 | dev_priv->backlight_enabled = false; | 288 | dev_priv->backlight_enabled = false; |
| 289 | intel_panel_actually_set_backlight(dev, 0); | 289 | intel_panel_actually_set_backlight(dev, 0); |
| 290 | |||
| 291 | if (INTEL_INFO(dev)->gen >= 4) { | ||
| 292 | uint32_t reg, tmp; | ||
| 293 | |||
| 294 | reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; | ||
| 295 | |||
| 296 | I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); | ||
| 297 | |||
| 298 | if (HAS_PCH_SPLIT(dev)) { | ||
| 299 | tmp = I915_READ(BLC_PWM_PCH_CTL1); | ||
| 300 | tmp &= ~BLM_PCH_PWM_ENABLE; | ||
| 301 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp); | ||
| 302 | } | ||
| 303 | } | ||
| 290 | } | 304 | } |
| 291 | 305 | ||
| 292 | void intel_panel_enable_backlight(struct drm_device *dev) | 306 | void intel_panel_enable_backlight(struct drm_device *dev, |
| 307 | enum pipe pipe) | ||
| 293 | { | 308 | { |
| 294 | struct drm_i915_private *dev_priv = dev->dev_private; | 309 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 295 | 310 | ||
| @@ -298,6 +313,40 @@ void intel_panel_enable_backlight(struct drm_device *dev) | |||
| 298 | 313 | ||
| 299 | dev_priv->backlight_enabled = true; | 314 | dev_priv->backlight_enabled = true; |
| 300 | intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); | 315 | intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); |
| 316 | |||
| 317 | if (INTEL_INFO(dev)->gen >= 4) { | ||
| 318 | uint32_t reg, tmp; | ||
| 319 | |||
| 320 | reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; | ||
| 321 | |||
| 322 | |||
| 323 | tmp = I915_READ(reg); | ||
| 324 | |||
| 325 | /* Note that this can also get called through dpms changes. And | ||
| 326 | * we don't track the backlight dpms state, hence check whether | ||
| 327 | * we have to do anything first. */ | ||
| 328 | if (tmp & BLM_PWM_ENABLE) | ||
| 329 | return; | ||
| 330 | |||
| 331 | if (dev_priv->num_pipe == 3) | ||
| 332 | tmp &= ~BLM_PIPE_SELECT_IVB; | ||
| 333 | else | ||
| 334 | tmp &= ~BLM_PIPE_SELECT; | ||
| 335 | |||
| 336 | tmp |= BLM_PIPE(pipe); | ||
| 337 | tmp &= ~BLM_PWM_ENABLE; | ||
| 338 | |||
| 339 | I915_WRITE(reg, tmp); | ||
| 340 | POSTING_READ(reg); | ||
| 341 | I915_WRITE(reg, tmp | BLM_PWM_ENABLE); | ||
| 342 | |||
| 343 | if (HAS_PCH_SPLIT(dev)) { | ||
| 344 | tmp = I915_READ(BLC_PWM_PCH_CTL1); | ||
| 345 | tmp |= BLM_PCH_PWM_ENABLE; | ||
| 346 | tmp &= ~BLM_PCH_OVERRIDE_ENABLE; | ||
| 347 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp); | ||
| 348 | } | ||
| 349 | } | ||
| 301 | } | 350 | } |
| 302 | 351 | ||
| 303 | static void intel_panel_init_backlight(struct drm_device *dev) | 352 | static void intel_panel_init_backlight(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d0ce2a5b1d3f..94aabcaa3a67 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -387,8 +387,6 @@ void intel_update_fbc(struct drm_device *dev) | |||
| 387 | struct drm_i915_gem_object *obj; | 387 | struct drm_i915_gem_object *obj; |
| 388 | int enable_fbc; | 388 | int enable_fbc; |
| 389 | 389 | ||
| 390 | DRM_DEBUG_KMS("\n"); | ||
| 391 | |||
| 392 | if (!i915_powersave) | 390 | if (!i915_powersave) |
| 393 | return; | 391 | return; |
| 394 | 392 | ||
| @@ -405,7 +403,9 @@ void intel_update_fbc(struct drm_device *dev) | |||
| 405 | * - going to an unsupported config (interlace, pixel multiply, etc.) | 403 | * - going to an unsupported config (interlace, pixel multiply, etc.) |
| 406 | */ | 404 | */ |
| 407 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { | 405 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { |
| 408 | if (tmp_crtc->enabled && tmp_crtc->fb) { | 406 | if (tmp_crtc->enabled && |
| 407 | !to_intel_crtc(tmp_crtc)->primary_disabled && | ||
| 408 | tmp_crtc->fb) { | ||
| 409 | if (crtc) { | 409 | if (crtc) { |
| 410 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); | 410 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); |
| 411 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; | 411 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; |
| @@ -2182,7 +2182,7 @@ bool ironlake_set_drps(struct drm_device *dev, u8 val) | |||
| 2182 | return true; | 2182 | return true; |
| 2183 | } | 2183 | } |
| 2184 | 2184 | ||
| 2185 | void ironlake_enable_drps(struct drm_device *dev) | 2185 | static void ironlake_enable_drps(struct drm_device *dev) |
| 2186 | { | 2186 | { |
| 2187 | struct drm_i915_private *dev_priv = dev->dev_private; | 2187 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2188 | u32 rgvmodectl = I915_READ(MEMMODECTL); | 2188 | u32 rgvmodectl = I915_READ(MEMMODECTL); |
| @@ -2246,7 +2246,7 @@ void ironlake_enable_drps(struct drm_device *dev) | |||
| 2246 | getrawmonotonic(&dev_priv->last_time2); | 2246 | getrawmonotonic(&dev_priv->last_time2); |
| 2247 | } | 2247 | } |
| 2248 | 2248 | ||
| 2249 | void ironlake_disable_drps(struct drm_device *dev) | 2249 | static void ironlake_disable_drps(struct drm_device *dev) |
| 2250 | { | 2250 | { |
| 2251 | struct drm_i915_private *dev_priv = dev->dev_private; | 2251 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2252 | u16 rgvswctl = I915_READ16(MEMSWCTL); | 2252 | u16 rgvswctl = I915_READ16(MEMSWCTL); |
| @@ -2299,10 +2299,11 @@ void gen6_set_rps(struct drm_device *dev, u8 val) | |||
| 2299 | dev_priv->cur_delay = val; | 2299 | dev_priv->cur_delay = val; |
| 2300 | } | 2300 | } |
| 2301 | 2301 | ||
| 2302 | void gen6_disable_rps(struct drm_device *dev) | 2302 | static void gen6_disable_rps(struct drm_device *dev) |
| 2303 | { | 2303 | { |
| 2304 | struct drm_i915_private *dev_priv = dev->dev_private; | 2304 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2305 | 2305 | ||
| 2306 | I915_WRITE(GEN6_RC_CONTROL, 0); | ||
| 2306 | I915_WRITE(GEN6_RPNSWREQ, 1 << 31); | 2307 | I915_WRITE(GEN6_RPNSWREQ, 1 << 31); |
| 2307 | I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); | 2308 | I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); |
| 2308 | I915_WRITE(GEN6_PMIER, 0); | 2309 | I915_WRITE(GEN6_PMIER, 0); |
| @@ -2332,9 +2333,11 @@ int intel_enable_rc6(const struct drm_device *dev) | |||
| 2332 | if (INTEL_INFO(dev)->gen == 5) | 2333 | if (INTEL_INFO(dev)->gen == 5) |
| 2333 | return 0; | 2334 | return 0; |
| 2334 | 2335 | ||
| 2335 | /* Sorry Haswell, no RC6 for you for now. */ | 2336 | /* On Haswell, only RC6 is available. So let's enable it by default to |
| 2337 | * provide better testing and coverage since the beginning. | ||
| 2338 | */ | ||
| 2336 | if (IS_HASWELL(dev)) | 2339 | if (IS_HASWELL(dev)) |
| 2337 | return 0; | 2340 | return INTEL_RC6_ENABLE; |
| 2338 | 2341 | ||
| 2339 | /* | 2342 | /* |
| 2340 | * Disable rc6 on Sandybridge | 2343 | * Disable rc6 on Sandybridge |
| @@ -2347,8 +2350,9 @@ int intel_enable_rc6(const struct drm_device *dev) | |||
| 2347 | return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); | 2350 | return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); |
| 2348 | } | 2351 | } |
| 2349 | 2352 | ||
| 2350 | void gen6_enable_rps(struct drm_i915_private *dev_priv) | 2353 | static void gen6_enable_rps(struct drm_device *dev) |
| 2351 | { | 2354 | { |
| 2355 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 2352 | struct intel_ring_buffer *ring; | 2356 | struct intel_ring_buffer *ring; |
| 2353 | u32 rp_state_cap; | 2357 | u32 rp_state_cap; |
| 2354 | u32 gt_perf_status; | 2358 | u32 gt_perf_status; |
| @@ -2357,6 +2361,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2357 | int rc6_mode; | 2361 | int rc6_mode; |
| 2358 | int i; | 2362 | int i; |
| 2359 | 2363 | ||
| 2364 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
| 2365 | |||
| 2360 | /* Here begins a magic sequence of register writes to enable | 2366 | /* Here begins a magic sequence of register writes to enable |
| 2361 | * auto-downclocking. | 2367 | * auto-downclocking. |
| 2362 | * | 2368 | * |
| @@ -2364,7 +2370,6 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2364 | * userspace... | 2370 | * userspace... |
| 2365 | */ | 2371 | */ |
| 2366 | I915_WRITE(GEN6_RC_STATE, 0); | 2372 | I915_WRITE(GEN6_RC_STATE, 0); |
| 2367 | mutex_lock(&dev_priv->dev->struct_mutex); | ||
| 2368 | 2373 | ||
| 2369 | /* Clear the DBG now so we don't confuse earlier errors */ | 2374 | /* Clear the DBG now so we don't confuse earlier errors */ |
| 2370 | if ((gtfifodbg = I915_READ(GTFIFODBG))) { | 2375 | if ((gtfifodbg = I915_READ(GTFIFODBG))) { |
| @@ -2400,20 +2405,24 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2400 | I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); | 2405 | I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); |
| 2401 | I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ | 2406 | I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ |
| 2402 | 2407 | ||
| 2408 | /* Check if we are enabling RC6 */ | ||
| 2403 | rc6_mode = intel_enable_rc6(dev_priv->dev); | 2409 | rc6_mode = intel_enable_rc6(dev_priv->dev); |
| 2404 | if (rc6_mode & INTEL_RC6_ENABLE) | 2410 | if (rc6_mode & INTEL_RC6_ENABLE) |
| 2405 | rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; | 2411 | rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; |
| 2406 | 2412 | ||
| 2407 | if (rc6_mode & INTEL_RC6p_ENABLE) | 2413 | /* We don't use those on Haswell */ |
| 2408 | rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; | 2414 | if (!IS_HASWELL(dev)) { |
| 2415 | if (rc6_mode & INTEL_RC6p_ENABLE) | ||
| 2416 | rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; | ||
| 2409 | 2417 | ||
| 2410 | if (rc6_mode & INTEL_RC6pp_ENABLE) | 2418 | if (rc6_mode & INTEL_RC6pp_ENABLE) |
| 2411 | rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; | 2419 | rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; |
| 2420 | } | ||
| 2412 | 2421 | ||
| 2413 | DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", | 2422 | DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", |
| 2414 | (rc6_mode & INTEL_RC6_ENABLE) ? "on" : "off", | 2423 | (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", |
| 2415 | (rc6_mode & INTEL_RC6p_ENABLE) ? "on" : "off", | 2424 | (rc6_mask & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", |
| 2416 | (rc6_mode & INTEL_RC6pp_ENABLE) ? "on" : "off"); | 2425 | (rc6_mask & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); |
| 2417 | 2426 | ||
| 2418 | I915_WRITE(GEN6_RC_CONTROL, | 2427 | I915_WRITE(GEN6_RC_CONTROL, |
| 2419 | rc6_mask | | 2428 | rc6_mask | |
| @@ -2431,10 +2440,19 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2431 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, | 2440 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, |
| 2432 | dev_priv->max_delay << 24 | | 2441 | dev_priv->max_delay << 24 | |
| 2433 | dev_priv->min_delay << 16); | 2442 | dev_priv->min_delay << 16); |
| 2434 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); | 2443 | |
| 2435 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); | 2444 | if (IS_HASWELL(dev)) { |
| 2436 | I915_WRITE(GEN6_RP_UP_EI, 100000); | 2445 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); |
| 2437 | I915_WRITE(GEN6_RP_DOWN_EI, 5000000); | 2446 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); |
| 2447 | I915_WRITE(GEN6_RP_UP_EI, 66000); | ||
| 2448 | I915_WRITE(GEN6_RP_DOWN_EI, 350000); | ||
| 2449 | } else { | ||
| 2450 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); | ||
| 2451 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); | ||
| 2452 | I915_WRITE(GEN6_RP_UP_EI, 100000); | ||
| 2453 | I915_WRITE(GEN6_RP_DOWN_EI, 5000000); | ||
| 2454 | } | ||
| 2455 | |||
| 2438 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); | 2456 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); |
| 2439 | I915_WRITE(GEN6_RP_CONTROL, | 2457 | I915_WRITE(GEN6_RP_CONTROL, |
| 2440 | GEN6_RP_MEDIA_TURBO | | 2458 | GEN6_RP_MEDIA_TURBO | |
| @@ -2442,7 +2460,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2442 | GEN6_RP_MEDIA_IS_GFX | | 2460 | GEN6_RP_MEDIA_IS_GFX | |
| 2443 | GEN6_RP_ENABLE | | 2461 | GEN6_RP_ENABLE | |
| 2444 | GEN6_RP_UP_BUSY_AVG | | 2462 | GEN6_RP_UP_BUSY_AVG | |
| 2445 | GEN6_RP_DOWN_IDLE_CONT); | 2463 | (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT)); |
| 2446 | 2464 | ||
| 2447 | if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, | 2465 | if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, |
| 2448 | 500)) | 2466 | 500)) |
| @@ -2473,14 +2491,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2473 | gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8); | 2491 | gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8); |
| 2474 | 2492 | ||
| 2475 | /* requires MSI enabled */ | 2493 | /* requires MSI enabled */ |
| 2476 | I915_WRITE(GEN6_PMIER, | 2494 | I915_WRITE(GEN6_PMIER, GEN6_PM_DEFERRED_EVENTS); |
| 2477 | GEN6_PM_MBOX_EVENT | | ||
| 2478 | GEN6_PM_THERMAL_EVENT | | ||
| 2479 | GEN6_PM_RP_DOWN_TIMEOUT | | ||
| 2480 | GEN6_PM_RP_UP_THRESHOLD | | ||
| 2481 | GEN6_PM_RP_DOWN_THRESHOLD | | ||
| 2482 | GEN6_PM_RP_UP_EI_EXPIRED | | ||
| 2483 | GEN6_PM_RP_DOWN_EI_EXPIRED); | ||
| 2484 | spin_lock_irq(&dev_priv->rps_lock); | 2495 | spin_lock_irq(&dev_priv->rps_lock); |
| 2485 | WARN_ON(dev_priv->pm_iir != 0); | 2496 | WARN_ON(dev_priv->pm_iir != 0); |
| 2486 | I915_WRITE(GEN6_PMIMR, 0); | 2497 | I915_WRITE(GEN6_PMIMR, 0); |
| @@ -2489,15 +2500,17 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2489 | I915_WRITE(GEN6_PMINTRMSK, 0); | 2500 | I915_WRITE(GEN6_PMINTRMSK, 0); |
| 2490 | 2501 | ||
| 2491 | gen6_gt_force_wake_put(dev_priv); | 2502 | gen6_gt_force_wake_put(dev_priv); |
| 2492 | mutex_unlock(&dev_priv->dev->struct_mutex); | ||
| 2493 | } | 2503 | } |
| 2494 | 2504 | ||
| 2495 | void gen6_update_ring_freq(struct drm_i915_private *dev_priv) | 2505 | static void gen6_update_ring_freq(struct drm_device *dev) |
| 2496 | { | 2506 | { |
| 2507 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 2497 | int min_freq = 15; | 2508 | int min_freq = 15; |
| 2498 | int gpu_freq, ia_freq, max_ia_freq; | 2509 | int gpu_freq, ia_freq, max_ia_freq; |
| 2499 | int scaling_factor = 180; | 2510 | int scaling_factor = 180; |
| 2500 | 2511 | ||
| 2512 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
| 2513 | |||
| 2501 | max_ia_freq = cpufreq_quick_get_max(0); | 2514 | max_ia_freq = cpufreq_quick_get_max(0); |
| 2502 | /* | 2515 | /* |
| 2503 | * Default to measured freq if none found, PCU will ensure we don't go | 2516 | * Default to measured freq if none found, PCU will ensure we don't go |
| @@ -2509,8 +2522,6 @@ void gen6_update_ring_freq(struct drm_i915_private *dev_priv) | |||
| 2509 | /* Convert from kHz to MHz */ | 2522 | /* Convert from kHz to MHz */ |
| 2510 | max_ia_freq /= 1000; | 2523 | max_ia_freq /= 1000; |
| 2511 | 2524 | ||
| 2512 | mutex_lock(&dev_priv->dev->struct_mutex); | ||
| 2513 | |||
| 2514 | /* | 2525 | /* |
| 2515 | * For each potential GPU frequency, load a ring frequency we'd like | 2526 | * For each potential GPU frequency, load a ring frequency we'd like |
| 2516 | * to use for memory access. We do this by specifying the IA frequency | 2527 | * to use for memory access. We do this by specifying the IA frequency |
| @@ -2541,11 +2552,9 @@ void gen6_update_ring_freq(struct drm_i915_private *dev_priv) | |||
| 2541 | continue; | 2552 | continue; |
| 2542 | } | 2553 | } |
| 2543 | } | 2554 | } |
| 2544 | |||
| 2545 | mutex_unlock(&dev_priv->dev->struct_mutex); | ||
| 2546 | } | 2555 | } |
| 2547 | 2556 | ||
| 2548 | static void ironlake_teardown_rc6(struct drm_device *dev) | 2557 | void ironlake_teardown_rc6(struct drm_device *dev) |
| 2549 | { | 2558 | { |
| 2550 | struct drm_i915_private *dev_priv = dev->dev_private; | 2559 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2551 | 2560 | ||
| @@ -2562,7 +2571,7 @@ static void ironlake_teardown_rc6(struct drm_device *dev) | |||
| 2562 | } | 2571 | } |
| 2563 | } | 2572 | } |
| 2564 | 2573 | ||
| 2565 | void ironlake_disable_rc6(struct drm_device *dev) | 2574 | static void ironlake_disable_rc6(struct drm_device *dev) |
| 2566 | { | 2575 | { |
| 2567 | struct drm_i915_private *dev_priv = dev->dev_private; | 2576 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2568 | 2577 | ||
| @@ -2578,8 +2587,6 @@ void ironlake_disable_rc6(struct drm_device *dev) | |||
| 2578 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 2587 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
| 2579 | POSTING_READ(RSTDBYCTL); | 2588 | POSTING_READ(RSTDBYCTL); |
| 2580 | } | 2589 | } |
| 2581 | |||
| 2582 | ironlake_teardown_rc6(dev); | ||
| 2583 | } | 2590 | } |
| 2584 | 2591 | ||
| 2585 | static int ironlake_setup_rc6(struct drm_device *dev) | 2592 | static int ironlake_setup_rc6(struct drm_device *dev) |
| @@ -2601,7 +2608,7 @@ static int ironlake_setup_rc6(struct drm_device *dev) | |||
| 2601 | return 0; | 2608 | return 0; |
| 2602 | } | 2609 | } |
| 2603 | 2610 | ||
| 2604 | void ironlake_enable_rc6(struct drm_device *dev) | 2611 | static void ironlake_enable_rc6(struct drm_device *dev) |
| 2605 | { | 2612 | { |
| 2606 | struct drm_i915_private *dev_priv = dev->dev_private; | 2613 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2607 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; | 2614 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; |
| @@ -2613,12 +2620,11 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
| 2613 | if (!intel_enable_rc6(dev)) | 2620 | if (!intel_enable_rc6(dev)) |
| 2614 | return; | 2621 | return; |
| 2615 | 2622 | ||
| 2616 | mutex_lock(&dev->struct_mutex); | 2623 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); |
| 2624 | |||
| 2617 | ret = ironlake_setup_rc6(dev); | 2625 | ret = ironlake_setup_rc6(dev); |
| 2618 | if (ret) { | 2626 | if (ret) |
| 2619 | mutex_unlock(&dev->struct_mutex); | ||
| 2620 | return; | 2627 | return; |
| 2621 | } | ||
| 2622 | 2628 | ||
| 2623 | /* | 2629 | /* |
| 2624 | * GPU can automatically power down the render unit if given a page | 2630 | * GPU can automatically power down the render unit if given a page |
| @@ -2627,7 +2633,6 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
| 2627 | ret = intel_ring_begin(ring, 6); | 2633 | ret = intel_ring_begin(ring, 6); |
| 2628 | if (ret) { | 2634 | if (ret) { |
| 2629 | ironlake_teardown_rc6(dev); | 2635 | ironlake_teardown_rc6(dev); |
| 2630 | mutex_unlock(&dev->struct_mutex); | ||
| 2631 | return; | 2636 | return; |
| 2632 | } | 2637 | } |
| 2633 | 2638 | ||
| @@ -2652,13 +2657,11 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
| 2652 | if (ret) { | 2657 | if (ret) { |
| 2653 | DRM_ERROR("failed to enable ironlake power power savings\n"); | 2658 | DRM_ERROR("failed to enable ironlake power power savings\n"); |
| 2654 | ironlake_teardown_rc6(dev); | 2659 | ironlake_teardown_rc6(dev); |
| 2655 | mutex_unlock(&dev->struct_mutex); | ||
| 2656 | return; | 2660 | return; |
| 2657 | } | 2661 | } |
| 2658 | 2662 | ||
| 2659 | I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN); | 2663 | I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN); |
| 2660 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 2664 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
| 2661 | mutex_unlock(&dev->struct_mutex); | ||
| 2662 | } | 2665 | } |
| 2663 | 2666 | ||
| 2664 | static unsigned long intel_pxfreq(u32 vidfreq) | 2667 | static unsigned long intel_pxfreq(u32 vidfreq) |
| @@ -3154,8 +3157,7 @@ void intel_gpu_ips_teardown(void) | |||
| 3154 | i915_mch_dev = NULL; | 3157 | i915_mch_dev = NULL; |
| 3155 | spin_unlock(&mchdev_lock); | 3158 | spin_unlock(&mchdev_lock); |
| 3156 | } | 3159 | } |
| 3157 | 3160 | static void intel_init_emon(struct drm_device *dev) | |
| 3158 | void intel_init_emon(struct drm_device *dev) | ||
| 3159 | { | 3161 | { |
| 3160 | struct drm_i915_private *dev_priv = dev->dev_private; | 3162 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3161 | u32 lcfuse; | 3163 | u32 lcfuse; |
| @@ -3226,6 +3228,28 @@ void intel_init_emon(struct drm_device *dev) | |||
| 3226 | dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK); | 3228 | dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK); |
| 3227 | } | 3229 | } |
| 3228 | 3230 | ||
| 3231 | void intel_disable_gt_powersave(struct drm_device *dev) | ||
| 3232 | { | ||
| 3233 | if (IS_IRONLAKE_M(dev)) { | ||
| 3234 | ironlake_disable_drps(dev); | ||
| 3235 | ironlake_disable_rc6(dev); | ||
| 3236 | } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) { | ||
| 3237 | gen6_disable_rps(dev); | ||
| 3238 | } | ||
| 3239 | } | ||
| 3240 | |||
| 3241 | void intel_enable_gt_powersave(struct drm_device *dev) | ||
| 3242 | { | ||
| 3243 | if (IS_IRONLAKE_M(dev)) { | ||
| 3244 | ironlake_enable_drps(dev); | ||
| 3245 | ironlake_enable_rc6(dev); | ||
| 3246 | intel_init_emon(dev); | ||
| 3247 | } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { | ||
| 3248 | gen6_enable_rps(dev); | ||
| 3249 | gen6_update_ring_freq(dev); | ||
| 3250 | } | ||
| 3251 | } | ||
| 3252 | |||
| 3229 | static void ironlake_init_clock_gating(struct drm_device *dev) | 3253 | static void ironlake_init_clock_gating(struct drm_device *dev) |
| 3230 | { | 3254 | { |
| 3231 | struct drm_i915_private *dev_priv = dev->dev_private; | 3255 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -3328,8 +3352,12 @@ static void gen6_init_clock_gating(struct drm_device *dev) | |||
| 3328 | * | 3352 | * |
| 3329 | * According to the spec, bit 11 (RCCUNIT) must also be set, | 3353 | * According to the spec, bit 11 (RCCUNIT) must also be set, |
| 3330 | * but we didn't debug actual testcases to find it out. | 3354 | * but we didn't debug actual testcases to find it out. |
| 3355 | * | ||
| 3356 | * Also apply WaDisableVDSUnitClockGating and | ||
| 3357 | * WaDisableRCPBUnitClockGating. | ||
| 3331 | */ | 3358 | */ |
| 3332 | I915_WRITE(GEN6_UCGCTL2, | 3359 | I915_WRITE(GEN6_UCGCTL2, |
| 3360 | GEN7_VDSUNIT_CLOCK_GATE_DISABLE | | ||
| 3333 | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | | 3361 | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | |
| 3334 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); | 3362 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); |
| 3335 | 3363 | ||
| @@ -3357,6 +3385,9 @@ static void gen6_init_clock_gating(struct drm_device *dev) | |||
| 3357 | ILK_DPARB_CLK_GATE | | 3385 | ILK_DPARB_CLK_GATE | |
| 3358 | ILK_DPFD_CLK_GATE); | 3386 | ILK_DPFD_CLK_GATE); |
| 3359 | 3387 | ||
| 3388 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | | ||
| 3389 | GEN6_MBCTL_ENABLE_BOOT_FETCH); | ||
| 3390 | |||
| 3360 | for_each_pipe(pipe) { | 3391 | for_each_pipe(pipe) { |
| 3361 | I915_WRITE(DSPCNTR(pipe), | 3392 | I915_WRITE(DSPCNTR(pipe), |
| 3362 | I915_READ(DSPCNTR(pipe)) | | 3393 | I915_READ(DSPCNTR(pipe)) | |
| @@ -3377,7 +3408,7 @@ static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) | |||
| 3377 | I915_WRITE(GEN7_FF_THREAD_MODE, reg); | 3408 | I915_WRITE(GEN7_FF_THREAD_MODE, reg); |
| 3378 | } | 3409 | } |
| 3379 | 3410 | ||
| 3380 | static void ivybridge_init_clock_gating(struct drm_device *dev) | 3411 | static void haswell_init_clock_gating(struct drm_device *dev) |
| 3381 | { | 3412 | { |
| 3382 | struct drm_i915_private *dev_priv = dev->dev_private; | 3413 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3383 | int pipe; | 3414 | int pipe; |
| @@ -3427,13 +3458,24 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) | |||
| 3427 | /* WaDisable4x2SubspanOptimization */ | 3458 | /* WaDisable4x2SubspanOptimization */ |
| 3428 | I915_WRITE(CACHE_MODE_1, | 3459 | I915_WRITE(CACHE_MODE_1, |
| 3429 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); | 3460 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); |
| 3461 | |||
| 3462 | /* XXX: This is a workaround for early silicon revisions and should be | ||
| 3463 | * removed later. | ||
| 3464 | */ | ||
| 3465 | I915_WRITE(WM_DBG, | ||
| 3466 | I915_READ(WM_DBG) | | ||
| 3467 | WM_DBG_DISALLOW_MULTIPLE_LP | | ||
| 3468 | WM_DBG_DISALLOW_SPRITE | | ||
| 3469 | WM_DBG_DISALLOW_MAXFIFO); | ||
| 3470 | |||
| 3430 | } | 3471 | } |
| 3431 | 3472 | ||
| 3432 | static void valleyview_init_clock_gating(struct drm_device *dev) | 3473 | static void ivybridge_init_clock_gating(struct drm_device *dev) |
| 3433 | { | 3474 | { |
| 3434 | struct drm_i915_private *dev_priv = dev->dev_private; | 3475 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3435 | int pipe; | 3476 | int pipe; |
| 3436 | uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; | 3477 | uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; |
| 3478 | uint32_t snpcr; | ||
| 3437 | 3479 | ||
| 3438 | I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); | 3480 | I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); |
| 3439 | 3481 | ||
| @@ -3441,10 +3483,77 @@ static void valleyview_init_clock_gating(struct drm_device *dev) | |||
| 3441 | I915_WRITE(WM2_LP_ILK, 0); | 3483 | I915_WRITE(WM2_LP_ILK, 0); |
| 3442 | I915_WRITE(WM1_LP_ILK, 0); | 3484 | I915_WRITE(WM1_LP_ILK, 0); |
| 3443 | 3485 | ||
| 3444 | /* According to the spec, bit 13 (RCZUNIT) must be set on IVB. | 3486 | I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); |
| 3487 | |||
| 3488 | I915_WRITE(IVB_CHICKEN3, | ||
| 3489 | CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | | ||
| 3490 | CHICKEN3_DGMG_DONE_FIX_DISABLE); | ||
| 3491 | |||
| 3492 | /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ | ||
| 3493 | I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, | ||
| 3494 | GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); | ||
| 3495 | |||
| 3496 | /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ | ||
| 3497 | I915_WRITE(GEN7_L3CNTLREG1, | ||
| 3498 | GEN7_WA_FOR_GEN7_L3_CONTROL); | ||
| 3499 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, | ||
| 3500 | GEN7_WA_L3_CHICKEN_MODE); | ||
| 3501 | |||
| 3502 | /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock | ||
| 3503 | * gating disable must be set. Failure to set it results in | ||
| 3504 | * flickering pixels due to Z write ordering failures after | ||
| 3505 | * some amount of runtime in the Mesa "fire" demo, and Unigine | ||
| 3506 | * Sanctuary and Tropics, and apparently anything else with | ||
| 3507 | * alpha test or pixel discard. | ||
| 3508 | * | ||
| 3509 | * According to the spec, bit 11 (RCCUNIT) must also be set, | ||
| 3510 | * but we didn't debug actual testcases to find it out. | ||
| 3511 | * | ||
| 3512 | * According to the spec, bit 13 (RCZUNIT) must be set on IVB. | ||
| 3445 | * This implements the WaDisableRCZUnitClockGating workaround. | 3513 | * This implements the WaDisableRCZUnitClockGating workaround. |
| 3446 | */ | 3514 | */ |
| 3447 | I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE); | 3515 | I915_WRITE(GEN6_UCGCTL2, |
| 3516 | GEN6_RCZUNIT_CLOCK_GATE_DISABLE | | ||
| 3517 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); | ||
| 3518 | |||
| 3519 | /* This is required by WaCatErrorRejectionIssue */ | ||
| 3520 | I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, | ||
| 3521 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | | ||
| 3522 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); | ||
| 3523 | |||
| 3524 | for_each_pipe(pipe) { | ||
| 3525 | I915_WRITE(DSPCNTR(pipe), | ||
| 3526 | I915_READ(DSPCNTR(pipe)) | | ||
| 3527 | DISPPLANE_TRICKLE_FEED_DISABLE); | ||
| 3528 | intel_flush_display_plane(dev_priv, pipe); | ||
| 3529 | } | ||
| 3530 | |||
| 3531 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | | ||
| 3532 | GEN6_MBCTL_ENABLE_BOOT_FETCH); | ||
| 3533 | |||
| 3534 | gen7_setup_fixed_func_scheduler(dev_priv); | ||
| 3535 | |||
| 3536 | /* WaDisable4x2SubspanOptimization */ | ||
| 3537 | I915_WRITE(CACHE_MODE_1, | ||
| 3538 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); | ||
| 3539 | |||
| 3540 | snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); | ||
| 3541 | snpcr &= ~GEN6_MBC_SNPCR_MASK; | ||
| 3542 | snpcr |= GEN6_MBC_SNPCR_MED; | ||
| 3543 | I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); | ||
| 3544 | } | ||
| 3545 | |||
| 3546 | static void valleyview_init_clock_gating(struct drm_device *dev) | ||
| 3547 | { | ||
| 3548 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 3549 | int pipe; | ||
| 3550 | uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; | ||
| 3551 | |||
| 3552 | I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); | ||
| 3553 | |||
| 3554 | I915_WRITE(WM3_LP_ILK, 0); | ||
| 3555 | I915_WRITE(WM2_LP_ILK, 0); | ||
| 3556 | I915_WRITE(WM1_LP_ILK, 0); | ||
| 3448 | 3557 | ||
| 3449 | I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); | 3558 | I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); |
| 3450 | 3559 | ||
| @@ -3465,6 +3574,35 @@ static void valleyview_init_clock_gating(struct drm_device *dev) | |||
| 3465 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | | 3574 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | |
| 3466 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); | 3575 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); |
| 3467 | 3576 | ||
| 3577 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | | ||
| 3578 | GEN6_MBCTL_ENABLE_BOOT_FETCH); | ||
| 3579 | |||
| 3580 | |||
| 3581 | /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock | ||
| 3582 | * gating disable must be set. Failure to set it results in | ||
| 3583 | * flickering pixels due to Z write ordering failures after | ||
| 3584 | * some amount of runtime in the Mesa "fire" demo, and Unigine | ||
| 3585 | * Sanctuary and Tropics, and apparently anything else with | ||
| 3586 | * alpha test or pixel discard. | ||
| 3587 | * | ||
| 3588 | * According to the spec, bit 11 (RCCUNIT) must also be set, | ||
| 3589 | * but we didn't debug actual testcases to find it out. | ||
| 3590 | * | ||
| 3591 | * According to the spec, bit 13 (RCZUNIT) must be set on IVB. | ||
| 3592 | * This implements the WaDisableRCZUnitClockGating workaround. | ||
| 3593 | * | ||
| 3594 | * Also apply WaDisableVDSUnitClockGating and | ||
| 3595 | * WaDisableRCPBUnitClockGating. | ||
| 3596 | */ | ||
| 3597 | I915_WRITE(GEN6_UCGCTL2, | ||
| 3598 | GEN7_VDSUNIT_CLOCK_GATE_DISABLE | | ||
| 3599 | GEN7_TDLUNIT_CLOCK_GATE_DISABLE | | ||
| 3600 | GEN6_RCZUNIT_CLOCK_GATE_DISABLE | | ||
| 3601 | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | | ||
| 3602 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); | ||
| 3603 | |||
| 3604 | I915_WRITE(GEN7_UCGCTL4, GEN7_L3BANK2X_CLOCK_GATE_DISABLE); | ||
| 3605 | |||
| 3468 | for_each_pipe(pipe) { | 3606 | for_each_pipe(pipe) { |
| 3469 | I915_WRITE(DSPCNTR(pipe), | 3607 | I915_WRITE(DSPCNTR(pipe), |
| 3470 | I915_READ(DSPCNTR(pipe)) | | 3608 | I915_READ(DSPCNTR(pipe)) | |
| @@ -3474,6 +3612,19 @@ static void valleyview_init_clock_gating(struct drm_device *dev) | |||
| 3474 | 3612 | ||
| 3475 | I915_WRITE(CACHE_MODE_1, | 3613 | I915_WRITE(CACHE_MODE_1, |
| 3476 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); | 3614 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); |
| 3615 | |||
| 3616 | /* | ||
| 3617 | * On ValleyView, the GUnit needs to signal the GT | ||
| 3618 | * when flip and other events complete. So enable | ||
| 3619 | * all the GUnit->GT interrupts here | ||
| 3620 | */ | ||
| 3621 | I915_WRITE(VLV_DPFLIPSTAT, PIPEB_LINE_COMPARE_INT_EN | | ||
| 3622 | PIPEB_HLINE_INT_EN | PIPEB_VBLANK_INT_EN | | ||
| 3623 | SPRITED_FLIPDONE_INT_EN | SPRITEC_FLIPDONE_INT_EN | | ||
| 3624 | PLANEB_FLIPDONE_INT_EN | PIPEA_LINE_COMPARE_INT_EN | | ||
| 3625 | PIPEA_HLINE_INT_EN | PIPEA_VBLANK_INT_EN | | ||
| 3626 | SPRITEB_FLIPDONE_INT_EN | SPRITEA_FLIPDONE_INT_EN | | ||
| 3627 | PLANEA_FLIPDONE_INT_EN); | ||
| 3477 | } | 3628 | } |
| 3478 | 3629 | ||
| 3479 | static void g4x_init_clock_gating(struct drm_device *dev) | 3630 | static void g4x_init_clock_gating(struct drm_device *dev) |
| @@ -3681,34 +3832,6 @@ void intel_init_pm(struct drm_device *dev) | |||
| 3681 | 3832 | ||
| 3682 | /* For FIFO watermark updates */ | 3833 | /* For FIFO watermark updates */ |
| 3683 | if (HAS_PCH_SPLIT(dev)) { | 3834 | if (HAS_PCH_SPLIT(dev)) { |
| 3684 | dev_priv->display.force_wake_get = __gen6_gt_force_wake_get; | ||
| 3685 | dev_priv->display.force_wake_put = __gen6_gt_force_wake_put; | ||
| 3686 | |||
| 3687 | /* IVB configs may use multi-threaded forcewake */ | ||
| 3688 | if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { | ||
| 3689 | u32 ecobus; | ||
| 3690 | |||
| 3691 | /* A small trick here - if the bios hasn't configured MT forcewake, | ||
| 3692 | * and if the device is in RC6, then force_wake_mt_get will not wake | ||
| 3693 | * the device and the ECOBUS read will return zero. Which will be | ||
| 3694 | * (correctly) interpreted by the test below as MT forcewake being | ||
| 3695 | * disabled. | ||
| 3696 | */ | ||
| 3697 | mutex_lock(&dev->struct_mutex); | ||
| 3698 | __gen6_gt_force_wake_mt_get(dev_priv); | ||
| 3699 | ecobus = I915_READ_NOTRACE(ECOBUS); | ||
| 3700 | __gen6_gt_force_wake_mt_put(dev_priv); | ||
| 3701 | mutex_unlock(&dev->struct_mutex); | ||
| 3702 | |||
| 3703 | if (ecobus & FORCEWAKE_MT_ENABLE) { | ||
| 3704 | DRM_DEBUG_KMS("Using MT version of forcewake\n"); | ||
| 3705 | dev_priv->display.force_wake_get = | ||
| 3706 | __gen6_gt_force_wake_mt_get; | ||
| 3707 | dev_priv->display.force_wake_put = | ||
| 3708 | __gen6_gt_force_wake_mt_put; | ||
| 3709 | } | ||
| 3710 | } | ||
| 3711 | |||
| 3712 | if (HAS_PCH_IBX(dev)) | 3835 | if (HAS_PCH_IBX(dev)) |
| 3713 | dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating; | 3836 | dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating; |
| 3714 | else if (HAS_PCH_CPT(dev)) | 3837 | else if (HAS_PCH_CPT(dev)) |
| @@ -3756,7 +3879,7 @@ void intel_init_pm(struct drm_device *dev) | |||
| 3756 | "Disable CxSR\n"); | 3879 | "Disable CxSR\n"); |
| 3757 | dev_priv->display.update_wm = NULL; | 3880 | dev_priv->display.update_wm = NULL; |
| 3758 | } | 3881 | } |
| 3759 | dev_priv->display.init_clock_gating = ivybridge_init_clock_gating; | 3882 | dev_priv->display.init_clock_gating = haswell_init_clock_gating; |
| 3760 | dev_priv->display.sanitize_pm = gen6_sanitize_pm; | 3883 | dev_priv->display.sanitize_pm = gen6_sanitize_pm; |
| 3761 | } else | 3884 | } else |
| 3762 | dev_priv->display.update_wm = NULL; | 3885 | dev_priv->display.update_wm = NULL; |
| @@ -3764,8 +3887,6 @@ void intel_init_pm(struct drm_device *dev) | |||
| 3764 | dev_priv->display.update_wm = valleyview_update_wm; | 3887 | dev_priv->display.update_wm = valleyview_update_wm; |
| 3765 | dev_priv->display.init_clock_gating = | 3888 | dev_priv->display.init_clock_gating = |
| 3766 | valleyview_init_clock_gating; | 3889 | valleyview_init_clock_gating; |
| 3767 | dev_priv->display.force_wake_get = vlv_force_wake_get; | ||
| 3768 | dev_priv->display.force_wake_put = vlv_force_wake_put; | ||
| 3769 | } else if (IS_PINEVIEW(dev)) { | 3890 | } else if (IS_PINEVIEW(dev)) { |
| 3770 | if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), | 3891 | if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), |
| 3771 | dev_priv->is_ddr3, | 3892 | dev_priv->is_ddr3, |
| @@ -3811,10 +3932,196 @@ void intel_init_pm(struct drm_device *dev) | |||
| 3811 | else | 3932 | else |
| 3812 | dev_priv->display.get_fifo_size = i830_get_fifo_size; | 3933 | dev_priv->display.get_fifo_size = i830_get_fifo_size; |
| 3813 | } | 3934 | } |
| 3935 | } | ||
| 3936 | |||
| 3937 | static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv) | ||
| 3938 | { | ||
| 3939 | u32 gt_thread_status_mask; | ||
| 3940 | |||
| 3941 | if (IS_HASWELL(dev_priv->dev)) | ||
| 3942 | gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW; | ||
| 3943 | else | ||
| 3944 | gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK; | ||
| 3814 | 3945 | ||
| 3815 | /* We attempt to init the necessary power wells early in the initialization | 3946 | /* w/a for a sporadic read returning 0 by waiting for the GT |
| 3816 | * time, so the subsystems that expect power to be enabled can work. | 3947 | * thread to wake up. |
| 3817 | */ | 3948 | */ |
| 3818 | intel_init_power_wells(dev); | 3949 | if (wait_for_atomic_us((I915_READ_NOTRACE(GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500)) |
| 3950 | DRM_ERROR("GT thread status wait timed out\n"); | ||
| 3951 | } | ||
| 3952 | |||
| 3953 | static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 3954 | { | ||
| 3955 | u32 forcewake_ack; | ||
| 3956 | |||
| 3957 | if (IS_HASWELL(dev_priv->dev)) | ||
| 3958 | forcewake_ack = FORCEWAKE_ACK_HSW; | ||
| 3959 | else | ||
| 3960 | forcewake_ack = FORCEWAKE_ACK; | ||
| 3961 | |||
| 3962 | if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500)) | ||
| 3963 | DRM_ERROR("Force wake wait timed out\n"); | ||
| 3964 | |||
| 3965 | I915_WRITE_NOTRACE(FORCEWAKE, 1); | ||
| 3966 | |||
| 3967 | if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500)) | ||
| 3968 | DRM_ERROR("Force wake wait timed out\n"); | ||
| 3969 | |||
| 3970 | __gen6_gt_wait_for_thread_c0(dev_priv); | ||
| 3971 | } | ||
| 3972 | |||
| 3973 | static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) | ||
| 3974 | { | ||
| 3975 | u32 forcewake_ack; | ||
| 3976 | |||
| 3977 | if (IS_HASWELL(dev_priv->dev)) | ||
| 3978 | forcewake_ack = FORCEWAKE_ACK_HSW; | ||
| 3979 | else | ||
| 3980 | forcewake_ack = FORCEWAKE_MT_ACK; | ||
| 3981 | |||
| 3982 | if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500)) | ||
| 3983 | DRM_ERROR("Force wake wait timed out\n"); | ||
| 3984 | |||
| 3985 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1)); | ||
| 3986 | |||
| 3987 | if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500)) | ||
| 3988 | DRM_ERROR("Force wake wait timed out\n"); | ||
| 3989 | |||
| 3990 | __gen6_gt_wait_for_thread_c0(dev_priv); | ||
| 3991 | } | ||
| 3992 | |||
| 3993 | /* | ||
| 3994 | * Generally this is called implicitly by the register read function. However, | ||
| 3995 | * if some sequence requires the GT to not power down then this function should | ||
| 3996 | * be called at the beginning of the sequence followed by a call to | ||
| 3997 | * gen6_gt_force_wake_put() at the end of the sequence. | ||
| 3998 | */ | ||
| 3999 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 4000 | { | ||
| 4001 | unsigned long irqflags; | ||
| 4002 | |||
| 4003 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); | ||
| 4004 | if (dev_priv->forcewake_count++ == 0) | ||
| 4005 | dev_priv->gt.force_wake_get(dev_priv); | ||
| 4006 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | ||
| 4007 | } | ||
| 4008 | |||
| 4009 | void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) | ||
| 4010 | { | ||
| 4011 | u32 gtfifodbg; | ||
| 4012 | gtfifodbg = I915_READ_NOTRACE(GTFIFODBG); | ||
| 4013 | if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, | ||
| 4014 | "MMIO read or write has been dropped %x\n", gtfifodbg)) | ||
| 4015 | I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); | ||
| 4016 | } | ||
| 4017 | |||
| 4018 | static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 4019 | { | ||
| 4020 | I915_WRITE_NOTRACE(FORCEWAKE, 0); | ||
| 4021 | /* The below doubles as a POSTING_READ */ | ||
| 4022 | gen6_gt_check_fifodbg(dev_priv); | ||
| 4023 | } | ||
| 4024 | |||
| 4025 | static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) | ||
| 4026 | { | ||
| 4027 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1)); | ||
| 4028 | /* The below doubles as a POSTING_READ */ | ||
| 4029 | gen6_gt_check_fifodbg(dev_priv); | ||
| 4030 | } | ||
| 4031 | |||
| 4032 | /* | ||
| 4033 | * see gen6_gt_force_wake_get() | ||
| 4034 | */ | ||
| 4035 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 4036 | { | ||
| 4037 | unsigned long irqflags; | ||
| 4038 | |||
| 4039 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); | ||
| 4040 | if (--dev_priv->forcewake_count == 0) | ||
| 4041 | dev_priv->gt.force_wake_put(dev_priv); | ||
| 4042 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | ||
| 4043 | } | ||
| 4044 | |||
| 4045 | int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) | ||
| 4046 | { | ||
| 4047 | int ret = 0; | ||
| 4048 | |||
| 4049 | if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { | ||
| 4050 | int loop = 500; | ||
| 4051 | u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | ||
| 4052 | while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { | ||
| 4053 | udelay(10); | ||
| 4054 | fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | ||
| 4055 | } | ||
| 4056 | if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES)) | ||
| 4057 | ++ret; | ||
| 4058 | dev_priv->gt_fifo_count = fifo; | ||
| 4059 | } | ||
| 4060 | dev_priv->gt_fifo_count--; | ||
| 4061 | |||
| 4062 | return ret; | ||
| 4063 | } | ||
| 4064 | |||
| 4065 | static void vlv_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 4066 | { | ||
| 4067 | /* Already awake? */ | ||
| 4068 | if ((I915_READ(0x130094) & 0xa1) == 0xa1) | ||
| 4069 | return; | ||
| 4070 | |||
| 4071 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff); | ||
| 4072 | POSTING_READ(FORCEWAKE_VLV); | ||
| 4073 | |||
| 4074 | if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1), 500)) | ||
| 4075 | DRM_ERROR("Force wake wait timed out\n"); | ||
| 4076 | |||
| 4077 | __gen6_gt_wait_for_thread_c0(dev_priv); | ||
| 4078 | } | ||
| 4079 | |||
| 4080 | static void vlv_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 4081 | { | ||
| 4082 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000); | ||
| 4083 | /* FIXME: confirm VLV behavior with Punit folks */ | ||
| 4084 | POSTING_READ(FORCEWAKE_VLV); | ||
| 4085 | } | ||
| 4086 | |||
| 4087 | void intel_gt_init(struct drm_device *dev) | ||
| 4088 | { | ||
| 4089 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 4090 | |||
| 4091 | spin_lock_init(&dev_priv->gt_lock); | ||
| 4092 | |||
| 4093 | if (IS_VALLEYVIEW(dev)) { | ||
| 4094 | dev_priv->gt.force_wake_get = vlv_force_wake_get; | ||
| 4095 | dev_priv->gt.force_wake_put = vlv_force_wake_put; | ||
| 4096 | } else if (INTEL_INFO(dev)->gen >= 6) { | ||
| 4097 | dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; | ||
| 4098 | dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; | ||
| 4099 | |||
| 4100 | /* IVB configs may use multi-threaded forcewake */ | ||
| 4101 | if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { | ||
| 4102 | u32 ecobus; | ||
| 4103 | |||
| 4104 | /* A small trick here - if the bios hasn't configured | ||
| 4105 | * MT forcewake, and if the device is in RC6, then | ||
| 4106 | * force_wake_mt_get will not wake the device and the | ||
| 4107 | * ECOBUS read will return zero. Which will be | ||
| 4108 | * (correctly) interpreted by the test below as MT | ||
| 4109 | * forcewake being disabled. | ||
| 4110 | */ | ||
| 4111 | mutex_lock(&dev->struct_mutex); | ||
| 4112 | __gen6_gt_force_wake_mt_get(dev_priv); | ||
| 4113 | ecobus = I915_READ_NOTRACE(ECOBUS); | ||
| 4114 | __gen6_gt_force_wake_mt_put(dev_priv); | ||
| 4115 | mutex_unlock(&dev->struct_mutex); | ||
| 4116 | |||
| 4117 | if (ecobus & FORCEWAKE_MT_ENABLE) { | ||
| 4118 | DRM_DEBUG_KMS("Using MT version of forcewake\n"); | ||
| 4119 | dev_priv->gt.force_wake_get = | ||
| 4120 | __gen6_gt_force_wake_mt_get; | ||
| 4121 | dev_priv->gt.force_wake_put = | ||
| 4122 | __gen6_gt_force_wake_mt_put; | ||
| 4123 | } | ||
| 4124 | } | ||
| 4125 | } | ||
| 3819 | } | 4126 | } |
| 3820 | 4127 | ||
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e5b84ff89ca5..bf0195a96d53 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
| @@ -219,19 +219,28 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring, | |||
| 219 | int ret; | 219 | int ret; |
| 220 | 220 | ||
| 221 | /* Force SNB workarounds for PIPE_CONTROL flushes */ | 221 | /* Force SNB workarounds for PIPE_CONTROL flushes */ |
| 222 | intel_emit_post_sync_nonzero_flush(ring); | 222 | ret = intel_emit_post_sync_nonzero_flush(ring); |
| 223 | if (ret) | ||
| 224 | return ret; | ||
| 223 | 225 | ||
| 224 | /* Just flush everything. Experiments have shown that reducing the | 226 | /* Just flush everything. Experiments have shown that reducing the |
| 225 | * number of bits based on the write domains has little performance | 227 | * number of bits based on the write domains has little performance |
| 226 | * impact. | 228 | * impact. |
| 227 | */ | 229 | */ |
| 228 | flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; | 230 | flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; |
| 231 | flags |= PIPE_CONTROL_TLB_INVALIDATE; | ||
| 229 | flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; | 232 | flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; |
| 230 | flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; | 233 | flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; |
| 231 | flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; | 234 | flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; |
| 232 | flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; | 235 | flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; |
| 233 | flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; | 236 | flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; |
| 234 | flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; | 237 | flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; |
| 238 | /* | ||
| 239 | * Ensure that any following seqno writes only happen when the render | ||
| 240 | * cache is indeed flushed (but only if the caller actually wants that). | ||
| 241 | */ | ||
| 242 | if (flush_domains) | ||
| 243 | flags |= PIPE_CONTROL_CS_STALL; | ||
| 235 | 244 | ||
| 236 | ret = intel_ring_begin(ring, 6); | 245 | ret = intel_ring_begin(ring, 6); |
| 237 | if (ret) | 246 | if (ret) |
| @@ -433,11 +442,21 @@ static int init_render_ring(struct intel_ring_buffer *ring) | |||
| 433 | */ | 442 | */ |
| 434 | I915_WRITE(CACHE_MODE_0, | 443 | I915_WRITE(CACHE_MODE_0, |
| 435 | _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); | 444 | _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); |
| 445 | |||
| 446 | /* This is not explicitly set for GEN6, so read the register. | ||
| 447 | * see intel_ring_mi_set_context() for why we care. | ||
| 448 | * TODO: consider explicitly setting the bit for GEN5 | ||
| 449 | */ | ||
| 450 | ring->itlb_before_ctx_switch = | ||
| 451 | !!(I915_READ(GFX_MODE) & GFX_TLB_INVALIDATE_ALWAYS); | ||
| 436 | } | 452 | } |
| 437 | 453 | ||
| 438 | if (INTEL_INFO(dev)->gen >= 6) | 454 | if (INTEL_INFO(dev)->gen >= 6) |
| 439 | I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); | 455 | I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); |
| 440 | 456 | ||
| 457 | if (IS_IVYBRIDGE(dev)) | ||
| 458 | I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); | ||
| 459 | |||
| 441 | return ret; | 460 | return ret; |
| 442 | } | 461 | } |
| 443 | 462 | ||
| @@ -825,7 +844,11 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) | |||
| 825 | 844 | ||
| 826 | spin_lock_irqsave(&dev_priv->irq_lock, flags); | 845 | spin_lock_irqsave(&dev_priv->irq_lock, flags); |
| 827 | if (ring->irq_refcount++ == 0) { | 846 | if (ring->irq_refcount++ == 0) { |
| 828 | I915_WRITE_IMR(ring, ~ring->irq_enable_mask); | 847 | if (IS_IVYBRIDGE(dev) && ring->id == RCS) |
| 848 | I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | | ||
| 849 | GEN6_RENDER_L3_PARITY_ERROR)); | ||
| 850 | else | ||
| 851 | I915_WRITE_IMR(ring, ~ring->irq_enable_mask); | ||
| 829 | dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; | 852 | dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; |
| 830 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); | 853 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); |
| 831 | POSTING_READ(GTIMR); | 854 | POSTING_READ(GTIMR); |
| @@ -844,7 +867,10 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) | |||
| 844 | 867 | ||
| 845 | spin_lock_irqsave(&dev_priv->irq_lock, flags); | 868 | spin_lock_irqsave(&dev_priv->irq_lock, flags); |
| 846 | if (--ring->irq_refcount == 0) { | 869 | if (--ring->irq_refcount == 0) { |
| 847 | I915_WRITE_IMR(ring, ~0); | 870 | if (IS_IVYBRIDGE(dev) && ring->id == RCS) |
| 871 | I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); | ||
| 872 | else | ||
| 873 | I915_WRITE_IMR(ring, ~0); | ||
| 848 | dev_priv->gt_irq_mask |= ring->irq_enable_mask; | 874 | dev_priv->gt_irq_mask |= ring->irq_enable_mask; |
| 849 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); | 875 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); |
| 850 | POSTING_READ(GTIMR); | 876 | POSTING_READ(GTIMR); |
| @@ -946,6 +972,7 @@ static int init_status_page(struct intel_ring_buffer *ring) | |||
| 946 | ring->status_page.gfx_addr = obj->gtt_offset; | 972 | ring->status_page.gfx_addr = obj->gtt_offset; |
| 947 | ring->status_page.page_addr = kmap(obj->pages[0]); | 973 | ring->status_page.page_addr = kmap(obj->pages[0]); |
| 948 | if (ring->status_page.page_addr == NULL) { | 974 | if (ring->status_page.page_addr == NULL) { |
| 975 | ret = -ENOMEM; | ||
| 949 | goto err_unpin; | 976 | goto err_unpin; |
| 950 | } | 977 | } |
| 951 | ring->status_page.obj = obj; | 978 | ring->status_page.obj = obj; |
| @@ -969,6 +996,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, | |||
| 969 | struct intel_ring_buffer *ring) | 996 | struct intel_ring_buffer *ring) |
| 970 | { | 997 | { |
| 971 | struct drm_i915_gem_object *obj; | 998 | struct drm_i915_gem_object *obj; |
| 999 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 972 | int ret; | 1000 | int ret; |
| 973 | 1001 | ||
| 974 | ring->dev = dev; | 1002 | ring->dev = dev; |
| @@ -1002,8 +1030,9 @@ static int intel_init_ring_buffer(struct drm_device *dev, | |||
| 1002 | if (ret) | 1030 | if (ret) |
| 1003 | goto err_unpin; | 1031 | goto err_unpin; |
| 1004 | 1032 | ||
| 1005 | ring->virtual_start = ioremap_wc(dev->agp->base + obj->gtt_offset, | 1033 | ring->virtual_start = |
| 1006 | ring->size); | 1034 | ioremap_wc(dev_priv->mm.gtt->gma_bus_addr + obj->gtt_offset, |
| 1035 | ring->size); | ||
| 1007 | if (ring->virtual_start == NULL) { | 1036 | if (ring->virtual_start == NULL) { |
| 1008 | DRM_ERROR("Failed to map ringbuffer.\n"); | 1037 | DRM_ERROR("Failed to map ringbuffer.\n"); |
| 1009 | ret = -EINVAL; | 1038 | ret = -EINVAL; |
| @@ -1089,20 +1118,9 @@ static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring) | |||
| 1089 | 1118 | ||
| 1090 | static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno) | 1119 | static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno) |
| 1091 | { | 1120 | { |
| 1092 | struct drm_i915_private *dev_priv = ring->dev->dev_private; | ||
| 1093 | bool was_interruptible; | ||
| 1094 | int ret; | 1121 | int ret; |
| 1095 | 1122 | ||
| 1096 | /* XXX As we have not yet audited all the paths to check that | 1123 | ret = i915_wait_seqno(ring, seqno); |
| 1097 | * they are ready for ERESTARTSYS from intel_ring_begin, do not | ||
| 1098 | * allow us to be interruptible by a signal. | ||
| 1099 | */ | ||
| 1100 | was_interruptible = dev_priv->mm.interruptible; | ||
| 1101 | dev_priv->mm.interruptible = false; | ||
| 1102 | |||
| 1103 | ret = i915_wait_request(ring, seqno); | ||
| 1104 | |||
| 1105 | dev_priv->mm.interruptible = was_interruptible; | ||
| 1106 | if (!ret) | 1124 | if (!ret) |
| 1107 | i915_gem_retire_requests_ring(ring); | 1125 | i915_gem_retire_requests_ring(ring); |
| 1108 | 1126 | ||
| @@ -1200,8 +1218,10 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) | |||
| 1200 | } | 1218 | } |
| 1201 | 1219 | ||
| 1202 | msleep(1); | 1220 | msleep(1); |
| 1203 | if (atomic_read(&dev_priv->mm.wedged)) | 1221 | |
| 1204 | return -EAGAIN; | 1222 | ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); |
| 1223 | if (ret) | ||
| 1224 | return ret; | ||
| 1205 | } while (!time_after(jiffies, end)); | 1225 | } while (!time_after(jiffies, end)); |
| 1206 | trace_i915_ring_wait_end(ring); | 1226 | trace_i915_ring_wait_end(ring); |
| 1207 | return -EBUSY; | 1227 | return -EBUSY; |
| @@ -1210,12 +1230,13 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) | |||
| 1210 | int intel_ring_begin(struct intel_ring_buffer *ring, | 1230 | int intel_ring_begin(struct intel_ring_buffer *ring, |
| 1211 | int num_dwords) | 1231 | int num_dwords) |
| 1212 | { | 1232 | { |
| 1213 | struct drm_i915_private *dev_priv = ring->dev->dev_private; | 1233 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
| 1214 | int n = 4*num_dwords; | 1234 | int n = 4*num_dwords; |
| 1215 | int ret; | 1235 | int ret; |
| 1216 | 1236 | ||
| 1217 | if (unlikely(atomic_read(&dev_priv->mm.wedged))) | 1237 | ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); |
| 1218 | return -EIO; | 1238 | if (ret) |
| 1239 | return ret; | ||
| 1219 | 1240 | ||
| 1220 | if (unlikely(ring->tail + n > ring->effective_size)) { | 1241 | if (unlikely(ring->tail + n > ring->effective_size)) { |
| 1221 | ret = intel_wrap_ring_buffer(ring); | 1242 | ret = intel_wrap_ring_buffer(ring); |
| @@ -1250,20 +1271,31 @@ static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring, | |||
| 1250 | drm_i915_private_t *dev_priv = ring->dev->dev_private; | 1271 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
| 1251 | 1272 | ||
| 1252 | /* Every tail move must follow the sequence below */ | 1273 | /* Every tail move must follow the sequence below */ |
| 1274 | |||
| 1275 | /* Disable notification that the ring is IDLE. The GT | ||
| 1276 | * will then assume that it is busy and bring it out of rc6. | ||
| 1277 | */ | ||
| 1253 | I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, | 1278 | I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, |
| 1254 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | | 1279 | _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); |
| 1255 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE); | ||
| 1256 | I915_WRITE(GEN6_BSD_RNCID, 0x0); | ||
| 1257 | 1280 | ||
| 1281 | /* Clear the context id. Here be magic! */ | ||
| 1282 | I915_WRITE64(GEN6_BSD_RNCID, 0x0); | ||
| 1283 | |||
| 1284 | /* Wait for the ring not to be idle, i.e. for it to wake up. */ | ||
| 1258 | if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & | 1285 | if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & |
| 1259 | GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0, | 1286 | GEN6_BSD_SLEEP_INDICATOR) == 0, |
| 1260 | 50)) | 1287 | 50)) |
| 1261 | DRM_ERROR("timed out waiting for IDLE Indicator\n"); | 1288 | DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); |
| 1262 | 1289 | ||
| 1290 | /* Now that the ring is fully powered up, update the tail */ | ||
| 1263 | I915_WRITE_TAIL(ring, value); | 1291 | I915_WRITE_TAIL(ring, value); |
| 1292 | POSTING_READ(RING_TAIL(ring->mmio_base)); | ||
| 1293 | |||
| 1294 | /* Let the ring send IDLE messages to the GT again, | ||
| 1295 | * and so let it sleep to conserve power when idle. | ||
| 1296 | */ | ||
| 1264 | I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, | 1297 | I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, |
| 1265 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | | 1298 | _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); |
| 1266 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE); | ||
| 1267 | } | 1299 | } |
| 1268 | 1300 | ||
| 1269 | static int gen6_ring_flush(struct intel_ring_buffer *ring, | 1301 | static int gen6_ring_flush(struct intel_ring_buffer *ring, |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 55d3da26bae7..1d3c81fdad92 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
| @@ -113,9 +113,17 @@ struct intel_ring_buffer { | |||
| 113 | * Do we have some not yet emitted requests outstanding? | 113 | * Do we have some not yet emitted requests outstanding? |
| 114 | */ | 114 | */ |
| 115 | u32 outstanding_lazy_request; | 115 | u32 outstanding_lazy_request; |
| 116 | bool gpu_caches_dirty; | ||
| 116 | 117 | ||
| 117 | wait_queue_head_t irq_queue; | 118 | wait_queue_head_t irq_queue; |
| 118 | 119 | ||
| 120 | /** | ||
| 121 | * Do an explicit TLB flush before MI_SET_CONTEXT | ||
| 122 | */ | ||
| 123 | bool itlb_before_ctx_switch; | ||
| 124 | struct i915_hw_context *default_context; | ||
| 125 | struct drm_i915_gem_object *last_context_obj; | ||
| 126 | |||
| 119 | void *private; | 127 | void *private; |
| 120 | }; | 128 | }; |
| 121 | 129 | ||
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index b6a9d45fc3c6..26a6a4d0d078 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -140,9 +140,6 @@ struct intel_sdvo { | |||
| 140 | 140 | ||
| 141 | /* DDC bus used by this SDVO encoder */ | 141 | /* DDC bus used by this SDVO encoder */ |
| 142 | uint8_t ddc_bus; | 142 | uint8_t ddc_bus; |
| 143 | |||
| 144 | /* Input timings for adjusted_mode */ | ||
| 145 | struct intel_sdvo_dtd input_dtd; | ||
| 146 | }; | 143 | }; |
| 147 | 144 | ||
| 148 | struct intel_sdvo_connector { | 145 | struct intel_sdvo_connector { |
| @@ -938,7 +935,7 @@ static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) | |||
| 938 | 935 | ||
| 939 | static bool | 936 | static bool |
| 940 | intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, | 937 | intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, |
| 941 | struct drm_display_mode *mode) | 938 | const struct drm_display_mode *mode) |
| 942 | { | 939 | { |
| 943 | struct intel_sdvo_dtd output_dtd; | 940 | struct intel_sdvo_dtd output_dtd; |
| 944 | 941 | ||
| @@ -953,11 +950,15 @@ intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, | |||
| 953 | return true; | 950 | return true; |
| 954 | } | 951 | } |
| 955 | 952 | ||
| 953 | /* Asks the sdvo controller for the preferred input mode given the output mode. | ||
| 954 | * Unfortunately we have to set up the full output mode to do that. */ | ||
| 956 | static bool | 955 | static bool |
| 957 | intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, | 956 | intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, |
| 958 | struct drm_display_mode *mode, | 957 | const struct drm_display_mode *mode, |
| 959 | struct drm_display_mode *adjusted_mode) | 958 | struct drm_display_mode *adjusted_mode) |
| 960 | { | 959 | { |
| 960 | struct intel_sdvo_dtd input_dtd; | ||
| 961 | |||
| 961 | /* Reset the input timing to the screen. Assume always input 0. */ | 962 | /* Reset the input timing to the screen. Assume always input 0. */ |
| 962 | if (!intel_sdvo_set_target_input(intel_sdvo)) | 963 | if (!intel_sdvo_set_target_input(intel_sdvo)) |
| 963 | return false; | 964 | return false; |
| @@ -969,16 +970,16 @@ intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, | |||
| 969 | return false; | 970 | return false; |
| 970 | 971 | ||
| 971 | if (!intel_sdvo_get_preferred_input_timing(intel_sdvo, | 972 | if (!intel_sdvo_get_preferred_input_timing(intel_sdvo, |
| 972 | &intel_sdvo->input_dtd)) | 973 | &input_dtd)) |
| 973 | return false; | 974 | return false; |
| 974 | 975 | ||
| 975 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &intel_sdvo->input_dtd); | 976 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); |
| 976 | 977 | ||
| 977 | return true; | 978 | return true; |
| 978 | } | 979 | } |
| 979 | 980 | ||
| 980 | static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | 981 | static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, |
| 981 | struct drm_display_mode *mode, | 982 | const struct drm_display_mode *mode, |
| 982 | struct drm_display_mode *adjusted_mode) | 983 | struct drm_display_mode *adjusted_mode) |
| 983 | { | 984 | { |
| 984 | struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); | 985 | struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); |
| @@ -993,17 +994,17 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
| 993 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) | 994 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) |
| 994 | return false; | 995 | return false; |
| 995 | 996 | ||
| 996 | (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, | 997 | (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, |
| 997 | mode, | 998 | mode, |
| 998 | adjusted_mode); | 999 | adjusted_mode); |
| 999 | } else if (intel_sdvo->is_lvds) { | 1000 | } else if (intel_sdvo->is_lvds) { |
| 1000 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, | 1001 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, |
| 1001 | intel_sdvo->sdvo_lvds_fixed_mode)) | 1002 | intel_sdvo->sdvo_lvds_fixed_mode)) |
| 1002 | return false; | 1003 | return false; |
| 1003 | 1004 | ||
| 1004 | (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, | 1005 | (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, |
| 1005 | mode, | 1006 | mode, |
| 1006 | adjusted_mode); | 1007 | adjusted_mode); |
| 1007 | } | 1008 | } |
| 1008 | 1009 | ||
| 1009 | /* Make the CRTC code factor in the SDVO pixel multiplier. The | 1010 | /* Make the CRTC code factor in the SDVO pixel multiplier. The |
| @@ -1057,7 +1058,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1057 | intel_sdvo->sdvo_lvds_fixed_mode); | 1058 | intel_sdvo->sdvo_lvds_fixed_mode); |
| 1058 | else | 1059 | else |
| 1059 | intel_sdvo_get_dtd_from_mode(&output_dtd, mode); | 1060 | intel_sdvo_get_dtd_from_mode(&output_dtd, mode); |
| 1060 | (void) intel_sdvo_set_output_timing(intel_sdvo, &output_dtd); | 1061 | if (!intel_sdvo_set_output_timing(intel_sdvo, &output_dtd)) |
| 1062 | DRM_INFO("Setting output timings on %s failed\n", | ||
| 1063 | SDVO_NAME(intel_sdvo)); | ||
| 1061 | 1064 | ||
| 1062 | /* Set the input timing to the screen. Assume always input 0. */ | 1065 | /* Set the input timing to the screen. Assume always input 0. */ |
| 1063 | if (!intel_sdvo_set_target_input(intel_sdvo)) | 1066 | if (!intel_sdvo_set_target_input(intel_sdvo)) |
| @@ -1079,7 +1082,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1079 | * adjusted_mode. | 1082 | * adjusted_mode. |
| 1080 | */ | 1083 | */ |
| 1081 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); | 1084 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); |
| 1082 | (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd); | 1085 | if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) |
| 1086 | DRM_INFO("Setting input timings on %s failed\n", | ||
| 1087 | SDVO_NAME(intel_sdvo)); | ||
| 1083 | 1088 | ||
| 1084 | switch (pixel_multiplier) { | 1089 | switch (pixel_multiplier) { |
| 1085 | default: | 1090 | default: |
| @@ -1376,7 +1381,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) | |||
| 1376 | 1381 | ||
| 1377 | /* add 30ms delay when the output type might be TV */ | 1382 | /* add 30ms delay when the output type might be TV */ |
| 1378 | if (intel_sdvo->caps.output_flags & SDVO_TV_MASK) | 1383 | if (intel_sdvo->caps.output_flags & SDVO_TV_MASK) |
| 1379 | mdelay(30); | 1384 | msleep(30); |
| 1380 | 1385 | ||
| 1381 | if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) | 1386 | if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) |
| 1382 | return connector_status_unknown; | 1387 | return connector_status_unknown; |
| @@ -2521,6 +2526,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) | |||
| 2521 | struct drm_i915_private *dev_priv = dev->dev_private; | 2526 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2522 | struct intel_encoder *intel_encoder; | 2527 | struct intel_encoder *intel_encoder; |
| 2523 | struct intel_sdvo *intel_sdvo; | 2528 | struct intel_sdvo *intel_sdvo; |
| 2529 | u32 hotplug_mask; | ||
| 2524 | int i; | 2530 | int i; |
| 2525 | 2531 | ||
| 2526 | intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); | 2532 | intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); |
| @@ -2552,10 +2558,18 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) | |||
| 2552 | } | 2558 | } |
| 2553 | } | 2559 | } |
| 2554 | 2560 | ||
| 2555 | if (intel_sdvo->is_sdvob) | 2561 | hotplug_mask = 0; |
| 2556 | dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; | 2562 | if (IS_G4X(dev)) { |
| 2557 | else | 2563 | hotplug_mask = intel_sdvo->is_sdvob ? |
| 2558 | dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; | 2564 | SDVOB_HOTPLUG_INT_STATUS_G4X : SDVOC_HOTPLUG_INT_STATUS_G4X; |
| 2565 | } else if (IS_GEN4(dev)) { | ||
| 2566 | hotplug_mask = intel_sdvo->is_sdvob ? | ||
| 2567 | SDVOB_HOTPLUG_INT_STATUS_I965 : SDVOC_HOTPLUG_INT_STATUS_I965; | ||
| 2568 | } else { | ||
| 2569 | hotplug_mask = intel_sdvo->is_sdvob ? | ||
| 2570 | SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915; | ||
| 2571 | } | ||
| 2572 | dev_priv->hotplug_supported_mask |= hotplug_mask; | ||
| 2559 | 2573 | ||
| 2560 | drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); | 2574 | drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); |
| 2561 | 2575 | ||
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 2a20fb0781d7..cc8df4de2d92 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
| @@ -56,6 +56,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
| 56 | sprctl &= ~SPRITE_PIXFORMAT_MASK; | 56 | sprctl &= ~SPRITE_PIXFORMAT_MASK; |
| 57 | sprctl &= ~SPRITE_RGB_ORDER_RGBX; | 57 | sprctl &= ~SPRITE_RGB_ORDER_RGBX; |
| 58 | sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK; | 58 | sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK; |
| 59 | sprctl &= ~SPRITE_TILED; | ||
| 59 | 60 | ||
| 60 | switch (fb->pixel_format) { | 61 | switch (fb->pixel_format) { |
| 61 | case DRM_FORMAT_XBGR8888: | 62 | case DRM_FORMAT_XBGR8888: |
| @@ -84,7 +85,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
| 84 | break; | 85 | break; |
| 85 | default: | 86 | default: |
| 86 | DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n"); | 87 | DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n"); |
| 87 | sprctl |= DVS_FORMAT_RGBX888; | 88 | sprctl |= SPRITE_FORMAT_RGBX888; |
| 88 | pixel_size = 4; | 89 | pixel_size = 4; |
| 89 | break; | 90 | break; |
| 90 | } | 91 | } |
| @@ -233,6 +234,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
| 233 | dvscntr &= ~DVS_PIXFORMAT_MASK; | 234 | dvscntr &= ~DVS_PIXFORMAT_MASK; |
| 234 | dvscntr &= ~DVS_RGB_ORDER_XBGR; | 235 | dvscntr &= ~DVS_RGB_ORDER_XBGR; |
| 235 | dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK; | 236 | dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK; |
| 237 | dvscntr &= ~DVS_TILED; | ||
| 236 | 238 | ||
| 237 | switch (fb->pixel_format) { | 239 | switch (fb->pixel_format) { |
| 238 | case DRM_FORMAT_XBGR8888: | 240 | case DRM_FORMAT_XBGR8888: |
| @@ -326,6 +328,12 @@ intel_enable_primary(struct drm_crtc *crtc) | |||
| 326 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 328 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 327 | int reg = DSPCNTR(intel_crtc->plane); | 329 | int reg = DSPCNTR(intel_crtc->plane); |
| 328 | 330 | ||
| 331 | if (!intel_crtc->primary_disabled) | ||
| 332 | return; | ||
| 333 | |||
| 334 | intel_crtc->primary_disabled = false; | ||
| 335 | intel_update_fbc(dev); | ||
| 336 | |||
| 329 | I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); | 337 | I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); |
| 330 | } | 338 | } |
| 331 | 339 | ||
| @@ -337,7 +345,13 @@ intel_disable_primary(struct drm_crtc *crtc) | |||
| 337 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 345 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 338 | int reg = DSPCNTR(intel_crtc->plane); | 346 | int reg = DSPCNTR(intel_crtc->plane); |
| 339 | 347 | ||
| 348 | if (intel_crtc->primary_disabled) | ||
| 349 | return; | ||
| 350 | |||
| 340 | I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); | 351 | I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); |
| 352 | |||
| 353 | intel_crtc->primary_disabled = true; | ||
| 354 | intel_update_fbc(dev); | ||
| 341 | } | 355 | } |
| 342 | 356 | ||
| 343 | static int | 357 | static int |
| @@ -485,18 +499,14 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
| 485 | * Be sure to re-enable the primary before the sprite is no longer | 499 | * Be sure to re-enable the primary before the sprite is no longer |
| 486 | * covering it fully. | 500 | * covering it fully. |
| 487 | */ | 501 | */ |
| 488 | if (!disable_primary && intel_plane->primary_disabled) { | 502 | if (!disable_primary) |
| 489 | intel_enable_primary(crtc); | 503 | intel_enable_primary(crtc); |
| 490 | intel_plane->primary_disabled = false; | ||
| 491 | } | ||
| 492 | 504 | ||
| 493 | intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, | 505 | intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, |
| 494 | crtc_w, crtc_h, x, y, src_w, src_h); | 506 | crtc_w, crtc_h, x, y, src_w, src_h); |
| 495 | 507 | ||
| 496 | if (disable_primary) { | 508 | if (disable_primary) |
| 497 | intel_disable_primary(crtc); | 509 | intel_disable_primary(crtc); |
| 498 | intel_plane->primary_disabled = true; | ||
| 499 | } | ||
| 500 | 510 | ||
| 501 | /* Unpin old obj after new one is active to avoid ugliness */ | 511 | /* Unpin old obj after new one is active to avoid ugliness */ |
| 502 | if (old_obj) { | 512 | if (old_obj) { |
| @@ -527,11 +537,8 @@ intel_disable_plane(struct drm_plane *plane) | |||
| 527 | struct intel_plane *intel_plane = to_intel_plane(plane); | 537 | struct intel_plane *intel_plane = to_intel_plane(plane); |
| 528 | int ret = 0; | 538 | int ret = 0; |
| 529 | 539 | ||
| 530 | if (intel_plane->primary_disabled) { | 540 | if (plane->crtc) |
| 531 | intel_enable_primary(plane->crtc); | 541 | intel_enable_primary(plane->crtc); |
| 532 | intel_plane->primary_disabled = false; | ||
| 533 | } | ||
| 534 | |||
| 535 | intel_plane->disable_plane(plane); | 542 | intel_plane->disable_plane(plane); |
| 536 | 543 | ||
| 537 | if (!intel_plane->obj) | 544 | if (!intel_plane->obj) |
| @@ -685,6 +692,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) | |||
| 685 | break; | 692 | break; |
| 686 | 693 | ||
| 687 | default: | 694 | default: |
| 695 | kfree(intel_plane); | ||
| 688 | return -ENODEV; | 696 | return -ENODEV; |
| 689 | } | 697 | } |
| 690 | 698 | ||
| @@ -699,4 +707,3 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) | |||
| 699 | 707 | ||
| 700 | return ret; | 708 | return ret; |
| 701 | } | 709 | } |
| 702 | |||
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index a233a51fd7e6..befce6c49704 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
| @@ -891,24 +891,21 @@ intel_tv_mode_valid(struct drm_connector *connector, | |||
| 891 | 891 | ||
| 892 | 892 | ||
| 893 | static bool | 893 | static bool |
| 894 | intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 894 | intel_tv_mode_fixup(struct drm_encoder *encoder, |
| 895 | const struct drm_display_mode *mode, | ||
| 895 | struct drm_display_mode *adjusted_mode) | 896 | struct drm_display_mode *adjusted_mode) |
| 896 | { | 897 | { |
| 897 | struct drm_device *dev = encoder->dev; | 898 | struct drm_device *dev = encoder->dev; |
| 898 | struct drm_mode_config *drm_config = &dev->mode_config; | ||
| 899 | struct intel_tv *intel_tv = enc_to_intel_tv(encoder); | 899 | struct intel_tv *intel_tv = enc_to_intel_tv(encoder); |
| 900 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); | 900 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); |
| 901 | struct drm_encoder *other_encoder; | 901 | struct intel_encoder *other_encoder; |
| 902 | 902 | ||
| 903 | if (!tv_mode) | 903 | if (!tv_mode) |
| 904 | return false; | 904 | return false; |
| 905 | 905 | ||
| 906 | /* FIXME: lock encoder list */ | 906 | for_each_encoder_on_crtc(dev, encoder->crtc, other_encoder) |
| 907 | list_for_each_entry(other_encoder, &drm_config->encoder_list, head) { | 907 | if (&other_encoder->base != encoder) |
| 908 | if (other_encoder != encoder && | ||
| 909 | other_encoder->crtc == encoder->crtc) | ||
| 910 | return false; | 908 | return false; |
| 911 | } | ||
| 912 | 909 | ||
| 913 | adjusted_mode->clock = tv_mode->clock; | 910 | adjusted_mode->clock = tv_mode->clock; |
| 914 | return true; | 911 | return true; |
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index f9a925d58819..b1bb46de3f5a 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c | |||
| @@ -75,7 +75,6 @@ static struct drm_driver driver = { | |||
| 75 | .irq_postinstall = mga_driver_irq_postinstall, | 75 | .irq_postinstall = mga_driver_irq_postinstall, |
| 76 | .irq_uninstall = mga_driver_irq_uninstall, | 76 | .irq_uninstall = mga_driver_irq_uninstall, |
| 77 | .irq_handler = mga_driver_irq_handler, | 77 | .irq_handler = mga_driver_irq_handler, |
| 78 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 79 | .ioctls = mga_ioctls, | 78 | .ioctls = mga_ioctls, |
| 80 | .dma_ioctl = mga_dma_buffers, | 79 | .dma_ioctl = mga_dma_buffers, |
| 81 | .fops = &mga_driver_fops, | 80 | .fops = &mga_driver_fops, |
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 93e832d6c328..ea1024d79974 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c | |||
| @@ -47,6 +47,9 @@ static void mgag200_kick_out_firmware_fb(struct pci_dev *pdev) | |||
| 47 | bool primary = false; | 47 | bool primary = false; |
| 48 | 48 | ||
| 49 | ap = alloc_apertures(1); | 49 | ap = alloc_apertures(1); |
| 50 | if (!ap) | ||
| 51 | return; | ||
| 52 | |||
| 50 | ap->ranges[0].base = pci_resource_start(pdev, 0); | 53 | ap->ranges[0].base = pci_resource_start(pdev, 0); |
| 51 | ap->ranges[0].size = pci_resource_len(pdev, 0); | 54 | ap->ranges[0].size = pci_resource_len(pdev, 0); |
| 52 | 55 | ||
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index d303061b251e..a4d7c500c97b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c | |||
| @@ -78,8 +78,8 @@ static inline void mga_wait_busy(struct mga_device *mdev) | |||
| 78 | * to just pass that straight through, so this does nothing | 78 | * to just pass that straight through, so this does nothing |
| 79 | */ | 79 | */ |
| 80 | static bool mga_crtc_mode_fixup(struct drm_crtc *crtc, | 80 | static bool mga_crtc_mode_fixup(struct drm_crtc *crtc, |
| 81 | struct drm_display_mode *mode, | 81 | const struct drm_display_mode *mode, |
| 82 | struct drm_display_mode *adjusted_mode) | 82 | struct drm_display_mode *adjusted_mode) |
| 83 | { | 83 | { |
| 84 | return true; | 84 | return true; |
| 85 | } | 85 | } |
| @@ -1322,8 +1322,8 @@ void mga_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
| 1322 | * to handle any encoder-specific limitations | 1322 | * to handle any encoder-specific limitations |
| 1323 | */ | 1323 | */ |
| 1324 | static bool mga_encoder_mode_fixup(struct drm_encoder *encoder, | 1324 | static bool mga_encoder_mode_fixup(struct drm_encoder *encoder, |
| 1325 | struct drm_display_mode *mode, | 1325 | const struct drm_display_mode *mode, |
| 1326 | struct drm_display_mode *adjusted_mode) | 1326 | struct drm_display_mode *adjusted_mode) |
| 1327 | { | 1327 | { |
| 1328 | return true; | 1328 | return true; |
| 1329 | } | 1329 | } |
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index fe5267d06ab5..1cece6a78f39 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | ccflags-y := -Iinclude/drm | 5 | ccflags-y := -Iinclude/drm |
| 6 | nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | 6 | nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ |
| 7 | nouveau_object.o nouveau_irq.o nouveau_notifier.o \ | 7 | nouveau_gpuobj.o nouveau_irq.o nouveau_notifier.o \ |
| 8 | nouveau_sgdma.o nouveau_dma.o nouveau_util.o \ | 8 | nouveau_sgdma.o nouveau_dma.o nouveau_util.o \ |
| 9 | nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ | 9 | nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ |
| 10 | nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ | 10 | nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ |
| @@ -12,6 +12,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
| 12 | nouveau_hdmi.o nouveau_dp.o nouveau_ramht.o \ | 12 | nouveau_hdmi.o nouveau_dp.o nouveau_ramht.o \ |
| 13 | nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ | 13 | nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ |
| 14 | nouveau_mm.o nouveau_vm.o nouveau_mxm.o nouveau_gpio.o \ | 14 | nouveau_mm.o nouveau_vm.o nouveau_mxm.o nouveau_gpio.o \ |
| 15 | nouveau_abi16.o \ | ||
| 15 | nv04_timer.o \ | 16 | nv04_timer.o \ |
| 16 | nv04_mc.o nv40_mc.o nv50_mc.o \ | 17 | nv04_mc.o nv40_mc.o nv50_mc.o \ |
| 17 | nv04_fb.o nv10_fb.o nv20_fb.o nv30_fb.o nv40_fb.o \ | 18 | nv04_fb.o nv10_fb.o nv20_fb.o nv30_fb.o nv40_fb.o \ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c new file mode 100644 index 000000000000..ff23d88880e5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c | |||
| @@ -0,0 +1,245 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2012 Red Hat Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include "drmP.h" | ||
| 25 | |||
| 26 | #include "nouveau_drv.h" | ||
| 27 | #include "nouveau_dma.h" | ||
| 28 | #include "nouveau_abi16.h" | ||
| 29 | #include "nouveau_ramht.h" | ||
| 30 | #include "nouveau_software.h" | ||
| 31 | |||
| 32 | int | ||
| 33 | nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) | ||
| 34 | { | ||
| 35 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 36 | struct drm_nouveau_getparam *getparam = data; | ||
| 37 | |||
| 38 | switch (getparam->param) { | ||
| 39 | case NOUVEAU_GETPARAM_CHIPSET_ID: | ||
| 40 | getparam->value = dev_priv->chipset; | ||
| 41 | break; | ||
| 42 | case NOUVEAU_GETPARAM_PCI_VENDOR: | ||
| 43 | getparam->value = dev->pci_vendor; | ||
| 44 | break; | ||
| 45 | case NOUVEAU_GETPARAM_PCI_DEVICE: | ||
| 46 | getparam->value = dev->pci_device; | ||
| 47 | break; | ||
| 48 | case NOUVEAU_GETPARAM_BUS_TYPE: | ||
| 49 | if (drm_pci_device_is_agp(dev)) | ||
| 50 | getparam->value = 0; | ||
| 51 | else | ||
| 52 | if (!pci_is_pcie(dev->pdev)) | ||
| 53 | getparam->value = 1; | ||
| 54 | else | ||
| 55 | getparam->value = 2; | ||
| 56 | break; | ||
| 57 | case NOUVEAU_GETPARAM_FB_SIZE: | ||
| 58 | getparam->value = dev_priv->fb_available_size; | ||
| 59 | break; | ||
| 60 | case NOUVEAU_GETPARAM_AGP_SIZE: | ||
| 61 | getparam->value = dev_priv->gart_info.aper_size; | ||
| 62 | break; | ||
| 63 | case NOUVEAU_GETPARAM_VM_VRAM_BASE: | ||
| 64 | getparam->value = 0; /* deprecated */ | ||
| 65 | break; | ||
| 66 | case NOUVEAU_GETPARAM_PTIMER_TIME: | ||
| 67 | getparam->value = dev_priv->engine.timer.read(dev); | ||
| 68 | break; | ||
| 69 | case NOUVEAU_GETPARAM_HAS_BO_USAGE: | ||
| 70 | getparam->value = 1; | ||
| 71 | break; | ||
| 72 | case NOUVEAU_GETPARAM_HAS_PAGEFLIP: | ||
| 73 | getparam->value = 1; | ||
| 74 | break; | ||
| 75 | case NOUVEAU_GETPARAM_GRAPH_UNITS: | ||
| 76 | /* NV40 and NV50 versions are quite different, but register | ||
| 77 | * address is the same. User is supposed to know the card | ||
| 78 | * family anyway... */ | ||
| 79 | if (dev_priv->chipset >= 0x40) { | ||
| 80 | getparam->value = nv_rd32(dev, NV40_PMC_GRAPH_UNITS); | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | /* FALLTHRU */ | ||
| 84 | default: | ||
| 85 | NV_DEBUG(dev, "unknown parameter %lld\n", getparam->param); | ||
| 86 | return -EINVAL; | ||
| 87 | } | ||
| 88 | |||
| 89 | return 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | int | ||
| 93 | nouveau_abi16_ioctl_setparam(ABI16_IOCTL_ARGS) | ||
| 94 | { | ||
| 95 | return -EINVAL; | ||
| 96 | } | ||
| 97 | |||
| 98 | int | ||
| 99 | nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) | ||
| 100 | { | ||
| 101 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 102 | struct drm_nouveau_channel_alloc *init = data; | ||
| 103 | struct nouveau_channel *chan; | ||
| 104 | int ret; | ||
| 105 | |||
| 106 | if (!dev_priv->eng[NVOBJ_ENGINE_GR]) | ||
| 107 | return -ENODEV; | ||
| 108 | |||
| 109 | if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) | ||
| 110 | return -EINVAL; | ||
| 111 | |||
| 112 | ret = nouveau_channel_alloc(dev, &chan, file_priv, | ||
| 113 | init->fb_ctxdma_handle, | ||
| 114 | init->tt_ctxdma_handle); | ||
| 115 | if (ret) | ||
| 116 | return ret; | ||
| 117 | init->channel = chan->id; | ||
| 118 | |||
| 119 | if (nouveau_vram_pushbuf == 0) { | ||
| 120 | if (chan->dma.ib_max) | ||
| 121 | init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | | ||
| 122 | NOUVEAU_GEM_DOMAIN_GART; | ||
| 123 | else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM) | ||
| 124 | init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; | ||
| 125 | else | ||
| 126 | init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; | ||
| 127 | } else { | ||
| 128 | init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; | ||
| 129 | } | ||
| 130 | |||
| 131 | if (dev_priv->card_type < NV_C0) { | ||
| 132 | init->subchan[0].handle = 0x00000000; | ||
| 133 | init->subchan[0].grclass = 0x0000; | ||
| 134 | init->subchan[1].handle = NvSw; | ||
| 135 | init->subchan[1].grclass = NV_SW; | ||
| 136 | init->nr_subchan = 2; | ||
| 137 | } | ||
| 138 | |||
| 139 | /* Named memory object area */ | ||
| 140 | ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, | ||
| 141 | &init->notifier_handle); | ||
| 142 | |||
| 143 | if (ret == 0) | ||
| 144 | atomic_inc(&chan->users); /* userspace reference */ | ||
| 145 | nouveau_channel_put(&chan); | ||
| 146 | return ret; | ||
| 147 | } | ||
| 148 | |||
| 149 | int | ||
| 150 | nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS) | ||
| 151 | { | ||
| 152 | struct drm_nouveau_channel_free *req = data; | ||
| 153 | struct nouveau_channel *chan; | ||
| 154 | |||
| 155 | chan = nouveau_channel_get(file_priv, req->channel); | ||
| 156 | if (IS_ERR(chan)) | ||
| 157 | return PTR_ERR(chan); | ||
| 158 | |||
| 159 | list_del(&chan->list); | ||
| 160 | atomic_dec(&chan->users); | ||
| 161 | nouveau_channel_put(&chan); | ||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | int | ||
| 166 | nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS) | ||
| 167 | { | ||
| 168 | struct drm_nouveau_grobj_alloc *init = data; | ||
| 169 | struct nouveau_channel *chan; | ||
| 170 | int ret; | ||
| 171 | |||
| 172 | if (init->handle == ~0) | ||
| 173 | return -EINVAL; | ||
| 174 | |||
| 175 | /* compatibility with userspace that assumes 506e for all chipsets */ | ||
| 176 | if (init->class == 0x506e) { | ||
| 177 | init->class = nouveau_software_class(dev); | ||
| 178 | if (init->class == 0x906e) | ||
| 179 | return 0; | ||
| 180 | } else | ||
| 181 | if (init->class == 0x906e) { | ||
| 182 | NV_ERROR(dev, "906e not supported yet\n"); | ||
| 183 | return -EINVAL; | ||
| 184 | } | ||
| 185 | |||
| 186 | chan = nouveau_channel_get(file_priv, init->channel); | ||
| 187 | if (IS_ERR(chan)) | ||
| 188 | return PTR_ERR(chan); | ||
| 189 | |||
| 190 | if (nouveau_ramht_find(chan, init->handle)) { | ||
| 191 | ret = -EEXIST; | ||
| 192 | goto out; | ||
| 193 | } | ||
| 194 | |||
| 195 | ret = nouveau_gpuobj_gr_new(chan, init->handle, init->class); | ||
| 196 | if (ret) { | ||
| 197 | NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n", | ||
| 198 | ret, init->channel, init->handle); | ||
| 199 | } | ||
| 200 | |||
| 201 | out: | ||
| 202 | nouveau_channel_put(&chan); | ||
| 203 | return ret; | ||
| 204 | } | ||
| 205 | |||
| 206 | int | ||
| 207 | nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) | ||
| 208 | { | ||
| 209 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 210 | struct drm_nouveau_notifierobj_alloc *na = data; | ||
| 211 | struct nouveau_channel *chan; | ||
| 212 | int ret; | ||
| 213 | |||
| 214 | /* completely unnecessary for these chipsets... */ | ||
| 215 | if (unlikely(dev_priv->card_type >= NV_C0)) | ||
| 216 | return -EINVAL; | ||
| 217 | |||
| 218 | chan = nouveau_channel_get(file_priv, na->channel); | ||
| 219 | if (IS_ERR(chan)) | ||
| 220 | return PTR_ERR(chan); | ||
| 221 | |||
| 222 | ret = nouveau_notifier_alloc(chan, na->handle, na->size, 0, 0x1000, | ||
| 223 | &na->offset); | ||
| 224 | nouveau_channel_put(&chan); | ||
| 225 | return ret; | ||
| 226 | } | ||
| 227 | |||
| 228 | int | ||
| 229 | nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS) | ||
| 230 | { | ||
| 231 | struct drm_nouveau_gpuobj_free *objfree = data; | ||
| 232 | struct nouveau_channel *chan; | ||
| 233 | int ret; | ||
| 234 | |||
| 235 | chan = nouveau_channel_get(file_priv, objfree->channel); | ||
| 236 | if (IS_ERR(chan)) | ||
| 237 | return PTR_ERR(chan); | ||
| 238 | |||
| 239 | /* Synchronize with the user channel */ | ||
| 240 | nouveau_channel_idle(chan); | ||
| 241 | |||
| 242 | ret = nouveau_ramht_remove(chan, objfree->handle); | ||
| 243 | nouveau_channel_put(&chan); | ||
| 244 | return ret; | ||
| 245 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h new file mode 100644 index 000000000000..e6328b008a8c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | #ifndef __NOUVEAU_ABI16_H__ | ||
| 2 | #define __NOUVEAU_ABI16_H__ | ||
| 3 | |||
| 4 | #define ABI16_IOCTL_ARGS \ | ||
| 5 | struct drm_device *dev, void *data, struct drm_file *file_priv | ||
| 6 | int nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS); | ||
| 7 | int nouveau_abi16_ioctl_setparam(ABI16_IOCTL_ARGS); | ||
| 8 | int nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS); | ||
| 9 | int nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS); | ||
| 10 | int nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS); | ||
| 11 | int nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS); | ||
| 12 | int nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS); | ||
| 13 | |||
| 14 | struct drm_nouveau_channel_alloc { | ||
| 15 | uint32_t fb_ctxdma_handle; | ||
| 16 | uint32_t tt_ctxdma_handle; | ||
| 17 | |||
| 18 | int channel; | ||
| 19 | uint32_t pushbuf_domains; | ||
| 20 | |||
| 21 | /* Notifier memory */ | ||
| 22 | uint32_t notifier_handle; | ||
| 23 | |||
| 24 | /* DRM-enforced subchannel assignments */ | ||
| 25 | struct { | ||
| 26 | uint32_t handle; | ||
| 27 | uint32_t grclass; | ||
| 28 | } subchan[8]; | ||
| 29 | uint32_t nr_subchan; | ||
| 30 | }; | ||
| 31 | |||
| 32 | struct drm_nouveau_channel_free { | ||
| 33 | int channel; | ||
| 34 | }; | ||
| 35 | |||
| 36 | struct drm_nouveau_grobj_alloc { | ||
| 37 | int channel; | ||
| 38 | uint32_t handle; | ||
| 39 | int class; | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct drm_nouveau_notifierobj_alloc { | ||
| 43 | uint32_t channel; | ||
| 44 | uint32_t handle; | ||
| 45 | uint32_t size; | ||
| 46 | uint32_t offset; | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct drm_nouveau_gpuobj_free { | ||
| 50 | int channel; | ||
| 51 | uint32_t handle; | ||
| 52 | }; | ||
| 53 | |||
| 54 | #define NOUVEAU_GETPARAM_PCI_VENDOR 3 | ||
| 55 | #define NOUVEAU_GETPARAM_PCI_DEVICE 4 | ||
| 56 | #define NOUVEAU_GETPARAM_BUS_TYPE 5 | ||
| 57 | #define NOUVEAU_GETPARAM_FB_SIZE 8 | ||
| 58 | #define NOUVEAU_GETPARAM_AGP_SIZE 9 | ||
| 59 | #define NOUVEAU_GETPARAM_CHIPSET_ID 11 | ||
| 60 | #define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 | ||
| 61 | #define NOUVEAU_GETPARAM_GRAPH_UNITS 13 | ||
| 62 | #define NOUVEAU_GETPARAM_PTIMER_TIME 14 | ||
| 63 | #define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 | ||
| 64 | #define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 | ||
| 65 | struct drm_nouveau_getparam { | ||
| 66 | uint64_t param; | ||
| 67 | uint64_t value; | ||
| 68 | }; | ||
| 69 | |||
| 70 | struct drm_nouveau_setparam { | ||
| 71 | uint64_t param; | ||
| 72 | uint64_t value; | ||
| 73 | }; | ||
| 74 | |||
| 75 | #define DRM_IOCTL_NOUVEAU_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GETPARAM, struct drm_nouveau_getparam) | ||
| 76 | #define DRM_IOCTL_NOUVEAU_SETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_SETPARAM, struct drm_nouveau_setparam) | ||
| 77 | #define DRM_IOCTL_NOUVEAU_CHANNEL_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_CHANNEL_ALLOC, struct drm_nouveau_channel_alloc) | ||
| 78 | #define DRM_IOCTL_NOUVEAU_CHANNEL_FREE DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_CHANNEL_FREE, struct drm_nouveau_channel_free) | ||
| 79 | #define DRM_IOCTL_NOUVEAU_GROBJ_ALLOC DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GROBJ_ALLOC, struct drm_nouveau_grobj_alloc) | ||
| 80 | #define DRM_IOCTL_NOUVEAU_NOTIFIEROBJ_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, struct drm_nouveau_notifierobj_alloc) | ||
| 81 | #define DRM_IOCTL_NOUVEAU_GPUOBJ_FREE DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GPUOBJ_FREE, struct drm_nouveau_gpuobj_free) | ||
| 82 | |||
| 83 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 2f11e16a81a9..a0a3fe3c016b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
| @@ -6091,6 +6091,18 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) | |||
| 6091 | } | 6091 | } |
| 6092 | } | 6092 | } |
| 6093 | 6093 | ||
| 6094 | /* fdo#50830: connector indices for VGA and DVI-I are backwards */ | ||
| 6095 | if (nv_match_device(dev, 0x0421, 0x3842, 0xc793)) { | ||
| 6096 | if (idx == 0 && *conn == 0x02000300) | ||
| 6097 | *conn = 0x02011300; | ||
| 6098 | else | ||
| 6099 | if (idx == 1 && *conn == 0x04011310) | ||
| 6100 | *conn = 0x04000310; | ||
| 6101 | else | ||
| 6102 | if (idx == 2 && *conn == 0x02011312) | ||
| 6103 | *conn = 0x02000312; | ||
| 6104 | } | ||
| 6105 | |||
| 6094 | return true; | 6106 | return true; |
| 6095 | } | 6107 | } |
| 6096 | 6108 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 629d8a2df5bd..debd90225a88 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c | |||
| @@ -395,98 +395,3 @@ nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv) | |||
| 395 | nouveau_channel_put(&chan); | 395 | nouveau_channel_put(&chan); |
| 396 | } | 396 | } |
| 397 | } | 397 | } |
| 398 | |||
| 399 | |||
| 400 | /*********************************** | ||
| 401 | * ioctls wrapping the functions | ||
| 402 | ***********************************/ | ||
| 403 | |||
| 404 | static int | ||
| 405 | nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, | ||
| 406 | struct drm_file *file_priv) | ||
| 407 | { | ||
| 408 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 409 | struct drm_nouveau_channel_alloc *init = data; | ||
| 410 | struct nouveau_channel *chan; | ||
| 411 | int ret; | ||
| 412 | |||
| 413 | if (!dev_priv->eng[NVOBJ_ENGINE_GR]) | ||
| 414 | return -ENODEV; | ||
| 415 | |||
| 416 | if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) | ||
| 417 | return -EINVAL; | ||
| 418 | |||
| 419 | ret = nouveau_channel_alloc(dev, &chan, file_priv, | ||
| 420 | init->fb_ctxdma_handle, | ||
| 421 | init->tt_ctxdma_handle); | ||
| 422 | if (ret) | ||
| 423 | return ret; | ||
| 424 | init->channel = chan->id; | ||
| 425 | |||
| 426 | if (nouveau_vram_pushbuf == 0) { | ||
| 427 | if (chan->dma.ib_max) | ||
| 428 | init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | | ||
| 429 | NOUVEAU_GEM_DOMAIN_GART; | ||
| 430 | else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM) | ||
| 431 | init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; | ||
| 432 | else | ||
| 433 | init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; | ||
| 434 | } else { | ||
| 435 | init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; | ||
| 436 | } | ||
| 437 | |||
| 438 | if (dev_priv->card_type < NV_C0) { | ||
| 439 | init->subchan[0].handle = 0x00000000; | ||
| 440 | init->subchan[0].grclass = 0x0000; | ||
| 441 | init->subchan[1].handle = NvSw; | ||
| 442 | init->subchan[1].grclass = NV_SW; | ||
| 443 | init->nr_subchan = 2; | ||
| 444 | } | ||
| 445 | |||
| 446 | /* Named memory object area */ | ||
| 447 | ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, | ||
| 448 | &init->notifier_handle); | ||
| 449 | |||
| 450 | if (ret == 0) | ||
| 451 | atomic_inc(&chan->users); /* userspace reference */ | ||
| 452 | nouveau_channel_put(&chan); | ||
| 453 | return ret; | ||
| 454 | } | ||
| 455 | |||
| 456 | static int | ||
| 457 | nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, | ||
| 458 | struct drm_file *file_priv) | ||
| 459 | { | ||
| 460 | struct drm_nouveau_channel_free *req = data; | ||
| 461 | struct nouveau_channel *chan; | ||
| 462 | |||
| 463 | chan = nouveau_channel_get(file_priv, req->channel); | ||
| 464 | if (IS_ERR(chan)) | ||
| 465 | return PTR_ERR(chan); | ||
| 466 | |||
| 467 | list_del(&chan->list); | ||
| 468 | atomic_dec(&chan->users); | ||
| 469 | nouveau_channel_put(&chan); | ||
| 470 | return 0; | ||
| 471 | } | ||
| 472 | |||
| 473 | /*********************************** | ||
| 474 | * finally, the ioctl table | ||
| 475 | ***********************************/ | ||
| 476 | |||
| 477 | struct drm_ioctl_desc nouveau_ioctls[] = { | ||
| 478 | DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH), | ||
| 479 | DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
| 480 | DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_UNLOCKED|DRM_AUTH), | ||
| 481 | DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_UNLOCKED|DRM_AUTH), | ||
| 482 | DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH), | ||
| 483 | DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_UNLOCKED|DRM_AUTH), | ||
| 484 | DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH), | ||
| 485 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH), | ||
| 486 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH), | ||
| 487 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH), | ||
| 488 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH), | ||
| 489 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH), | ||
| 490 | }; | ||
| 491 | |||
| 492 | int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index cad254c8e387..9a36f5f39b06 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include "drm.h" | 29 | #include "drm.h" |
| 30 | #include "drm_crtc_helper.h" | 30 | #include "drm_crtc_helper.h" |
| 31 | #include "nouveau_drv.h" | 31 | #include "nouveau_drv.h" |
| 32 | #include "nouveau_abi16.h" | ||
| 32 | #include "nouveau_hw.h" | 33 | #include "nouveau_hw.h" |
| 33 | #include "nouveau_fb.h" | 34 | #include "nouveau_fb.h" |
| 34 | #include "nouveau_fbcon.h" | 35 | #include "nouveau_fbcon.h" |
| @@ -384,6 +385,21 @@ nouveau_pci_resume(struct pci_dev *pdev) | |||
| 384 | return 0; | 385 | return 0; |
| 385 | } | 386 | } |
| 386 | 387 | ||
| 388 | static struct drm_ioctl_desc nouveau_ioctls[] = { | ||
| 389 | DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH), | ||
| 390 | DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
| 391 | DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_UNLOCKED|DRM_AUTH), | ||
| 392 | DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_UNLOCKED|DRM_AUTH), | ||
| 393 | DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH), | ||
| 394 | DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_UNLOCKED|DRM_AUTH), | ||
| 395 | DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH), | ||
| 396 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH), | ||
| 397 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH), | ||
| 398 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH), | ||
| 399 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH), | ||
| 400 | DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH), | ||
| 401 | }; | ||
| 402 | |||
| 387 | static const struct file_operations nouveau_driver_fops = { | 403 | static const struct file_operations nouveau_driver_fops = { |
| 388 | .owner = THIS_MODULE, | 404 | .owner = THIS_MODULE, |
| 389 | .open = drm_open, | 405 | .open = drm_open, |
| @@ -422,7 +438,6 @@ static struct drm_driver driver = { | |||
| 422 | .get_vblank_counter = drm_vblank_count, | 438 | .get_vblank_counter = drm_vblank_count, |
| 423 | .enable_vblank = nouveau_vblank_enable, | 439 | .enable_vblank = nouveau_vblank_enable, |
| 424 | .disable_vblank = nouveau_vblank_disable, | 440 | .disable_vblank = nouveau_vblank_disable, |
| 425 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 426 | .ioctls = nouveau_ioctls, | 441 | .ioctls = nouveau_ioctls, |
| 427 | .fops = &nouveau_driver_fops, | 442 | .fops = &nouveau_driver_fops, |
| 428 | 443 | ||
| @@ -463,7 +478,7 @@ static struct pci_driver nouveau_pci_driver = { | |||
| 463 | 478 | ||
| 464 | static int __init nouveau_init(void) | 479 | static int __init nouveau_init(void) |
| 465 | { | 480 | { |
| 466 | driver.num_ioctls = nouveau_max_ioctl; | 481 | driver.num_ioctls = ARRAY_SIZE(nouveau_ioctls); |
| 467 | 482 | ||
| 468 | if (nouveau_modeset == -1) { | 483 | if (nouveau_modeset == -1) { |
| 469 | #ifdef CONFIG_VGA_CONSOLE | 484 | #ifdef CONFIG_VGA_CONSOLE |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 8613cb23808c..4f2cc95ce264 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
| @@ -689,8 +689,6 @@ struct drm_nouveau_private { | |||
| 689 | void (*irq_handler[32])(struct drm_device *); | 689 | void (*irq_handler[32])(struct drm_device *); |
| 690 | bool msi_enabled; | 690 | bool msi_enabled; |
| 691 | 691 | ||
| 692 | struct list_head vbl_waiting; | ||
| 693 | |||
| 694 | struct { | 692 | struct { |
| 695 | struct drm_global_reference mem_global_ref; | 693 | struct drm_global_reference mem_global_ref; |
| 696 | struct ttm_bo_global_ref bo_global_ref; | 694 | struct ttm_bo_global_ref bo_global_ref; |
| @@ -872,10 +870,6 @@ extern int nouveau_load(struct drm_device *, unsigned long flags); | |||
| 872 | extern int nouveau_firstopen(struct drm_device *); | 870 | extern int nouveau_firstopen(struct drm_device *); |
| 873 | extern void nouveau_lastclose(struct drm_device *); | 871 | extern void nouveau_lastclose(struct drm_device *); |
| 874 | extern int nouveau_unload(struct drm_device *); | 872 | extern int nouveau_unload(struct drm_device *); |
| 875 | extern int nouveau_ioctl_getparam(struct drm_device *, void *data, | ||
| 876 | struct drm_file *); | ||
| 877 | extern int nouveau_ioctl_setparam(struct drm_device *, void *data, | ||
| 878 | struct drm_file *); | ||
| 879 | extern bool nouveau_wait_eq(struct drm_device *, uint64_t timeout, | 873 | extern bool nouveau_wait_eq(struct drm_device *, uint64_t timeout, |
| 880 | uint32_t reg, uint32_t mask, uint32_t val); | 874 | uint32_t reg, uint32_t mask, uint32_t val); |
| 881 | extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout, | 875 | extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout, |
| @@ -914,15 +908,8 @@ extern void nouveau_notifier_takedown_channel(struct nouveau_channel *); | |||
| 914 | extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, | 908 | extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, |
| 915 | int cout, uint32_t start, uint32_t end, | 909 | int cout, uint32_t start, uint32_t end, |
| 916 | uint32_t *offset); | 910 | uint32_t *offset); |
| 917 | extern int nouveau_notifier_offset(struct nouveau_gpuobj *, uint32_t *); | ||
| 918 | extern int nouveau_ioctl_notifier_alloc(struct drm_device *, void *data, | ||
| 919 | struct drm_file *); | ||
| 920 | extern int nouveau_ioctl_notifier_free(struct drm_device *, void *data, | ||
| 921 | struct drm_file *); | ||
| 922 | 911 | ||
| 923 | /* nouveau_channel.c */ | 912 | /* nouveau_channel.c */ |
| 924 | extern struct drm_ioctl_desc nouveau_ioctls[]; | ||
| 925 | extern int nouveau_max_ioctl; | ||
| 926 | extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); | 913 | extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); |
| 927 | extern int nouveau_channel_alloc(struct drm_device *dev, | 914 | extern int nouveau_channel_alloc(struct drm_device *dev, |
| 928 | struct nouveau_channel **chan, | 915 | struct nouveau_channel **chan, |
| @@ -938,7 +925,7 @@ extern void nouveau_channel_ref(struct nouveau_channel *chan, | |||
| 938 | struct nouveau_channel **pchan); | 925 | struct nouveau_channel **pchan); |
| 939 | extern int nouveau_channel_idle(struct nouveau_channel *chan); | 926 | extern int nouveau_channel_idle(struct nouveau_channel *chan); |
| 940 | 927 | ||
| 941 | /* nouveau_object.c */ | 928 | /* nouveau_gpuobj.c */ |
| 942 | #define NVOBJ_ENGINE_ADD(d, e, p) do { \ | 929 | #define NVOBJ_ENGINE_ADD(d, e, p) do { \ |
| 943 | struct drm_nouveau_private *dev_priv = (d)->dev_private; \ | 930 | struct drm_nouveau_private *dev_priv = (d)->dev_private; \ |
| 944 | dev_priv->eng[NVOBJ_ENGINE_##e] = (p); \ | 931 | dev_priv->eng[NVOBJ_ENGINE_##e] = (p); \ |
| @@ -993,10 +980,6 @@ extern int nv50_gpuobj_dma_new(struct nouveau_channel *, int class, u64 base, | |||
| 993 | extern void nv50_gpuobj_dma_init(struct nouveau_gpuobj *, u32 offset, | 980 | extern void nv50_gpuobj_dma_init(struct nouveau_gpuobj *, u32 offset, |
| 994 | int class, u64 base, u64 size, int target, | 981 | int class, u64 base, u64 size, int target, |
| 995 | int access, u32 type, u32 comp); | 982 | int access, u32 type, u32 comp); |
| 996 | extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, | ||
| 997 | struct drm_file *); | ||
| 998 | extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, | ||
| 999 | struct drm_file *); | ||
| 1000 | 983 | ||
| 1001 | /* nouveau_irq.c */ | 984 | /* nouveau_irq.c */ |
| 1002 | extern int nouveau_irq_init(struct drm_device *); | 985 | extern int nouveau_irq_init(struct drm_device *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 30f542316944..af7cfb825716 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
| @@ -207,8 +207,7 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, | |||
| 207 | struct nouveau_bo *nvbo = NULL; | 207 | struct nouveau_bo *nvbo = NULL; |
| 208 | int ret = 0; | 208 | int ret = 0; |
| 209 | 209 | ||
| 210 | if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) | 210 | dev_priv->ttm.bdev.dev_mapping = dev->dev_mapping; |
| 211 | dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; | ||
| 212 | 211 | ||
| 213 | if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { | 212 | if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { |
| 214 | NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); | 213 | NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); |
| @@ -342,6 +341,7 @@ retry: | |||
| 342 | if (nvbo->reserved_by && nvbo->reserved_by == file_priv) { | 341 | if (nvbo->reserved_by && nvbo->reserved_by == file_priv) { |
| 343 | NV_ERROR(dev, "multiple instances of buffer %d on " | 342 | NV_ERROR(dev, "multiple instances of buffer %d on " |
| 344 | "validation list\n", b->handle); | 343 | "validation list\n", b->handle); |
| 344 | drm_gem_object_unreference_unlocked(gem); | ||
| 345 | validate_fini(op, NULL); | 345 | validate_fini(op, NULL); |
| 346 | return -EINVAL; | 346 | return -EINVAL; |
| 347 | } | 347 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_gpuobj.c index b190cc01c820..bd79fedb7054 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_gpuobj.c | |||
| @@ -758,66 +758,6 @@ nouveau_gpuobj_resume(struct drm_device *dev) | |||
| 758 | dev_priv->engine.instmem.flush(dev); | 758 | dev_priv->engine.instmem.flush(dev); |
| 759 | } | 759 | } |
| 760 | 760 | ||
| 761 | int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, | ||
| 762 | struct drm_file *file_priv) | ||
| 763 | { | ||
| 764 | struct drm_nouveau_grobj_alloc *init = data; | ||
| 765 | struct nouveau_channel *chan; | ||
| 766 | int ret; | ||
| 767 | |||
| 768 | if (init->handle == ~0) | ||
| 769 | return -EINVAL; | ||
| 770 | |||
| 771 | /* compatibility with userspace that assumes 506e for all chipsets */ | ||
| 772 | if (init->class == 0x506e) { | ||
| 773 | init->class = nouveau_software_class(dev); | ||
| 774 | if (init->class == 0x906e) | ||
| 775 | return 0; | ||
| 776 | } else | ||
| 777 | if (init->class == 0x906e) { | ||
| 778 | NV_ERROR(dev, "906e not supported yet\n"); | ||
| 779 | return -EINVAL; | ||
| 780 | } | ||
| 781 | |||
| 782 | chan = nouveau_channel_get(file_priv, init->channel); | ||
| 783 | if (IS_ERR(chan)) | ||
| 784 | return PTR_ERR(chan); | ||
| 785 | |||
| 786 | if (nouveau_ramht_find(chan, init->handle)) { | ||
| 787 | ret = -EEXIST; | ||
| 788 | goto out; | ||
| 789 | } | ||
| 790 | |||
| 791 | ret = nouveau_gpuobj_gr_new(chan, init->handle, init->class); | ||
| 792 | if (ret) { | ||
| 793 | NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n", | ||
| 794 | ret, init->channel, init->handle); | ||
| 795 | } | ||
| 796 | |||
| 797 | out: | ||
| 798 | nouveau_channel_put(&chan); | ||
| 799 | return ret; | ||
| 800 | } | ||
| 801 | |||
| 802 | int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, | ||
| 803 | struct drm_file *file_priv) | ||
| 804 | { | ||
| 805 | struct drm_nouveau_gpuobj_free *objfree = data; | ||
| 806 | struct nouveau_channel *chan; | ||
| 807 | int ret; | ||
| 808 | |||
| 809 | chan = nouveau_channel_get(file_priv, objfree->channel); | ||
| 810 | if (IS_ERR(chan)) | ||
| 811 | return PTR_ERR(chan); | ||
| 812 | |||
| 813 | /* Synchronize with the user channel */ | ||
| 814 | nouveau_channel_idle(chan); | ||
| 815 | |||
| 816 | ret = nouveau_ramht_remove(chan, objfree->handle); | ||
| 817 | nouveau_channel_put(&chan); | ||
| 818 | return ret; | ||
| 819 | } | ||
| 820 | |||
| 821 | u32 | 761 | u32 |
| 822 | nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset) | 762 | nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset) |
| 823 | { | 763 | { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 868c7fd74854..b2c2937531a8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c | |||
| @@ -41,12 +41,8 @@ | |||
| 41 | void | 41 | void |
| 42 | nouveau_irq_preinstall(struct drm_device *dev) | 42 | nouveau_irq_preinstall(struct drm_device *dev) |
| 43 | { | 43 | { |
| 44 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 45 | |||
| 46 | /* Master disable */ | 44 | /* Master disable */ |
| 47 | nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); | 45 | nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); |
| 48 | |||
| 49 | INIT_LIST_HEAD(&dev_priv->vbl_waiting); | ||
| 50 | } | 46 | } |
| 51 | 47 | ||
| 52 | int | 48 | int |
diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c index 2ef883c4bbc1..69c93b864519 100644 --- a/drivers/gpu/drm/nouveau/nouveau_notifier.c +++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c | |||
| @@ -161,44 +161,3 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, | |||
| 161 | *b_offset = mem->start; | 161 | *b_offset = mem->start; |
| 162 | return 0; | 162 | return 0; |
| 163 | } | 163 | } |
| 164 | |||
| 165 | int | ||
| 166 | nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset) | ||
| 167 | { | ||
| 168 | if (!nobj || nobj->dtor != nouveau_notifier_gpuobj_dtor) | ||
| 169 | return -EINVAL; | ||
| 170 | |||
| 171 | if (poffset) { | ||
| 172 | struct drm_mm_node *mem = nobj->priv; | ||
| 173 | |||
| 174 | if (*poffset >= mem->size) | ||
| 175 | return false; | ||
| 176 | |||
| 177 | *poffset += mem->start; | ||
| 178 | } | ||
| 179 | |||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | int | ||
| 184 | nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, | ||
| 185 | struct drm_file *file_priv) | ||
| 186 | { | ||
| 187 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 188 | struct drm_nouveau_notifierobj_alloc *na = data; | ||
| 189 | struct nouveau_channel *chan; | ||
| 190 | int ret; | ||
| 191 | |||
| 192 | /* completely unnecessary for these chipsets... */ | ||
| 193 | if (unlikely(dev_priv->card_type >= NV_C0)) | ||
| 194 | return -EINVAL; | ||
| 195 | |||
| 196 | chan = nouveau_channel_get(file_priv, na->channel); | ||
| 197 | if (IS_ERR(chan)) | ||
| 198 | return PTR_ERR(chan); | ||
| 199 | |||
| 200 | ret = nouveau_notifier_alloc(chan, na->handle, na->size, 0, 0x1000, | ||
| 201 | &na->offset); | ||
| 202 | nouveau_channel_put(&chan); | ||
| 203 | return ret; | ||
| 204 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_software.h b/drivers/gpu/drm/nouveau/nouveau_software.h index e60bc6ce9003..709e5ac680ec 100644 --- a/drivers/gpu/drm/nouveau/nouveau_software.h +++ b/drivers/gpu/drm/nouveau/nouveau_software.h | |||
| @@ -4,13 +4,15 @@ | |||
| 4 | struct nouveau_software_priv { | 4 | struct nouveau_software_priv { |
| 5 | struct nouveau_exec_engine base; | 5 | struct nouveau_exec_engine base; |
| 6 | struct list_head vblank; | 6 | struct list_head vblank; |
| 7 | spinlock_t peephole_lock; | ||
| 7 | }; | 8 | }; |
| 8 | 9 | ||
| 9 | struct nouveau_software_chan { | 10 | struct nouveau_software_chan { |
| 10 | struct list_head flip; | 11 | struct list_head flip; |
| 11 | struct { | 12 | struct { |
| 12 | struct list_head list; | 13 | struct list_head list; |
| 13 | struct nouveau_bo *bo; | 14 | u32 channel; |
| 15 | u32 ctxdma; | ||
| 14 | u32 offset; | 16 | u32 offset; |
| 15 | u32 value; | 17 | u32 value; |
| 16 | u32 head; | 18 | u32 head; |
| @@ -18,32 +20,17 @@ struct nouveau_software_chan { | |||
| 18 | }; | 20 | }; |
| 19 | 21 | ||
| 20 | static inline void | 22 | static inline void |
| 21 | nouveau_software_vblank(struct drm_device *dev, int crtc) | ||
| 22 | { | ||
| 23 | struct nouveau_software_priv *psw = nv_engine(dev, NVOBJ_ENGINE_SW); | ||
| 24 | struct nouveau_software_chan *pch, *tmp; | ||
| 25 | |||
| 26 | list_for_each_entry_safe(pch, tmp, &psw->vblank, vblank.list) { | ||
| 27 | if (pch->vblank.head != crtc) | ||
| 28 | continue; | ||
| 29 | |||
| 30 | nouveau_bo_wr32(pch->vblank.bo, pch->vblank.offset, | ||
| 31 | pch->vblank.value); | ||
| 32 | list_del(&pch->vblank.list); | ||
| 33 | drm_vblank_put(dev, crtc); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | static inline void | ||
| 38 | nouveau_software_context_new(struct nouveau_software_chan *pch) | 23 | nouveau_software_context_new(struct nouveau_software_chan *pch) |
| 39 | { | 24 | { |
| 40 | INIT_LIST_HEAD(&pch->flip); | 25 | INIT_LIST_HEAD(&pch->flip); |
| 26 | INIT_LIST_HEAD(&pch->vblank.list); | ||
| 41 | } | 27 | } |
| 42 | 28 | ||
| 43 | static inline void | 29 | static inline void |
| 44 | nouveau_software_create(struct nouveau_software_priv *psw) | 30 | nouveau_software_create(struct nouveau_software_priv *psw) |
| 45 | { | 31 | { |
| 46 | INIT_LIST_HEAD(&psw->vblank); | 32 | INIT_LIST_HEAD(&psw->vblank); |
| 33 | spin_lock_init(&psw->peephole_lock); | ||
| 47 | } | 34 | } |
| 48 | 35 | ||
| 49 | static inline u16 | 36 | static inline u16 |
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 19706f0532ea..1cdfd6e757ce 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
| @@ -1234,80 +1234,6 @@ int nouveau_unload(struct drm_device *dev) | |||
| 1234 | return 0; | 1234 | return 0; |
| 1235 | } | 1235 | } |
| 1236 | 1236 | ||
| 1237 | int nouveau_ioctl_getparam(struct drm_device *dev, void *data, | ||
| 1238 | struct drm_file *file_priv) | ||
| 1239 | { | ||
| 1240 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 1241 | struct drm_nouveau_getparam *getparam = data; | ||
| 1242 | |||
| 1243 | switch (getparam->param) { | ||
| 1244 | case NOUVEAU_GETPARAM_CHIPSET_ID: | ||
| 1245 | getparam->value = dev_priv->chipset; | ||
| 1246 | break; | ||
| 1247 | case NOUVEAU_GETPARAM_PCI_VENDOR: | ||
| 1248 | getparam->value = dev->pci_vendor; | ||
| 1249 | break; | ||
| 1250 | case NOUVEAU_GETPARAM_PCI_DEVICE: | ||
| 1251 | getparam->value = dev->pci_device; | ||
| 1252 | break; | ||
| 1253 | case NOUVEAU_GETPARAM_BUS_TYPE: | ||
| 1254 | if (drm_pci_device_is_agp(dev)) | ||
| 1255 | getparam->value = NV_AGP; | ||
| 1256 | else if (pci_is_pcie(dev->pdev)) | ||
| 1257 | getparam->value = NV_PCIE; | ||
| 1258 | else | ||
| 1259 | getparam->value = NV_PCI; | ||
| 1260 | break; | ||
| 1261 | case NOUVEAU_GETPARAM_FB_SIZE: | ||
| 1262 | getparam->value = dev_priv->fb_available_size; | ||
| 1263 | break; | ||
| 1264 | case NOUVEAU_GETPARAM_AGP_SIZE: | ||
| 1265 | getparam->value = dev_priv->gart_info.aper_size; | ||
| 1266 | break; | ||
| 1267 | case NOUVEAU_GETPARAM_VM_VRAM_BASE: | ||
| 1268 | getparam->value = 0; /* deprecated */ | ||
| 1269 | break; | ||
| 1270 | case NOUVEAU_GETPARAM_PTIMER_TIME: | ||
| 1271 | getparam->value = dev_priv->engine.timer.read(dev); | ||
| 1272 | break; | ||
| 1273 | case NOUVEAU_GETPARAM_HAS_BO_USAGE: | ||
| 1274 | getparam->value = 1; | ||
| 1275 | break; | ||
| 1276 | case NOUVEAU_GETPARAM_HAS_PAGEFLIP: | ||
| 1277 | getparam->value = 1; | ||
| 1278 | break; | ||
| 1279 | case NOUVEAU_GETPARAM_GRAPH_UNITS: | ||
| 1280 | /* NV40 and NV50 versions are quite different, but register | ||
| 1281 | * address is the same. User is supposed to know the card | ||
| 1282 | * family anyway... */ | ||
| 1283 | if (dev_priv->chipset >= 0x40) { | ||
| 1284 | getparam->value = nv_rd32(dev, NV40_PMC_GRAPH_UNITS); | ||
| 1285 | break; | ||
| 1286 | } | ||
| 1287 | /* FALLTHRU */ | ||
| 1288 | default: | ||
| 1289 | NV_DEBUG(dev, "unknown parameter %lld\n", getparam->param); | ||
| 1290 | return -EINVAL; | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | return 0; | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | int | ||
| 1297 | nouveau_ioctl_setparam(struct drm_device *dev, void *data, | ||
| 1298 | struct drm_file *file_priv) | ||
| 1299 | { | ||
| 1300 | struct drm_nouveau_setparam *setparam = data; | ||
| 1301 | |||
| 1302 | switch (setparam->param) { | ||
| 1303 | default: | ||
| 1304 | NV_DEBUG(dev, "unknown parameter %lld\n", setparam->param); | ||
| 1305 | return -EINVAL; | ||
| 1306 | } | ||
| 1307 | |||
| 1308 | return 0; | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | /* Wait until (value(reg) & mask) == val, up until timeout has hit */ | 1237 | /* Wait until (value(reg) & mask) == val, up until timeout has hit */ |
| 1312 | bool | 1238 | bool |
| 1313 | nouveau_wait_eq(struct drm_device *dev, uint64_t timeout, | 1239 | nouveau_wait_eq(struct drm_device *dev, uint64_t timeout, |
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index 4c31c63e5528..43accc11102f 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c | |||
| @@ -215,7 +215,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | static bool | 217 | static bool |
| 218 | nv_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, | 218 | nv_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, |
| 219 | struct drm_display_mode *adjusted_mode) | 219 | struct drm_display_mode *adjusted_mode) |
| 220 | { | 220 | { |
| 221 | return true; | 221 | return true; |
diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 8300266ffaea..38f19479417c 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c | |||
| @@ -332,7 +332,7 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, | 334 | static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, |
| 335 | struct drm_display_mode *mode, | 335 | const struct drm_display_mode *mode, |
| 336 | struct drm_display_mode *adjusted_mode) | 336 | struct drm_display_mode *adjusted_mode) |
| 337 | { | 337 | { |
| 338 | if (nv04_dac_in_use(encoder)) | 338 | if (nv04_dac_in_use(encoder)) |
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 2258746016f8..c2675623b7cd 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c | |||
| @@ -179,7 +179,7 @@ static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder) | |||
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, | 181 | static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, |
| 182 | struct drm_display_mode *mode, | 182 | const struct drm_display_mode *mode, |
| 183 | struct drm_display_mode *adjusted_mode) | 183 | struct drm_display_mode *adjusted_mode) |
| 184 | { | 184 | { |
| 185 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 185 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 696d7e7dc2a0..67be5db021f5 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c | |||
| @@ -338,7 +338,7 @@ static int nv17_tv_mode_valid(struct drm_encoder *encoder, | |||
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, | 340 | static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, |
| 341 | struct drm_display_mode *mode, | 341 | const struct drm_display_mode *mode, |
| 342 | struct drm_display_mode *adjusted_mode) | 342 | struct drm_display_mode *adjusted_mode) |
| 343 | { | 343 | { |
| 344 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | 344 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); |
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 97a477b3d52d..22cebd5dd694 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
| @@ -527,7 +527,7 @@ nv50_crtc_commit(struct drm_crtc *crtc) | |||
| 527 | } | 527 | } |
| 528 | 528 | ||
| 529 | static bool | 529 | static bool |
| 530 | nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, | 530 | nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, |
| 531 | struct drm_display_mode *adjusted_mode) | 531 | struct drm_display_mode *adjusted_mode) |
| 532 | { | 532 | { |
| 533 | return true; | 533 | return true; |
diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c index eb216a446b89..2c36a6b92c53 100644 --- a/drivers/gpu/drm/nouveau/nv50_dac.c +++ b/drivers/gpu/drm/nouveau/nv50_dac.c | |||
| @@ -175,7 +175,8 @@ nv50_dac_restore(struct drm_encoder *encoder) | |||
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static bool | 177 | static bool |
| 178 | nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 178 | nv50_dac_mode_fixup(struct drm_encoder *encoder, |
| 179 | const struct drm_display_mode *mode, | ||
| 179 | struct drm_display_mode *adjusted_mode) | 180 | struct drm_display_mode *adjusted_mode) |
| 180 | { | 181 | { |
| 181 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 182 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 5c41612723b4..b244d9968c5d 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
| @@ -646,7 +646,30 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, | |||
| 646 | static void | 646 | static void |
| 647 | nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) | 647 | nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) |
| 648 | { | 648 | { |
| 649 | nouveau_software_vblank(dev, crtc); | 649 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 650 | struct nouveau_software_priv *psw = nv_engine(dev, NVOBJ_ENGINE_SW); | ||
| 651 | struct nouveau_software_chan *pch, *tmp; | ||
| 652 | |||
| 653 | list_for_each_entry_safe(pch, tmp, &psw->vblank, vblank.list) { | ||
| 654 | if (pch->vblank.head != crtc) | ||
| 655 | continue; | ||
| 656 | |||
| 657 | spin_lock(&psw->peephole_lock); | ||
| 658 | nv_wr32(dev, 0x001704, pch->vblank.channel); | ||
| 659 | nv_wr32(dev, 0x001710, 0x80000000 | pch->vblank.ctxdma); | ||
| 660 | if (dev_priv->chipset == 0x50) { | ||
| 661 | nv_wr32(dev, 0x001570, pch->vblank.offset); | ||
| 662 | nv_wr32(dev, 0x001574, pch->vblank.value); | ||
| 663 | } else { | ||
| 664 | nv_wr32(dev, 0x060010, pch->vblank.offset); | ||
| 665 | nv_wr32(dev, 0x060014, pch->vblank.value); | ||
| 666 | } | ||
| 667 | spin_unlock(&psw->peephole_lock); | ||
| 668 | |||
| 669 | list_del(&pch->vblank.list); | ||
| 670 | drm_vblank_put(dev, crtc); | ||
| 671 | } | ||
| 672 | |||
| 650 | drm_handle_vblank(dev, crtc); | 673 | drm_handle_vblank(dev, crtc); |
| 651 | } | 674 | } |
| 652 | 675 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index d9cc2f2638d6..437608d1dfe7 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c | |||
| @@ -299,7 +299,7 @@ static struct nouveau_bitfield nv50_graph_trap_ccache[] = { | |||
| 299 | 299 | ||
| 300 | /* There must be a *lot* of these. Will take some time to gather them up. */ | 300 | /* There must be a *lot* of these. Will take some time to gather them up. */ |
| 301 | struct nouveau_enum nv50_data_error_names[] = { | 301 | struct nouveau_enum nv50_data_error_names[] = { |
| 302 | { 0x00000003, "INVALID_QUERY_OR_TEXTURE", NULL }, | 302 | { 0x00000003, "INVALID_OPERATION", NULL }, |
| 303 | { 0x00000004, "INVALID_VALUE", NULL }, | 303 | { 0x00000004, "INVALID_VALUE", NULL }, |
| 304 | { 0x00000005, "INVALID_ENUM", NULL }, | 304 | { 0x00000005, "INVALID_ENUM", NULL }, |
| 305 | { 0x00000008, "INVALID_OBJECT", NULL }, | 305 | { 0x00000008, "INVALID_OBJECT", NULL }, |
diff --git a/drivers/gpu/drm/nouveau/nv50_software.c b/drivers/gpu/drm/nouveau/nv50_software.c index 114d2517d4a8..df554d9dacb8 100644 --- a/drivers/gpu/drm/nouveau/nv50_software.c +++ b/drivers/gpu/drm/nouveau/nv50_software.c | |||
| @@ -36,9 +36,6 @@ struct nv50_software_priv { | |||
| 36 | 36 | ||
| 37 | struct nv50_software_chan { | 37 | struct nv50_software_chan { |
| 38 | struct nouveau_software_chan base; | 38 | struct nouveau_software_chan base; |
| 39 | struct { | ||
| 40 | struct nouveau_gpuobj *object; | ||
| 41 | } vblank; | ||
| 42 | }; | 39 | }; |
| 43 | 40 | ||
| 44 | static int | 41 | static int |
| @@ -51,11 +48,7 @@ mthd_dma_vblsem(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) | |||
| 51 | if (!gpuobj) | 48 | if (!gpuobj) |
| 52 | return -ENOENT; | 49 | return -ENOENT; |
| 53 | 50 | ||
| 54 | if (nouveau_notifier_offset(gpuobj, NULL)) | 51 | pch->base.vblank.ctxdma = gpuobj->cinst >> 4; |
| 55 | return -EINVAL; | ||
| 56 | |||
| 57 | pch->vblank.object = gpuobj; | ||
| 58 | pch->base.vblank.offset = ~0; | ||
| 59 | return 0; | 52 | return 0; |
| 60 | } | 53 | } |
| 61 | 54 | ||
| @@ -63,11 +56,7 @@ static int | |||
| 63 | mthd_vblsem_offset(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) | 56 | mthd_vblsem_offset(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) |
| 64 | { | 57 | { |
| 65 | struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; | 58 | struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; |
| 66 | 59 | pch->base.vblank.offset = data; | |
| 67 | if (nouveau_notifier_offset(pch->vblank.object, &data)) | ||
| 68 | return -ERANGE; | ||
| 69 | |||
| 70 | pch->base.vblank.offset = data >> 2; | ||
| 71 | return 0; | 60 | return 0; |
| 72 | } | 61 | } |
| 73 | 62 | ||
| @@ -86,7 +75,7 @@ mthd_vblsem_release(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) | |||
| 86 | struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; | 75 | struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW]; |
| 87 | struct drm_device *dev = chan->dev; | 76 | struct drm_device *dev = chan->dev; |
| 88 | 77 | ||
| 89 | if (!pch->vblank.object || pch->base.vblank.offset == ~0 || data > 1) | 78 | if (data > 1) |
| 90 | return -EINVAL; | 79 | return -EINVAL; |
| 91 | 80 | ||
| 92 | drm_vblank_get(dev, data); | 81 | drm_vblank_get(dev, data); |
| @@ -116,7 +105,7 @@ nv50_software_context_new(struct nouveau_channel *chan, int engine) | |||
| 116 | return -ENOMEM; | 105 | return -ENOMEM; |
| 117 | 106 | ||
| 118 | nouveau_software_context_new(&pch->base); | 107 | nouveau_software_context_new(&pch->base); |
| 119 | pch->base.vblank.bo = chan->notifier_bo; | 108 | pch->base.vblank.channel = chan->ramin->vinst >> 12; |
| 120 | chan->engctx[engine] = pch; | 109 | chan->engctx[engine] = pch; |
| 121 | 110 | ||
| 122 | /* dma objects for display sync channel semaphore blocks */ | 111 | /* dma objects for display sync channel semaphore blocks */ |
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index a9514eaa74c1..93240bde891b 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c | |||
| @@ -327,7 +327,8 @@ nv50_sor_restore(struct drm_encoder *encoder) | |||
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | static bool | 329 | static bool |
| 330 | nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 330 | nv50_sor_mode_fixup(struct drm_encoder *encoder, |
| 331 | const struct drm_display_mode *mode, | ||
| 331 | struct drm_display_mode *adjusted_mode) | 332 | struct drm_display_mode *adjusted_mode) |
| 332 | { | 333 | { |
| 333 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 334 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c index edece9c616eb..bbfcc73b6708 100644 --- a/drivers/gpu/drm/nouveau/nv84_crypt.c +++ b/drivers/gpu/drm/nouveau/nv84_crypt.c | |||
| @@ -117,18 +117,30 @@ nv84_crypt_tlb_flush(struct drm_device *dev, int engine) | |||
| 117 | nv50_vm_flush_engine(dev, 0x0a); | 117 | nv50_vm_flush_engine(dev, 0x0a); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | static struct nouveau_bitfield nv84_crypt_intr[] = { | ||
| 121 | { 0x00000001, "INVALID_STATE" }, | ||
| 122 | { 0x00000002, "ILLEGAL_MTHD" }, | ||
| 123 | { 0x00000004, "ILLEGAL_CLASS" }, | ||
| 124 | { 0x00000080, "QUERY" }, | ||
| 125 | { 0x00000100, "FAULT" }, | ||
| 126 | {} | ||
| 127 | }; | ||
| 128 | |||
| 120 | static void | 129 | static void |
| 121 | nv84_crypt_isr(struct drm_device *dev) | 130 | nv84_crypt_isr(struct drm_device *dev) |
| 122 | { | 131 | { |
| 123 | u32 stat = nv_rd32(dev, 0x102130); | 132 | u32 stat = nv_rd32(dev, 0x102130); |
| 124 | u32 mthd = nv_rd32(dev, 0x102190); | 133 | u32 mthd = nv_rd32(dev, 0x102190); |
| 125 | u32 data = nv_rd32(dev, 0x102194); | 134 | u32 data = nv_rd32(dev, 0x102194); |
| 126 | u32 inst = nv_rd32(dev, 0x102188) & 0x7fffffff; | 135 | u64 inst = (u64)(nv_rd32(dev, 0x102188) & 0x7fffffff) << 12; |
| 127 | int show = nouveau_ratelimit(); | 136 | int show = nouveau_ratelimit(); |
| 137 | int chid = nv50_graph_isr_chid(dev, inst); | ||
| 128 | 138 | ||
| 129 | if (show) { | 139 | if (show) { |
| 130 | NV_INFO(dev, "PCRYPT_INTR: 0x%08x 0x%08x 0x%08x 0x%08x\n", | 140 | NV_INFO(dev, "PCRYPT:"); |
| 131 | stat, mthd, data, inst); | 141 | nouveau_bitfield_print(nv84_crypt_intr, stat); |
| 142 | printk(KERN_CONT " ch %d (0x%010llx) mthd 0x%04x data 0x%08x\n", | ||
| 143 | chid, inst, mthd, data); | ||
| 132 | } | 144 | } |
| 133 | 145 | ||
| 134 | nv_wr32(dev, 0x102130, stat); | 146 | nv_wr32(dev, 0x102130, stat); |
diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc b/drivers/gpu/drm/nouveau/nva3_copy.fuc index abc36626fef0..219850d53286 100644 --- a/drivers/gpu/drm/nouveau/nva3_copy.fuc +++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc | |||
| @@ -119,9 +119,9 @@ dispatch_dma: | |||
| 119 | // mthd 0x030c-0x0340, various stuff | 119 | // mthd 0x030c-0x0340, various stuff |
| 120 | .b16 0xc3 14 | 120 | .b16 0xc3 14 |
| 121 | .b32 #ctx_src_address_high ~0x000000ff | 121 | .b32 #ctx_src_address_high ~0x000000ff |
| 122 | .b32 #ctx_src_address_low ~0xfffffff0 | 122 | .b32 #ctx_src_address_low ~0xffffffff |
| 123 | .b32 #ctx_dst_address_high ~0x000000ff | 123 | .b32 #ctx_dst_address_high ~0x000000ff |
| 124 | .b32 #ctx_dst_address_low ~0xfffffff0 | 124 | .b32 #ctx_dst_address_low ~0xffffffff |
| 125 | .b32 #ctx_src_pitch ~0x0007ffff | 125 | .b32 #ctx_src_pitch ~0x0007ffff |
| 126 | .b32 #ctx_dst_pitch ~0x0007ffff | 126 | .b32 #ctx_dst_pitch ~0x0007ffff |
| 127 | .b32 #ctx_xcnt ~0x0000ffff | 127 | .b32 #ctx_xcnt ~0x0000ffff |
diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc.h b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h index 1f33fbdc00be..37d6de3c9d61 100644 --- a/drivers/gpu/drm/nouveau/nva3_copy.fuc.h +++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h | |||
| @@ -1,37 +1,72 @@ | |||
| 1 | uint32_t nva3_pcopy_data[] = { | 1 | u32 nva3_pcopy_data[] = { |
| 2 | /* 0x0000: ctx_object */ | ||
| 2 | 0x00000000, | 3 | 0x00000000, |
| 4 | /* 0x0004: ctx_dma */ | ||
| 5 | /* 0x0004: ctx_dma_query */ | ||
| 3 | 0x00000000, | 6 | 0x00000000, |
| 7 | /* 0x0008: ctx_dma_src */ | ||
| 4 | 0x00000000, | 8 | 0x00000000, |
| 9 | /* 0x000c: ctx_dma_dst */ | ||
| 5 | 0x00000000, | 10 | 0x00000000, |
| 11 | /* 0x0010: ctx_query_address_high */ | ||
| 6 | 0x00000000, | 12 | 0x00000000, |
| 13 | /* 0x0014: ctx_query_address_low */ | ||
| 7 | 0x00000000, | 14 | 0x00000000, |
| 15 | /* 0x0018: ctx_query_counter */ | ||
| 8 | 0x00000000, | 16 | 0x00000000, |
| 17 | /* 0x001c: ctx_src_address_high */ | ||
| 9 | 0x00000000, | 18 | 0x00000000, |
| 19 | /* 0x0020: ctx_src_address_low */ | ||
| 10 | 0x00000000, | 20 | 0x00000000, |
| 21 | /* 0x0024: ctx_src_pitch */ | ||
| 11 | 0x00000000, | 22 | 0x00000000, |
| 23 | /* 0x0028: ctx_src_tile_mode */ | ||
| 12 | 0x00000000, | 24 | 0x00000000, |
| 25 | /* 0x002c: ctx_src_xsize */ | ||
| 13 | 0x00000000, | 26 | 0x00000000, |
| 27 | /* 0x0030: ctx_src_ysize */ | ||
| 14 | 0x00000000, | 28 | 0x00000000, |
| 29 | /* 0x0034: ctx_src_zsize */ | ||
| 15 | 0x00000000, | 30 | 0x00000000, |
| 31 | /* 0x0038: ctx_src_zoff */ | ||
| 16 | 0x00000000, | 32 | 0x00000000, |
| 33 | /* 0x003c: ctx_src_xoff */ | ||
| 17 | 0x00000000, | 34 | 0x00000000, |
| 35 | /* 0x0040: ctx_src_yoff */ | ||
| 18 | 0x00000000, | 36 | 0x00000000, |
| 37 | /* 0x0044: ctx_src_cpp */ | ||
| 19 | 0x00000000, | 38 | 0x00000000, |
| 39 | /* 0x0048: ctx_dst_address_high */ | ||
| 20 | 0x00000000, | 40 | 0x00000000, |
| 41 | /* 0x004c: ctx_dst_address_low */ | ||
| 21 | 0x00000000, | 42 | 0x00000000, |
| 43 | /* 0x0050: ctx_dst_pitch */ | ||
| 22 | 0x00000000, | 44 | 0x00000000, |
| 45 | /* 0x0054: ctx_dst_tile_mode */ | ||
| 23 | 0x00000000, | 46 | 0x00000000, |
| 47 | /* 0x0058: ctx_dst_xsize */ | ||
| 24 | 0x00000000, | 48 | 0x00000000, |
| 49 | /* 0x005c: ctx_dst_ysize */ | ||
| 25 | 0x00000000, | 50 | 0x00000000, |
| 51 | /* 0x0060: ctx_dst_zsize */ | ||
| 26 | 0x00000000, | 52 | 0x00000000, |
| 53 | /* 0x0064: ctx_dst_zoff */ | ||
| 27 | 0x00000000, | 54 | 0x00000000, |
| 55 | /* 0x0068: ctx_dst_xoff */ | ||
| 28 | 0x00000000, | 56 | 0x00000000, |
| 57 | /* 0x006c: ctx_dst_yoff */ | ||
| 29 | 0x00000000, | 58 | 0x00000000, |
| 59 | /* 0x0070: ctx_dst_cpp */ | ||
| 30 | 0x00000000, | 60 | 0x00000000, |
| 61 | /* 0x0074: ctx_format */ | ||
| 31 | 0x00000000, | 62 | 0x00000000, |
| 63 | /* 0x0078: ctx_swz_const0 */ | ||
| 32 | 0x00000000, | 64 | 0x00000000, |
| 65 | /* 0x007c: ctx_swz_const1 */ | ||
| 33 | 0x00000000, | 66 | 0x00000000, |
| 67 | /* 0x0080: ctx_xcnt */ | ||
| 34 | 0x00000000, | 68 | 0x00000000, |
| 69 | /* 0x0084: ctx_ycnt */ | ||
| 35 | 0x00000000, | 70 | 0x00000000, |
| 36 | 0x00000000, | 71 | 0x00000000, |
| 37 | 0x00000000, | 72 | 0x00000000, |
| @@ -63,6 +98,7 @@ uint32_t nva3_pcopy_data[] = { | |||
| 63 | 0x00000000, | 98 | 0x00000000, |
| 64 | 0x00000000, | 99 | 0x00000000, |
| 65 | 0x00000000, | 100 | 0x00000000, |
| 101 | /* 0x0100: dispatch_table */ | ||
| 66 | 0x00010000, | 102 | 0x00010000, |
| 67 | 0x00000000, | 103 | 0x00000000, |
| 68 | 0x00000000, | 104 | 0x00000000, |
| @@ -73,6 +109,7 @@ uint32_t nva3_pcopy_data[] = { | |||
| 73 | 0x00010162, | 109 | 0x00010162, |
| 74 | 0x00000000, | 110 | 0x00000000, |
| 75 | 0x00030060, | 111 | 0x00030060, |
| 112 | /* 0x0128: dispatch_dma */ | ||
| 76 | 0x00010170, | 113 | 0x00010170, |
| 77 | 0x00000000, | 114 | 0x00000000, |
| 78 | 0x00010170, | 115 | 0x00010170, |
| @@ -118,11 +155,11 @@ uint32_t nva3_pcopy_data[] = { | |||
| 118 | 0x0000001c, | 155 | 0x0000001c, |
| 119 | 0xffffff00, | 156 | 0xffffff00, |
| 120 | 0x00000020, | 157 | 0x00000020, |
| 121 | 0x0000000f, | 158 | 0x00000000, |
| 122 | 0x00000048, | 159 | 0x00000048, |
| 123 | 0xffffff00, | 160 | 0xffffff00, |
| 124 | 0x0000004c, | 161 | 0x0000004c, |
| 125 | 0x0000000f, | 162 | 0x00000000, |
| 126 | 0x00000024, | 163 | 0x00000024, |
| 127 | 0xfff80000, | 164 | 0xfff80000, |
| 128 | 0x00000050, | 165 | 0x00000050, |
| @@ -146,7 +183,8 @@ uint32_t nva3_pcopy_data[] = { | |||
| 146 | 0x00000800, | 183 | 0x00000800, |
| 147 | }; | 184 | }; |
| 148 | 185 | ||
| 149 | uint32_t nva3_pcopy_code[] = { | 186 | u32 nva3_pcopy_code[] = { |
| 187 | /* 0x0000: main */ | ||
| 150 | 0x04fe04bd, | 188 | 0x04fe04bd, |
| 151 | 0x3517f000, | 189 | 0x3517f000, |
| 152 | 0xf10010fe, | 190 | 0xf10010fe, |
| @@ -158,23 +196,31 @@ uint32_t nva3_pcopy_code[] = { | |||
| 158 | 0x17f11031, | 196 | 0x17f11031, |
| 159 | 0x27f01200, | 197 | 0x27f01200, |
| 160 | 0x0012d003, | 198 | 0x0012d003, |
| 199 | /* 0x002f: spin */ | ||
| 161 | 0xf40031f4, | 200 | 0xf40031f4, |
| 162 | 0x0ef40028, | 201 | 0x0ef40028, |
| 202 | /* 0x0035: ih */ | ||
| 163 | 0x8001cffd, | 203 | 0x8001cffd, |
| 164 | 0xf40812c4, | 204 | 0xf40812c4, |
| 165 | 0x21f4060b, | 205 | 0x21f4060b, |
| 206 | /* 0x0041: ih_no_chsw */ | ||
| 166 | 0x0412c472, | 207 | 0x0412c472, |
| 167 | 0xf4060bf4, | 208 | 0xf4060bf4, |
| 209 | /* 0x004a: ih_no_cmd */ | ||
| 168 | 0x11c4c321, | 210 | 0x11c4c321, |
| 169 | 0x4001d00c, | 211 | 0x4001d00c, |
| 212 | /* 0x0052: swctx */ | ||
| 170 | 0x47f101f8, | 213 | 0x47f101f8, |
| 171 | 0x4bfe7700, | 214 | 0x4bfe7700, |
| 172 | 0x0007fe00, | 215 | 0x0007fe00, |
| 173 | 0xf00204b9, | 216 | 0xf00204b9, |
| 174 | 0x01f40643, | 217 | 0x01f40643, |
| 175 | 0x0604fa09, | 218 | 0x0604fa09, |
| 219 | /* 0x006b: swctx_load */ | ||
| 176 | 0xfa060ef4, | 220 | 0xfa060ef4, |
| 221 | /* 0x006e: swctx_done */ | ||
| 177 | 0x03f80504, | 222 | 0x03f80504, |
| 223 | /* 0x0072: chsw */ | ||
| 178 | 0x27f100f8, | 224 | 0x27f100f8, |
| 179 | 0x23cf1400, | 225 | 0x23cf1400, |
| 180 | 0x1e3fc800, | 226 | 0x1e3fc800, |
| @@ -183,18 +229,22 @@ uint32_t nva3_pcopy_code[] = { | |||
| 183 | 0x1e3af052, | 229 | 0x1e3af052, |
| 184 | 0xf00023d0, | 230 | 0xf00023d0, |
| 185 | 0x24d00147, | 231 | 0x24d00147, |
| 232 | /* 0x0093: chsw_no_unload */ | ||
| 186 | 0xcf00f880, | 233 | 0xcf00f880, |
| 187 | 0x3dc84023, | 234 | 0x3dc84023, |
| 188 | 0x220bf41e, | 235 | 0x220bf41e, |
| 189 | 0xf40131f4, | 236 | 0xf40131f4, |
| 190 | 0x57f05221, | 237 | 0x57f05221, |
| 191 | 0x0367f004, | 238 | 0x0367f004, |
| 239 | /* 0x00a8: chsw_load_ctx_dma */ | ||
| 192 | 0xa07856bc, | 240 | 0xa07856bc, |
| 193 | 0xb6018068, | 241 | 0xb6018068, |
| 194 | 0x87d00884, | 242 | 0x87d00884, |
| 195 | 0x0162b600, | 243 | 0x0162b600, |
| 244 | /* 0x00bb: chsw_finish_load */ | ||
| 196 | 0xf0f018f4, | 245 | 0xf0f018f4, |
| 197 | 0x23d00237, | 246 | 0x23d00237, |
| 247 | /* 0x00c3: dispatch */ | ||
| 198 | 0xf100f880, | 248 | 0xf100f880, |
| 199 | 0xcf190037, | 249 | 0xcf190037, |
| 200 | 0x33cf4032, | 250 | 0x33cf4032, |
| @@ -202,6 +252,7 @@ uint32_t nva3_pcopy_code[] = { | |||
| 202 | 0x1024b607, | 252 | 0x1024b607, |
| 203 | 0x010057f1, | 253 | 0x010057f1, |
| 204 | 0x74bd64bd, | 254 | 0x74bd64bd, |
| 255 | /* 0x00dc: dispatch_loop */ | ||
| 205 | 0x58005658, | 256 | 0x58005658, |
| 206 | 0x50b60157, | 257 | 0x50b60157, |
| 207 | 0x0446b804, | 258 | 0x0446b804, |
| @@ -211,6 +262,7 @@ uint32_t nva3_pcopy_code[] = { | |||
| 211 | 0xb60276bb, | 262 | 0xb60276bb, |
| 212 | 0x57bb0374, | 263 | 0x57bb0374, |
| 213 | 0xdf0ef400, | 264 | 0xdf0ef400, |
| 265 | /* 0x0100: dispatch_valid_mthd */ | ||
| 214 | 0xb60246bb, | 266 | 0xb60246bb, |
| 215 | 0x45bb0344, | 267 | 0x45bb0344, |
| 216 | 0x01459800, | 268 | 0x01459800, |
| @@ -220,31 +272,41 @@ uint32_t nva3_pcopy_code[] = { | |||
| 220 | 0xb0014658, | 272 | 0xb0014658, |
| 221 | 0x1bf40064, | 273 | 0x1bf40064, |
| 222 | 0x00538009, | 274 | 0x00538009, |
| 275 | /* 0x0127: dispatch_cmd */ | ||
| 223 | 0xf4300ef4, | 276 | 0xf4300ef4, |
| 224 | 0x55f90132, | 277 | 0x55f90132, |
| 225 | 0xf40c01f4, | 278 | 0xf40c01f4, |
| 279 | /* 0x0132: dispatch_invalid_bitfield */ | ||
| 226 | 0x25f0250e, | 280 | 0x25f0250e, |
| 281 | /* 0x0135: dispatch_illegal_mthd */ | ||
| 227 | 0x0125f002, | 282 | 0x0125f002, |
| 283 | /* 0x0138: dispatch_error */ | ||
| 228 | 0x100047f1, | 284 | 0x100047f1, |
| 229 | 0xd00042d0, | 285 | 0xd00042d0, |
| 230 | 0x27f04043, | 286 | 0x27f04043, |
| 231 | 0x0002d040, | 287 | 0x0002d040, |
| 288 | /* 0x0148: hostirq_wait */ | ||
| 232 | 0xf08002cf, | 289 | 0xf08002cf, |
| 233 | 0x24b04024, | 290 | 0x24b04024, |
| 234 | 0xf71bf400, | 291 | 0xf71bf400, |
| 292 | /* 0x0154: dispatch_done */ | ||
| 235 | 0x1d0027f1, | 293 | 0x1d0027f1, |
| 236 | 0xd00137f0, | 294 | 0xd00137f0, |
| 237 | 0x00f80023, | 295 | 0x00f80023, |
| 296 | /* 0x0160: cmd_nop */ | ||
| 297 | /* 0x0162: cmd_pm_trigger */ | ||
| 238 | 0x27f100f8, | 298 | 0x27f100f8, |
| 239 | 0x34bd2200, | 299 | 0x34bd2200, |
| 240 | 0xd00233f0, | 300 | 0xd00233f0, |
| 241 | 0x00f80023, | 301 | 0x00f80023, |
| 302 | /* 0x0170: cmd_dma */ | ||
| 242 | 0x012842b7, | 303 | 0x012842b7, |
| 243 | 0xf00145b6, | 304 | 0xf00145b6, |
| 244 | 0x43801e39, | 305 | 0x43801e39, |
| 245 | 0x0040b701, | 306 | 0x0040b701, |
| 246 | 0x0644b606, | 307 | 0x0644b606, |
| 247 | 0xf80043d0, | 308 | 0xf80043d0, |
| 309 | /* 0x0189: cmd_exec_set_format */ | ||
| 248 | 0xf030f400, | 310 | 0xf030f400, |
| 249 | 0xb00001b0, | 311 | 0xb00001b0, |
| 250 | 0x01b00101, | 312 | 0x01b00101, |
| @@ -256,20 +318,26 @@ uint32_t nva3_pcopy_code[] = { | |||
| 256 | 0x70b63847, | 318 | 0x70b63847, |
| 257 | 0x0232f401, | 319 | 0x0232f401, |
| 258 | 0x94bd84bd, | 320 | 0x94bd84bd, |
| 321 | /* 0x01b4: ncomp_loop */ | ||
| 259 | 0xb60f4ac4, | 322 | 0xb60f4ac4, |
| 260 | 0xb4bd0445, | 323 | 0xb4bd0445, |
| 324 | /* 0x01bc: bpc_loop */ | ||
| 261 | 0xf404a430, | 325 | 0xf404a430, |
| 262 | 0xa5ff0f18, | 326 | 0xa5ff0f18, |
| 263 | 0x00cbbbc0, | 327 | 0x00cbbbc0, |
| 264 | 0xf40231f4, | 328 | 0xf40231f4, |
| 329 | /* 0x01ce: cmp_c0 */ | ||
| 265 | 0x1bf4220e, | 330 | 0x1bf4220e, |
| 266 | 0x10c7f00c, | 331 | 0x10c7f00c, |
| 267 | 0xf400cbbb, | 332 | 0xf400cbbb, |
| 333 | /* 0x01da: cmp_c1 */ | ||
| 268 | 0xa430160e, | 334 | 0xa430160e, |
| 269 | 0x0c18f406, | 335 | 0x0c18f406, |
| 270 | 0xbb14c7f0, | 336 | 0xbb14c7f0, |
| 271 | 0x0ef400cb, | 337 | 0x0ef400cb, |
| 338 | /* 0x01e9: cmp_zero */ | ||
| 272 | 0x80c7f107, | 339 | 0x80c7f107, |
| 340 | /* 0x01ed: bpc_next */ | ||
| 273 | 0x01c83800, | 341 | 0x01c83800, |
| 274 | 0xb60180b6, | 342 | 0xb60180b6, |
| 275 | 0xb5b801b0, | 343 | 0xb5b801b0, |
| @@ -280,6 +348,7 @@ uint32_t nva3_pcopy_code[] = { | |||
| 280 | 0x98110680, | 348 | 0x98110680, |
| 281 | 0x68fd2008, | 349 | 0x68fd2008, |
| 282 | 0x0502f400, | 350 | 0x0502f400, |
| 351 | /* 0x0216: dst_xcnt */ | ||
| 283 | 0x75fd64bd, | 352 | 0x75fd64bd, |
| 284 | 0x1c078000, | 353 | 0x1c078000, |
| 285 | 0xf10078fd, | 354 | 0xf10078fd, |
| @@ -304,6 +373,7 @@ uint32_t nva3_pcopy_code[] = { | |||
| 304 | 0x980056d0, | 373 | 0x980056d0, |
| 305 | 0x56d01f06, | 374 | 0x56d01f06, |
| 306 | 0x1030f440, | 375 | 0x1030f440, |
| 376 | /* 0x0276: cmd_exec_set_surface_tiled */ | ||
| 307 | 0x579800f8, | 377 | 0x579800f8, |
| 308 | 0x6879c70a, | 378 | 0x6879c70a, |
| 309 | 0xb66478c7, | 379 | 0xb66478c7, |
| @@ -311,9 +381,11 @@ uint32_t nva3_pcopy_code[] = { | |||
| 311 | 0x0e76b060, | 381 | 0x0e76b060, |
| 312 | 0xf0091bf4, | 382 | 0xf0091bf4, |
| 313 | 0x0ef40477, | 383 | 0x0ef40477, |
| 384 | /* 0x0291: xtile64 */ | ||
| 314 | 0x027cf00f, | 385 | 0x027cf00f, |
| 315 | 0xfd1170b6, | 386 | 0xfd1170b6, |
| 316 | 0x77f00947, | 387 | 0x77f00947, |
| 388 | /* 0x029d: xtileok */ | ||
| 317 | 0x0f5a9806, | 389 | 0x0f5a9806, |
| 318 | 0xfd115b98, | 390 | 0xfd115b98, |
| 319 | 0xb7f000ab, | 391 | 0xb7f000ab, |
| @@ -371,6 +443,7 @@ uint32_t nva3_pcopy_code[] = { | |||
| 371 | 0x67d00600, | 443 | 0x67d00600, |
| 372 | 0x0060b700, | 444 | 0x0060b700, |
| 373 | 0x0068d004, | 445 | 0x0068d004, |
| 446 | /* 0x0382: cmd_exec_set_surface_linear */ | ||
| 374 | 0x6cf000f8, | 447 | 0x6cf000f8, |
| 375 | 0x0260b702, | 448 | 0x0260b702, |
| 376 | 0x0864b602, | 449 | 0x0864b602, |
| @@ -381,13 +454,16 @@ uint32_t nva3_pcopy_code[] = { | |||
| 381 | 0xb70067d0, | 454 | 0xb70067d0, |
| 382 | 0x98040060, | 455 | 0x98040060, |
| 383 | 0x67d00957, | 456 | 0x67d00957, |
| 457 | /* 0x03ab: cmd_exec_wait */ | ||
| 384 | 0xf900f800, | 458 | 0xf900f800, |
| 385 | 0xf110f900, | 459 | 0xf110f900, |
| 386 | 0xb6080007, | 460 | 0xb6080007, |
| 461 | /* 0x03b6: loop */ | ||
| 387 | 0x01cf0604, | 462 | 0x01cf0604, |
| 388 | 0x0114f000, | 463 | 0x0114f000, |
| 389 | 0xfcfa1bf4, | 464 | 0xfcfa1bf4, |
| 390 | 0xf800fc10, | 465 | 0xf800fc10, |
| 466 | /* 0x03c5: cmd_exec_query */ | ||
| 391 | 0x0d34c800, | 467 | 0x0d34c800, |
| 392 | 0xf5701bf4, | 468 | 0xf5701bf4, |
| 393 | 0xf103ab21, | 469 | 0xf103ab21, |
| @@ -417,6 +493,7 @@ uint32_t nva3_pcopy_code[] = { | |||
| 417 | 0x47f10153, | 493 | 0x47f10153, |
| 418 | 0x44b60800, | 494 | 0x44b60800, |
| 419 | 0x0045d006, | 495 | 0x0045d006, |
| 496 | /* 0x0438: query_counter */ | ||
| 420 | 0x03ab21f5, | 497 | 0x03ab21f5, |
| 421 | 0x080c47f1, | 498 | 0x080c47f1, |
| 422 | 0x980644b6, | 499 | 0x980644b6, |
| @@ -439,11 +516,13 @@ uint32_t nva3_pcopy_code[] = { | |||
| 439 | 0x47f10153, | 516 | 0x47f10153, |
| 440 | 0x44b60800, | 517 | 0x44b60800, |
| 441 | 0x0045d006, | 518 | 0x0045d006, |
| 519 | /* 0x0492: cmd_exec */ | ||
| 442 | 0x21f500f8, | 520 | 0x21f500f8, |
| 443 | 0x3fc803ab, | 521 | 0x3fc803ab, |
| 444 | 0x0e0bf400, | 522 | 0x0e0bf400, |
| 445 | 0x018921f5, | 523 | 0x018921f5, |
| 446 | 0x020047f1, | 524 | 0x020047f1, |
| 525 | /* 0x04a7: cmd_exec_no_format */ | ||
| 447 | 0xf11e0ef4, | 526 | 0xf11e0ef4, |
| 448 | 0xb6081067, | 527 | 0xb6081067, |
| 449 | 0x77f00664, | 528 | 0x77f00664, |
| @@ -451,19 +530,24 @@ uint32_t nva3_pcopy_code[] = { | |||
| 451 | 0x981c0780, | 530 | 0x981c0780, |
| 452 | 0x67d02007, | 531 | 0x67d02007, |
| 453 | 0x4067d000, | 532 | 0x4067d000, |
| 533 | /* 0x04c2: cmd_exec_init_src_surface */ | ||
| 454 | 0x32f444bd, | 534 | 0x32f444bd, |
| 455 | 0xc854bd02, | 535 | 0xc854bd02, |
| 456 | 0x0bf4043f, | 536 | 0x0bf4043f, |
| 457 | 0x8221f50a, | 537 | 0x8221f50a, |
| 458 | 0x0a0ef403, | 538 | 0x0a0ef403, |
| 539 | /* 0x04d4: src_tiled */ | ||
| 459 | 0x027621f5, | 540 | 0x027621f5, |
| 541 | /* 0x04db: cmd_exec_init_dst_surface */ | ||
| 460 | 0xf40749f0, | 542 | 0xf40749f0, |
| 461 | 0x57f00231, | 543 | 0x57f00231, |
| 462 | 0x083fc82c, | 544 | 0x083fc82c, |
| 463 | 0xf50a0bf4, | 545 | 0xf50a0bf4, |
| 464 | 0xf4038221, | 546 | 0xf4038221, |
| 547 | /* 0x04ee: dst_tiled */ | ||
| 465 | 0x21f50a0e, | 548 | 0x21f50a0e, |
| 466 | 0x49f00276, | 549 | 0x49f00276, |
| 550 | /* 0x04f5: cmd_exec_kick */ | ||
| 467 | 0x0057f108, | 551 | 0x0057f108, |
| 468 | 0x0654b608, | 552 | 0x0654b608, |
| 469 | 0xd0210698, | 553 | 0xd0210698, |
| @@ -473,6 +557,8 @@ uint32_t nva3_pcopy_code[] = { | |||
| 473 | 0xc80054d0, | 557 | 0xc80054d0, |
| 474 | 0x0bf40c3f, | 558 | 0x0bf40c3f, |
| 475 | 0xc521f507, | 559 | 0xc521f507, |
| 560 | /* 0x0519: cmd_exec_done */ | ||
| 561 | /* 0x051b: cmd_wrcache_flush */ | ||
| 476 | 0xf100f803, | 562 | 0xf100f803, |
| 477 | 0xbd220027, | 563 | 0xbd220027, |
| 478 | 0x0133f034, | 564 | 0x0133f034, |
diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h index a8d17458ced1..cd879f31bb38 100644 --- a/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h +++ b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h | |||
| @@ -1,34 +1,65 @@ | |||
| 1 | uint32_t nvc0_pcopy_data[] = { | 1 | u32 nvc0_pcopy_data[] = { |
| 2 | /* 0x0000: ctx_object */ | ||
| 2 | 0x00000000, | 3 | 0x00000000, |
| 4 | /* 0x0004: ctx_query_address_high */ | ||
| 3 | 0x00000000, | 5 | 0x00000000, |
| 6 | /* 0x0008: ctx_query_address_low */ | ||
| 4 | 0x00000000, | 7 | 0x00000000, |
| 8 | /* 0x000c: ctx_query_counter */ | ||
| 5 | 0x00000000, | 9 | 0x00000000, |
| 10 | /* 0x0010: ctx_src_address_high */ | ||
| 6 | 0x00000000, | 11 | 0x00000000, |
| 12 | /* 0x0014: ctx_src_address_low */ | ||
| 7 | 0x00000000, | 13 | 0x00000000, |
| 14 | /* 0x0018: ctx_src_pitch */ | ||
| 8 | 0x00000000, | 15 | 0x00000000, |
| 16 | /* 0x001c: ctx_src_tile_mode */ | ||
| 9 | 0x00000000, | 17 | 0x00000000, |
| 18 | /* 0x0020: ctx_src_xsize */ | ||
| 10 | 0x00000000, | 19 | 0x00000000, |
| 20 | /* 0x0024: ctx_src_ysize */ | ||
| 11 | 0x00000000, | 21 | 0x00000000, |
| 22 | /* 0x0028: ctx_src_zsize */ | ||
| 12 | 0x00000000, | 23 | 0x00000000, |
| 24 | /* 0x002c: ctx_src_zoff */ | ||
| 13 | 0x00000000, | 25 | 0x00000000, |
| 26 | /* 0x0030: ctx_src_xoff */ | ||
| 14 | 0x00000000, | 27 | 0x00000000, |
| 28 | /* 0x0034: ctx_src_yoff */ | ||
| 15 | 0x00000000, | 29 | 0x00000000, |
| 30 | /* 0x0038: ctx_src_cpp */ | ||
| 16 | 0x00000000, | 31 | 0x00000000, |
| 32 | /* 0x003c: ctx_dst_address_high */ | ||
| 17 | 0x00000000, | 33 | 0x00000000, |
| 34 | /* 0x0040: ctx_dst_address_low */ | ||
| 18 | 0x00000000, | 35 | 0x00000000, |
| 36 | /* 0x0044: ctx_dst_pitch */ | ||
| 19 | 0x00000000, | 37 | 0x00000000, |
| 38 | /* 0x0048: ctx_dst_tile_mode */ | ||
| 20 | 0x00000000, | 39 | 0x00000000, |
| 40 | /* 0x004c: ctx_dst_xsize */ | ||
| 21 | 0x00000000, | 41 | 0x00000000, |
| 42 | /* 0x0050: ctx_dst_ysize */ | ||
| 22 | 0x00000000, | 43 | 0x00000000, |
| 44 | /* 0x0054: ctx_dst_zsize */ | ||
| 23 | 0x00000000, | 45 | 0x00000000, |
| 46 | /* 0x0058: ctx_dst_zoff */ | ||
| 24 | 0x00000000, | 47 | 0x00000000, |
| 48 | /* 0x005c: ctx_dst_xoff */ | ||
| 25 | 0x00000000, | 49 | 0x00000000, |
| 50 | /* 0x0060: ctx_dst_yoff */ | ||
| 26 | 0x00000000, | 51 | 0x00000000, |
| 52 | /* 0x0064: ctx_dst_cpp */ | ||
| 27 | 0x00000000, | 53 | 0x00000000, |
| 54 | /* 0x0068: ctx_format */ | ||
| 28 | 0x00000000, | 55 | 0x00000000, |
| 56 | /* 0x006c: ctx_swz_const0 */ | ||
| 29 | 0x00000000, | 57 | 0x00000000, |
| 58 | /* 0x0070: ctx_swz_const1 */ | ||
| 30 | 0x00000000, | 59 | 0x00000000, |
| 60 | /* 0x0074: ctx_xcnt */ | ||
| 31 | 0x00000000, | 61 | 0x00000000, |
| 62 | /* 0x0078: ctx_ycnt */ | ||
| 32 | 0x00000000, | 63 | 0x00000000, |
| 33 | 0x00000000, | 64 | 0x00000000, |
| 34 | 0x00000000, | 65 | 0x00000000, |
| @@ -63,6 +94,7 @@ uint32_t nvc0_pcopy_data[] = { | |||
| 63 | 0x00000000, | 94 | 0x00000000, |
| 64 | 0x00000000, | 95 | 0x00000000, |
| 65 | 0x00000000, | 96 | 0x00000000, |
| 97 | /* 0x0100: dispatch_table */ | ||
| 66 | 0x00010000, | 98 | 0x00010000, |
| 67 | 0x00000000, | 99 | 0x00000000, |
| 68 | 0x00000000, | 100 | 0x00000000, |
| @@ -111,11 +143,11 @@ uint32_t nvc0_pcopy_data[] = { | |||
| 111 | 0x00000010, | 143 | 0x00000010, |
| 112 | 0xffffff00, | 144 | 0xffffff00, |
| 113 | 0x00000014, | 145 | 0x00000014, |
| 114 | 0x0000000f, | 146 | 0x00000000, |
| 115 | 0x0000003c, | 147 | 0x0000003c, |
| 116 | 0xffffff00, | 148 | 0xffffff00, |
| 117 | 0x00000040, | 149 | 0x00000040, |
| 118 | 0x0000000f, | 150 | 0x00000000, |
| 119 | 0x00000018, | 151 | 0x00000018, |
| 120 | 0xfff80000, | 152 | 0xfff80000, |
| 121 | 0x00000044, | 153 | 0x00000044, |
| @@ -139,7 +171,8 @@ uint32_t nvc0_pcopy_data[] = { | |||
| 139 | 0x00000800, | 171 | 0x00000800, |
| 140 | }; | 172 | }; |
| 141 | 173 | ||
| 142 | uint32_t nvc0_pcopy_code[] = { | 174 | u32 nvc0_pcopy_code[] = { |
| 175 | /* 0x0000: main */ | ||
| 143 | 0x04fe04bd, | 176 | 0x04fe04bd, |
| 144 | 0x3517f000, | 177 | 0x3517f000, |
| 145 | 0xf10010fe, | 178 | 0xf10010fe, |
| @@ -151,15 +184,20 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 151 | 0x17f11031, | 184 | 0x17f11031, |
| 152 | 0x27f01200, | 185 | 0x27f01200, |
| 153 | 0x0012d003, | 186 | 0x0012d003, |
| 187 | /* 0x002f: spin */ | ||
| 154 | 0xf40031f4, | 188 | 0xf40031f4, |
| 155 | 0x0ef40028, | 189 | 0x0ef40028, |
| 190 | /* 0x0035: ih */ | ||
| 156 | 0x8001cffd, | 191 | 0x8001cffd, |
| 157 | 0xf40812c4, | 192 | 0xf40812c4, |
| 158 | 0x21f4060b, | 193 | 0x21f4060b, |
| 194 | /* 0x0041: ih_no_chsw */ | ||
| 159 | 0x0412c4ca, | 195 | 0x0412c4ca, |
| 160 | 0xf5070bf4, | 196 | 0xf5070bf4, |
| 197 | /* 0x004b: ih_no_cmd */ | ||
| 161 | 0xc4010221, | 198 | 0xc4010221, |
| 162 | 0x01d00c11, | 199 | 0x01d00c11, |
| 200 | /* 0x0053: swctx */ | ||
| 163 | 0xf101f840, | 201 | 0xf101f840, |
| 164 | 0xfe770047, | 202 | 0xfe770047, |
| 165 | 0x47f1004b, | 203 | 0x47f1004b, |
| @@ -188,8 +226,11 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 188 | 0xf00204b9, | 226 | 0xf00204b9, |
| 189 | 0x01f40643, | 227 | 0x01f40643, |
| 190 | 0x0604fa09, | 228 | 0x0604fa09, |
| 229 | /* 0x00c3: swctx_load */ | ||
| 191 | 0xfa060ef4, | 230 | 0xfa060ef4, |
| 231 | /* 0x00c6: swctx_done */ | ||
| 192 | 0x03f80504, | 232 | 0x03f80504, |
| 233 | /* 0x00ca: chsw */ | ||
| 193 | 0x27f100f8, | 234 | 0x27f100f8, |
| 194 | 0x23cf1400, | 235 | 0x23cf1400, |
| 195 | 0x1e3fc800, | 236 | 0x1e3fc800, |
| @@ -198,18 +239,22 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 198 | 0x1e3af053, | 239 | 0x1e3af053, |
| 199 | 0xf00023d0, | 240 | 0xf00023d0, |
| 200 | 0x24d00147, | 241 | 0x24d00147, |
| 242 | /* 0x00eb: chsw_no_unload */ | ||
| 201 | 0xcf00f880, | 243 | 0xcf00f880, |
| 202 | 0x3dc84023, | 244 | 0x3dc84023, |
| 203 | 0x090bf41e, | 245 | 0x090bf41e, |
| 204 | 0xf40131f4, | 246 | 0xf40131f4, |
| 247 | /* 0x00fa: chsw_finish_load */ | ||
| 205 | 0x37f05321, | 248 | 0x37f05321, |
| 206 | 0x8023d002, | 249 | 0x8023d002, |
| 250 | /* 0x0102: dispatch */ | ||
| 207 | 0x37f100f8, | 251 | 0x37f100f8, |
| 208 | 0x32cf1900, | 252 | 0x32cf1900, |
| 209 | 0x0033cf40, | 253 | 0x0033cf40, |
| 210 | 0x07ff24e4, | 254 | 0x07ff24e4, |
| 211 | 0xf11024b6, | 255 | 0xf11024b6, |
| 212 | 0xbd010057, | 256 | 0xbd010057, |
| 257 | /* 0x011b: dispatch_loop */ | ||
| 213 | 0x5874bd64, | 258 | 0x5874bd64, |
| 214 | 0x57580056, | 259 | 0x57580056, |
| 215 | 0x0450b601, | 260 | 0x0450b601, |
| @@ -219,6 +264,7 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 219 | 0xbb0f08f4, | 264 | 0xbb0f08f4, |
| 220 | 0x74b60276, | 265 | 0x74b60276, |
| 221 | 0x0057bb03, | 266 | 0x0057bb03, |
| 267 | /* 0x013f: dispatch_valid_mthd */ | ||
| 222 | 0xbbdf0ef4, | 268 | 0xbbdf0ef4, |
| 223 | 0x44b60246, | 269 | 0x44b60246, |
| 224 | 0x0045bb03, | 270 | 0x0045bb03, |
| @@ -229,24 +275,33 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 229 | 0x64b00146, | 275 | 0x64b00146, |
| 230 | 0x091bf400, | 276 | 0x091bf400, |
| 231 | 0xf4005380, | 277 | 0xf4005380, |
| 278 | /* 0x0166: dispatch_cmd */ | ||
| 232 | 0x32f4300e, | 279 | 0x32f4300e, |
| 233 | 0xf455f901, | 280 | 0xf455f901, |
| 234 | 0x0ef40c01, | 281 | 0x0ef40c01, |
| 282 | /* 0x0171: dispatch_invalid_bitfield */ | ||
| 235 | 0x0225f025, | 283 | 0x0225f025, |
| 284 | /* 0x0174: dispatch_illegal_mthd */ | ||
| 285 | /* 0x0177: dispatch_error */ | ||
| 236 | 0xf10125f0, | 286 | 0xf10125f0, |
| 237 | 0xd0100047, | 287 | 0xd0100047, |
| 238 | 0x43d00042, | 288 | 0x43d00042, |
| 239 | 0x4027f040, | 289 | 0x4027f040, |
| 290 | /* 0x0187: hostirq_wait */ | ||
| 240 | 0xcf0002d0, | 291 | 0xcf0002d0, |
| 241 | 0x24f08002, | 292 | 0x24f08002, |
| 242 | 0x0024b040, | 293 | 0x0024b040, |
| 294 | /* 0x0193: dispatch_done */ | ||
| 243 | 0xf1f71bf4, | 295 | 0xf1f71bf4, |
| 244 | 0xf01d0027, | 296 | 0xf01d0027, |
| 245 | 0x23d00137, | 297 | 0x23d00137, |
| 298 | /* 0x019f: cmd_nop */ | ||
| 246 | 0xf800f800, | 299 | 0xf800f800, |
| 300 | /* 0x01a1: cmd_pm_trigger */ | ||
| 247 | 0x0027f100, | 301 | 0x0027f100, |
| 248 | 0xf034bd22, | 302 | 0xf034bd22, |
| 249 | 0x23d00233, | 303 | 0x23d00233, |
| 304 | /* 0x01af: cmd_exec_set_format */ | ||
| 250 | 0xf400f800, | 305 | 0xf400f800, |
| 251 | 0x01b0f030, | 306 | 0x01b0f030, |
| 252 | 0x0101b000, | 307 | 0x0101b000, |
| @@ -258,20 +313,26 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 258 | 0x3847c701, | 313 | 0x3847c701, |
| 259 | 0xf40170b6, | 314 | 0xf40170b6, |
| 260 | 0x84bd0232, | 315 | 0x84bd0232, |
| 316 | /* 0x01da: ncomp_loop */ | ||
| 261 | 0x4ac494bd, | 317 | 0x4ac494bd, |
| 262 | 0x0445b60f, | 318 | 0x0445b60f, |
| 319 | /* 0x01e2: bpc_loop */ | ||
| 263 | 0xa430b4bd, | 320 | 0xa430b4bd, |
| 264 | 0x0f18f404, | 321 | 0x0f18f404, |
| 265 | 0xbbc0a5ff, | 322 | 0xbbc0a5ff, |
| 266 | 0x31f400cb, | 323 | 0x31f400cb, |
| 267 | 0x220ef402, | 324 | 0x220ef402, |
| 325 | /* 0x01f4: cmp_c0 */ | ||
| 268 | 0xf00c1bf4, | 326 | 0xf00c1bf4, |
| 269 | 0xcbbb10c7, | 327 | 0xcbbb10c7, |
| 270 | 0x160ef400, | 328 | 0x160ef400, |
| 329 | /* 0x0200: cmp_c1 */ | ||
| 271 | 0xf406a430, | 330 | 0xf406a430, |
| 272 | 0xc7f00c18, | 331 | 0xc7f00c18, |
| 273 | 0x00cbbb14, | 332 | 0x00cbbb14, |
| 333 | /* 0x020f: cmp_zero */ | ||
| 274 | 0xf1070ef4, | 334 | 0xf1070ef4, |
| 335 | /* 0x0213: bpc_next */ | ||
| 275 | 0x380080c7, | 336 | 0x380080c7, |
| 276 | 0x80b601c8, | 337 | 0x80b601c8, |
| 277 | 0x01b0b601, | 338 | 0x01b0b601, |
| @@ -283,6 +344,7 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 283 | 0x1d08980e, | 344 | 0x1d08980e, |
| 284 | 0xf40068fd, | 345 | 0xf40068fd, |
| 285 | 0x64bd0502, | 346 | 0x64bd0502, |
| 347 | /* 0x023c: dst_xcnt */ | ||
| 286 | 0x800075fd, | 348 | 0x800075fd, |
| 287 | 0x78fd1907, | 349 | 0x78fd1907, |
| 288 | 0x1057f100, | 350 | 0x1057f100, |
| @@ -307,15 +369,18 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 307 | 0x1c069800, | 369 | 0x1c069800, |
| 308 | 0xf44056d0, | 370 | 0xf44056d0, |
| 309 | 0x00f81030, | 371 | 0x00f81030, |
| 372 | /* 0x029c: cmd_exec_set_surface_tiled */ | ||
| 310 | 0xc7075798, | 373 | 0xc7075798, |
| 311 | 0x78c76879, | 374 | 0x78c76879, |
| 312 | 0x0380b664, | 375 | 0x0380b664, |
| 313 | 0xb06077c7, | 376 | 0xb06077c7, |
| 314 | 0x1bf40e76, | 377 | 0x1bf40e76, |
| 315 | 0x0477f009, | 378 | 0x0477f009, |
| 379 | /* 0x02b7: xtile64 */ | ||
| 316 | 0xf00f0ef4, | 380 | 0xf00f0ef4, |
| 317 | 0x70b6027c, | 381 | 0x70b6027c, |
| 318 | 0x0947fd11, | 382 | 0x0947fd11, |
| 383 | /* 0x02c3: xtileok */ | ||
| 319 | 0x980677f0, | 384 | 0x980677f0, |
| 320 | 0x5b980c5a, | 385 | 0x5b980c5a, |
| 321 | 0x00abfd0e, | 386 | 0x00abfd0e, |
| @@ -374,6 +439,7 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 374 | 0xb70067d0, | 439 | 0xb70067d0, |
| 375 | 0xd0040060, | 440 | 0xd0040060, |
| 376 | 0x00f80068, | 441 | 0x00f80068, |
| 442 | /* 0x03a8: cmd_exec_set_surface_linear */ | ||
| 377 | 0xb7026cf0, | 443 | 0xb7026cf0, |
| 378 | 0xb6020260, | 444 | 0xb6020260, |
| 379 | 0x57980864, | 445 | 0x57980864, |
| @@ -384,12 +450,15 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 384 | 0x0060b700, | 450 | 0x0060b700, |
| 385 | 0x06579804, | 451 | 0x06579804, |
| 386 | 0xf80067d0, | 452 | 0xf80067d0, |
| 453 | /* 0x03d1: cmd_exec_wait */ | ||
| 387 | 0xf900f900, | 454 | 0xf900f900, |
| 388 | 0x0007f110, | 455 | 0x0007f110, |
| 389 | 0x0604b608, | 456 | 0x0604b608, |
| 457 | /* 0x03dc: loop */ | ||
| 390 | 0xf00001cf, | 458 | 0xf00001cf, |
| 391 | 0x1bf40114, | 459 | 0x1bf40114, |
| 392 | 0xfc10fcfa, | 460 | 0xfc10fcfa, |
| 461 | /* 0x03eb: cmd_exec_query */ | ||
| 393 | 0xc800f800, | 462 | 0xc800f800, |
| 394 | 0x1bf40d34, | 463 | 0x1bf40d34, |
| 395 | 0xd121f570, | 464 | 0xd121f570, |
| @@ -419,6 +488,7 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 419 | 0x0153f026, | 488 | 0x0153f026, |
| 420 | 0x080047f1, | 489 | 0x080047f1, |
| 421 | 0xd00644b6, | 490 | 0xd00644b6, |
| 491 | /* 0x045e: query_counter */ | ||
| 422 | 0x21f50045, | 492 | 0x21f50045, |
| 423 | 0x47f103d1, | 493 | 0x47f103d1, |
| 424 | 0x44b6080c, | 494 | 0x44b6080c, |
| @@ -442,11 +512,13 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 442 | 0x080047f1, | 512 | 0x080047f1, |
| 443 | 0xd00644b6, | 513 | 0xd00644b6, |
| 444 | 0x00f80045, | 514 | 0x00f80045, |
| 515 | /* 0x04b8: cmd_exec */ | ||
| 445 | 0x03d121f5, | 516 | 0x03d121f5, |
| 446 | 0xf4003fc8, | 517 | 0xf4003fc8, |
| 447 | 0x21f50e0b, | 518 | 0x21f50e0b, |
| 448 | 0x47f101af, | 519 | 0x47f101af, |
| 449 | 0x0ef40200, | 520 | 0x0ef40200, |
| 521 | /* 0x04cd: cmd_exec_no_format */ | ||
| 450 | 0x1067f11e, | 522 | 0x1067f11e, |
| 451 | 0x0664b608, | 523 | 0x0664b608, |
| 452 | 0x800177f0, | 524 | 0x800177f0, |
| @@ -454,18 +526,23 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 454 | 0x1d079819, | 526 | 0x1d079819, |
| 455 | 0xd00067d0, | 527 | 0xd00067d0, |
| 456 | 0x44bd4067, | 528 | 0x44bd4067, |
| 529 | /* 0x04e8: cmd_exec_init_src_surface */ | ||
| 457 | 0xbd0232f4, | 530 | 0xbd0232f4, |
| 458 | 0x043fc854, | 531 | 0x043fc854, |
| 459 | 0xf50a0bf4, | 532 | 0xf50a0bf4, |
| 460 | 0xf403a821, | 533 | 0xf403a821, |
| 534 | /* 0x04fa: src_tiled */ | ||
| 461 | 0x21f50a0e, | 535 | 0x21f50a0e, |
| 462 | 0x49f0029c, | 536 | 0x49f0029c, |
| 537 | /* 0x0501: cmd_exec_init_dst_surface */ | ||
| 463 | 0x0231f407, | 538 | 0x0231f407, |
| 464 | 0xc82c57f0, | 539 | 0xc82c57f0, |
| 465 | 0x0bf4083f, | 540 | 0x0bf4083f, |
| 466 | 0xa821f50a, | 541 | 0xa821f50a, |
| 467 | 0x0a0ef403, | 542 | 0x0a0ef403, |
| 543 | /* 0x0514: dst_tiled */ | ||
| 468 | 0x029c21f5, | 544 | 0x029c21f5, |
| 545 | /* 0x051b: cmd_exec_kick */ | ||
| 469 | 0xf10849f0, | 546 | 0xf10849f0, |
| 470 | 0xb6080057, | 547 | 0xb6080057, |
| 471 | 0x06980654, | 548 | 0x06980654, |
| @@ -475,7 +552,9 @@ uint32_t nvc0_pcopy_code[] = { | |||
| 475 | 0x54d00546, | 552 | 0x54d00546, |
| 476 | 0x0c3fc800, | 553 | 0x0c3fc800, |
| 477 | 0xf5070bf4, | 554 | 0xf5070bf4, |
| 555 | /* 0x053f: cmd_exec_done */ | ||
| 478 | 0xf803eb21, | 556 | 0xf803eb21, |
| 557 | /* 0x0541: cmd_wrcache_flush */ | ||
| 479 | 0x0027f100, | 558 | 0x0027f100, |
| 480 | 0xf034bd22, | 559 | 0xf034bd22, |
| 481 | 0x23d00133, | 560 | 0x23d00133, |
diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index c486d3ce3c2c..d0d60e1e7f95 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c | |||
| @@ -607,7 +607,7 @@ nvd0_crtc_commit(struct drm_crtc *crtc) | |||
| 607 | } | 607 | } |
| 608 | 608 | ||
| 609 | static bool | 609 | static bool |
| 610 | nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, | 610 | nvd0_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, |
| 611 | struct drm_display_mode *adjusted_mode) | 611 | struct drm_display_mode *adjusted_mode) |
| 612 | { | 612 | { |
| 613 | return true; | 613 | return true; |
| @@ -938,7 +938,8 @@ nvd0_dac_dpms(struct drm_encoder *encoder, int mode) | |||
| 938 | } | 938 | } |
| 939 | 939 | ||
| 940 | static bool | 940 | static bool |
| 941 | nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 941 | nvd0_dac_mode_fixup(struct drm_encoder *encoder, |
| 942 | const struct drm_display_mode *mode, | ||
| 942 | struct drm_display_mode *adjusted_mode) | 943 | struct drm_display_mode *adjusted_mode) |
| 943 | { | 944 | { |
| 944 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 945 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
| @@ -1377,7 +1378,8 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) | |||
| 1377 | } | 1378 | } |
| 1378 | 1379 | ||
| 1379 | static bool | 1380 | static bool |
| 1380 | nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 1381 | nvd0_sor_mode_fixup(struct drm_encoder *encoder, |
| 1382 | const struct drm_display_mode *mode, | ||
| 1381 | struct drm_display_mode *adjusted_mode) | 1383 | struct drm_display_mode *adjusted_mode) |
| 1382 | { | 1384 | { |
| 1383 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 1385 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 88718fad5d6d..2666a5308ab9 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c | |||
| @@ -71,7 +71,6 @@ static struct drm_driver driver = { | |||
| 71 | .irq_postinstall = r128_driver_irq_postinstall, | 71 | .irq_postinstall = r128_driver_irq_postinstall, |
| 72 | .irq_uninstall = r128_driver_irq_uninstall, | 72 | .irq_uninstall = r128_driver_irq_uninstall, |
| 73 | .irq_handler = r128_driver_irq_handler, | 73 | .irq_handler = r128_driver_irq_handler, |
| 74 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 75 | .ioctls = r128_ioctls, | 74 | .ioctls = r128_ioctls, |
| 76 | .dma_ioctl = r128_cce_buffers, | 75 | .dma_ioctl = r128_cce_buffers, |
| 77 | .fops = &r128_driver_fops, | 76 | .fops = &r128_driver_fops, |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 3904d7964a4b..9e6f76fec527 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
| @@ -457,22 +457,18 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, | |||
| 457 | switch (pll_id) { | 457 | switch (pll_id) { |
| 458 | case ATOM_PPLL1: | 458 | case ATOM_PPLL1: |
| 459 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL; | 459 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL; |
| 460 | args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 461 | args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 462 | break; | 460 | break; |
| 463 | case ATOM_PPLL2: | 461 | case ATOM_PPLL2: |
| 464 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL; | 462 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL; |
| 465 | args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 466 | args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 467 | break; | 463 | break; |
| 468 | case ATOM_DCPLL: | 464 | case ATOM_DCPLL: |
| 469 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL; | 465 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL; |
| 470 | args.v3.usSpreadSpectrumAmount = cpu_to_le16(0); | ||
| 471 | args.v3.usSpreadSpectrumStep = cpu_to_le16(0); | ||
| 472 | break; | 466 | break; |
| 473 | case ATOM_PPLL_INVALID: | 467 | case ATOM_PPLL_INVALID: |
| 474 | return; | 468 | return; |
| 475 | } | 469 | } |
| 470 | args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 471 | args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 476 | args.v3.ucEnable = enable; | 472 | args.v3.ucEnable = enable; |
| 477 | if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev)) | 473 | if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev)) |
| 478 | args.v3.ucEnable = ATOM_DISABLE; | 474 | args.v3.ucEnable = ATOM_DISABLE; |
| @@ -482,22 +478,18 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, | |||
| 482 | switch (pll_id) { | 478 | switch (pll_id) { |
| 483 | case ATOM_PPLL1: | 479 | case ATOM_PPLL1: |
| 484 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL; | 480 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL; |
| 485 | args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 486 | args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 487 | break; | 481 | break; |
| 488 | case ATOM_PPLL2: | 482 | case ATOM_PPLL2: |
| 489 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL; | 483 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL; |
| 490 | args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 491 | args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 492 | break; | 484 | break; |
| 493 | case ATOM_DCPLL: | 485 | case ATOM_DCPLL: |
| 494 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL; | 486 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL; |
| 495 | args.v2.usSpreadSpectrumAmount = cpu_to_le16(0); | ||
| 496 | args.v2.usSpreadSpectrumStep = cpu_to_le16(0); | ||
| 497 | break; | 487 | break; |
| 498 | case ATOM_PPLL_INVALID: | 488 | case ATOM_PPLL_INVALID: |
| 499 | return; | 489 | return; |
| 500 | } | 490 | } |
| 491 | args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 492 | args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 501 | args.v2.ucEnable = enable; | 493 | args.v2.ucEnable = enable; |
| 502 | if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev)) | 494 | if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev)) |
| 503 | args.v2.ucEnable = ATOM_DISABLE; | 495 | args.v2.ucEnable = ATOM_DISABLE; |
| @@ -1539,7 +1531,11 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) | |||
| 1539 | * crtc virtual pixel clock. | 1531 | * crtc virtual pixel clock. |
| 1540 | */ | 1532 | */ |
| 1541 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { | 1533 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { |
| 1542 | if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk) | 1534 | if (ASIC_IS_DCE5(rdev)) |
| 1535 | return ATOM_DCPLL; | ||
| 1536 | else if (ASIC_IS_DCE6(rdev)) | ||
| 1537 | return ATOM_PPLL0; | ||
| 1538 | else if (rdev->clock.dp_extclk) | ||
| 1543 | return ATOM_PPLL_INVALID; | 1539 | return ATOM_PPLL_INVALID; |
| 1544 | } | 1540 | } |
| 1545 | } | 1541 | } |
| @@ -1628,7 +1624,7 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1628 | } | 1624 | } |
| 1629 | 1625 | ||
| 1630 | static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, | 1626 | static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, |
| 1631 | struct drm_display_mode *mode, | 1627 | const struct drm_display_mode *mode, |
| 1632 | struct drm_display_mode *adjusted_mode) | 1628 | struct drm_display_mode *adjusted_mode) |
| 1633 | { | 1629 | { |
| 1634 | if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) | 1630 | if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) |
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 5131b3b0f7d2..7712cf5ab33b 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | * | 22 | * |
| 23 | * Authors: Dave Airlie | 23 | * Authors: Dave Airlie |
| 24 | * Alex Deucher | 24 | * Alex Deucher |
| 25 | * Jerome Glisse | ||
| 25 | */ | 26 | */ |
| 26 | #include "drmP.h" | 27 | #include "drmP.h" |
| 27 | #include "radeon_drm.h" | 28 | #include "radeon_drm.h" |
| @@ -608,7 +609,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, | |||
| 608 | } | 609 | } |
| 609 | 610 | ||
| 610 | void radeon_dp_set_link_config(struct drm_connector *connector, | 611 | void radeon_dp_set_link_config(struct drm_connector *connector, |
| 611 | struct drm_display_mode *mode) | 612 | const struct drm_display_mode *mode) |
| 612 | { | 613 | { |
| 613 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 614 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 614 | struct radeon_connector_atom_dig *dig_connector; | 615 | struct radeon_connector_atom_dig *dig_connector; |
| @@ -654,7 +655,6 @@ static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, | |||
| 654 | ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, | 655 | ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, |
| 655 | link_status, DP_LINK_STATUS_SIZE, 100); | 656 | link_status, DP_LINK_STATUS_SIZE, 100); |
| 656 | if (ret <= 0) { | 657 | if (ret <= 0) { |
| 657 | DRM_ERROR("displayport link status failed\n"); | ||
| 658 | return false; | 658 | return false; |
| 659 | } | 659 | } |
| 660 | 660 | ||
| @@ -833,8 +833,10 @@ static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) | |||
| 833 | else | 833 | else |
| 834 | mdelay(dp_info->rd_interval * 4); | 834 | mdelay(dp_info->rd_interval * 4); |
| 835 | 835 | ||
| 836 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) | 836 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
| 837 | DRM_ERROR("displayport link status failed\n"); | ||
| 837 | break; | 838 | break; |
| 839 | } | ||
| 838 | 840 | ||
| 839 | if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { | 841 | if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
| 840 | clock_recovery = true; | 842 | clock_recovery = true; |
| @@ -896,8 +898,10 @@ static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) | |||
| 896 | else | 898 | else |
| 897 | mdelay(dp_info->rd_interval * 4); | 899 | mdelay(dp_info->rd_interval * 4); |
| 898 | 900 | ||
| 899 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) | 901 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
| 902 | DRM_ERROR("displayport link status failed\n"); | ||
| 900 | break; | 903 | break; |
| 904 | } | ||
| 901 | 905 | ||
| 902 | if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { | 906 | if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
| 903 | channel_eq = true; | 907 | channel_eq = true; |
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 486ccdf4aacd..f9bc27fe269a 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c | |||
| @@ -58,7 +58,7 @@ static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) | |||
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, | 60 | static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, |
| 61 | struct drm_display_mode *mode, | 61 | const struct drm_display_mode *mode, |
| 62 | struct drm_display_mode *adjusted_mode) | 62 | struct drm_display_mode *adjusted_mode) |
| 63 | { | 63 | { |
| 64 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 64 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| @@ -1392,10 +1392,18 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) | |||
| 1392 | case DRM_MODE_DPMS_ON: | 1392 | case DRM_MODE_DPMS_ON: |
| 1393 | /* some early dce3.2 boards have a bug in their transmitter control table */ | 1393 | /* some early dce3.2 boards have a bug in their transmitter control table */ |
| 1394 | if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || | 1394 | if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || |
| 1395 | ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) | 1395 | ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { |
| 1396 | if (ASIC_IS_DCE6(rdev)) { | ||
| 1397 | /* It seems we need to call ATOM_ENCODER_CMD_SETUP again | ||
| 1398 | * before reenabling encoder on DPMS ON, otherwise we never | ||
| 1399 | * get picture | ||
| 1400 | */ | ||
| 1401 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); | ||
| 1402 | } | ||
| 1396 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); | 1403 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); |
| 1397 | else | 1404 | } else { |
| 1398 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); | 1405 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); |
| 1406 | } | ||
| 1399 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { | 1407 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { |
| 1400 | if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { | 1408 | if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { |
| 1401 | atombios_set_edp_panel_power(connector, | 1409 | atombios_set_edp_panel_power(connector, |
| @@ -2234,7 +2242,7 @@ radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode) | |||
| 2234 | } | 2242 | } |
| 2235 | 2243 | ||
| 2236 | static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder, | 2244 | static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder, |
| 2237 | struct drm_display_mode *mode, | 2245 | const struct drm_display_mode *mode, |
| 2238 | struct drm_display_mode *adjusted_mode) | 2246 | struct drm_display_mode *adjusted_mode) |
| 2239 | { | 2247 | { |
| 2240 | return true; | 2248 | return true; |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 7fb3d2e0434c..e585a3b947eb 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
| @@ -99,6 +99,14 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) | |||
| 99 | } | 99 | } |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | /** | ||
| 103 | * dce4_wait_for_vblank - vblank wait asic callback. | ||
| 104 | * | ||
| 105 | * @rdev: radeon_device pointer | ||
| 106 | * @crtc: crtc to wait for vblank on | ||
| 107 | * | ||
| 108 | * Wait for vblank on the requested crtc (evergreen+). | ||
| 109 | */ | ||
| 102 | void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) | 110 | void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) |
| 103 | { | 111 | { |
| 104 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; | 112 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; |
| @@ -118,18 +126,49 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) | |||
| 118 | } | 126 | } |
| 119 | } | 127 | } |
| 120 | 128 | ||
| 129 | /** | ||
| 130 | * radeon_irq_kms_pflip_irq_get - pre-pageflip callback. | ||
| 131 | * | ||
| 132 | * @rdev: radeon_device pointer | ||
| 133 | * @crtc: crtc to prepare for pageflip on | ||
| 134 | * | ||
| 135 | * Pre-pageflip callback (evergreen+). | ||
| 136 | * Enables the pageflip irq (vblank irq). | ||
| 137 | */ | ||
| 121 | void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) | 138 | void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) |
| 122 | { | 139 | { |
| 123 | /* enable the pflip int */ | 140 | /* enable the pflip int */ |
| 124 | radeon_irq_kms_pflip_irq_get(rdev, crtc); | 141 | radeon_irq_kms_pflip_irq_get(rdev, crtc); |
| 125 | } | 142 | } |
| 126 | 143 | ||
| 144 | /** | ||
| 145 | * evergreen_post_page_flip - pos-pageflip callback. | ||
| 146 | * | ||
| 147 | * @rdev: radeon_device pointer | ||
| 148 | * @crtc: crtc to cleanup pageflip on | ||
| 149 | * | ||
| 150 | * Post-pageflip callback (evergreen+). | ||
| 151 | * Disables the pageflip irq (vblank irq). | ||
| 152 | */ | ||
| 127 | void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) | 153 | void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) |
| 128 | { | 154 | { |
| 129 | /* disable the pflip int */ | 155 | /* disable the pflip int */ |
| 130 | radeon_irq_kms_pflip_irq_put(rdev, crtc); | 156 | radeon_irq_kms_pflip_irq_put(rdev, crtc); |
| 131 | } | 157 | } |
| 132 | 158 | ||
| 159 | /** | ||
| 160 | * evergreen_page_flip - pageflip callback. | ||
| 161 | * | ||
| 162 | * @rdev: radeon_device pointer | ||
| 163 | * @crtc_id: crtc to cleanup pageflip on | ||
| 164 | * @crtc_base: new address of the crtc (GPU MC address) | ||
| 165 | * | ||
| 166 | * Does the actual pageflip (evergreen+). | ||
| 167 | * During vblank we take the crtc lock and wait for the update_pending | ||
| 168 | * bit to go high, when it does, we release the lock, and allow the | ||
| 169 | * double buffered update to take place. | ||
| 170 | * Returns the current update pending status. | ||
| 171 | */ | ||
| 133 | u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | 172 | u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) |
| 134 | { | 173 | { |
| 135 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 174 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
| @@ -214,6 +253,15 @@ int sumo_get_temp(struct radeon_device *rdev) | |||
| 214 | return actual_temp * 1000; | 253 | return actual_temp * 1000; |
| 215 | } | 254 | } |
| 216 | 255 | ||
| 256 | /** | ||
| 257 | * sumo_pm_init_profile - Initialize power profiles callback. | ||
| 258 | * | ||
| 259 | * @rdev: radeon_device pointer | ||
| 260 | * | ||
| 261 | * Initialize the power states used in profile mode | ||
| 262 | * (sumo, trinity, SI). | ||
| 263 | * Used for profile mode only. | ||
| 264 | */ | ||
| 217 | void sumo_pm_init_profile(struct radeon_device *rdev) | 265 | void sumo_pm_init_profile(struct radeon_device *rdev) |
| 218 | { | 266 | { |
| 219 | int idx; | 267 | int idx; |
| @@ -265,6 +313,14 @@ void sumo_pm_init_profile(struct radeon_device *rdev) | |||
| 265 | rdev->pm.power_state[idx].num_clock_modes - 1; | 313 | rdev->pm.power_state[idx].num_clock_modes - 1; |
| 266 | } | 314 | } |
| 267 | 315 | ||
| 316 | /** | ||
| 317 | * evergreen_pm_misc - set additional pm hw parameters callback. | ||
| 318 | * | ||
| 319 | * @rdev: radeon_device pointer | ||
| 320 | * | ||
| 321 | * Set non-clock parameters associated with a power state | ||
| 322 | * (voltage, etc.) (evergreen+). | ||
| 323 | */ | ||
| 268 | void evergreen_pm_misc(struct radeon_device *rdev) | 324 | void evergreen_pm_misc(struct radeon_device *rdev) |
| 269 | { | 325 | { |
| 270 | int req_ps_idx = rdev->pm.requested_power_state_index; | 326 | int req_ps_idx = rdev->pm.requested_power_state_index; |
| @@ -292,6 +348,13 @@ void evergreen_pm_misc(struct radeon_device *rdev) | |||
| 292 | } | 348 | } |
| 293 | } | 349 | } |
| 294 | 350 | ||
| 351 | /** | ||
| 352 | * evergreen_pm_prepare - pre-power state change callback. | ||
| 353 | * | ||
| 354 | * @rdev: radeon_device pointer | ||
| 355 | * | ||
| 356 | * Prepare for a power state change (evergreen+). | ||
| 357 | */ | ||
| 295 | void evergreen_pm_prepare(struct radeon_device *rdev) | 358 | void evergreen_pm_prepare(struct radeon_device *rdev) |
| 296 | { | 359 | { |
| 297 | struct drm_device *ddev = rdev->ddev; | 360 | struct drm_device *ddev = rdev->ddev; |
| @@ -310,6 +373,13 @@ void evergreen_pm_prepare(struct radeon_device *rdev) | |||
| 310 | } | 373 | } |
| 311 | } | 374 | } |
| 312 | 375 | ||
| 376 | /** | ||
| 377 | * evergreen_pm_finish - post-power state change callback. | ||
| 378 | * | ||
| 379 | * @rdev: radeon_device pointer | ||
| 380 | * | ||
| 381 | * Clean up after a power state change (evergreen+). | ||
| 382 | */ | ||
| 313 | void evergreen_pm_finish(struct radeon_device *rdev) | 383 | void evergreen_pm_finish(struct radeon_device *rdev) |
| 314 | { | 384 | { |
| 315 | struct drm_device *ddev = rdev->ddev; | 385 | struct drm_device *ddev = rdev->ddev; |
| @@ -328,6 +398,15 @@ void evergreen_pm_finish(struct radeon_device *rdev) | |||
| 328 | } | 398 | } |
| 329 | } | 399 | } |
| 330 | 400 | ||
| 401 | /** | ||
| 402 | * evergreen_hpd_sense - hpd sense callback. | ||
| 403 | * | ||
| 404 | * @rdev: radeon_device pointer | ||
| 405 | * @hpd: hpd (hotplug detect) pin | ||
| 406 | * | ||
| 407 | * Checks if a digital monitor is connected (evergreen+). | ||
| 408 | * Returns true if connected, false if not connected. | ||
| 409 | */ | ||
| 331 | bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | 410 | bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) |
| 332 | { | 411 | { |
| 333 | bool connected = false; | 412 | bool connected = false; |
| @@ -364,6 +443,14 @@ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | |||
| 364 | return connected; | 443 | return connected; |
| 365 | } | 444 | } |
| 366 | 445 | ||
| 446 | /** | ||
| 447 | * evergreen_hpd_set_polarity - hpd set polarity callback. | ||
| 448 | * | ||
| 449 | * @rdev: radeon_device pointer | ||
| 450 | * @hpd: hpd (hotplug detect) pin | ||
| 451 | * | ||
| 452 | * Set the polarity of the hpd pin (evergreen+). | ||
| 453 | */ | ||
| 367 | void evergreen_hpd_set_polarity(struct radeon_device *rdev, | 454 | void evergreen_hpd_set_polarity(struct radeon_device *rdev, |
| 368 | enum radeon_hpd_id hpd) | 455 | enum radeon_hpd_id hpd) |
| 369 | { | 456 | { |
| @@ -424,10 +511,19 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev, | |||
| 424 | } | 511 | } |
| 425 | } | 512 | } |
| 426 | 513 | ||
| 514 | /** | ||
| 515 | * evergreen_hpd_init - hpd setup callback. | ||
| 516 | * | ||
| 517 | * @rdev: radeon_device pointer | ||
| 518 | * | ||
| 519 | * Setup the hpd pins used by the card (evergreen+). | ||
| 520 | * Enable the pin, set the polarity, and enable the hpd interrupts. | ||
| 521 | */ | ||
| 427 | void evergreen_hpd_init(struct radeon_device *rdev) | 522 | void evergreen_hpd_init(struct radeon_device *rdev) |
| 428 | { | 523 | { |
| 429 | struct drm_device *dev = rdev->ddev; | 524 | struct drm_device *dev = rdev->ddev; |
| 430 | struct drm_connector *connector; | 525 | struct drm_connector *connector; |
| 526 | unsigned enabled = 0; | ||
| 431 | u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | | 527 | u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | |
| 432 | DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN; | 528 | DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN; |
| 433 | 529 | ||
| @@ -436,73 +532,72 @@ void evergreen_hpd_init(struct radeon_device *rdev) | |||
| 436 | switch (radeon_connector->hpd.hpd) { | 532 | switch (radeon_connector->hpd.hpd) { |
| 437 | case RADEON_HPD_1: | 533 | case RADEON_HPD_1: |
| 438 | WREG32(DC_HPD1_CONTROL, tmp); | 534 | WREG32(DC_HPD1_CONTROL, tmp); |
| 439 | rdev->irq.hpd[0] = true; | ||
| 440 | break; | 535 | break; |
| 441 | case RADEON_HPD_2: | 536 | case RADEON_HPD_2: |
| 442 | WREG32(DC_HPD2_CONTROL, tmp); | 537 | WREG32(DC_HPD2_CONTROL, tmp); |
| 443 | rdev->irq.hpd[1] = true; | ||
| 444 | break; | 538 | break; |
| 445 | case RADEON_HPD_3: | 539 | case RADEON_HPD_3: |
| 446 | WREG32(DC_HPD3_CONTROL, tmp); | 540 | WREG32(DC_HPD3_CONTROL, tmp); |
| 447 | rdev->irq.hpd[2] = true; | ||
| 448 | break; | 541 | break; |
| 449 | case RADEON_HPD_4: | 542 | case RADEON_HPD_4: |
| 450 | WREG32(DC_HPD4_CONTROL, tmp); | 543 | WREG32(DC_HPD4_CONTROL, tmp); |
| 451 | rdev->irq.hpd[3] = true; | ||
| 452 | break; | 544 | break; |
| 453 | case RADEON_HPD_5: | 545 | case RADEON_HPD_5: |
| 454 | WREG32(DC_HPD5_CONTROL, tmp); | 546 | WREG32(DC_HPD5_CONTROL, tmp); |
| 455 | rdev->irq.hpd[4] = true; | ||
| 456 | break; | 547 | break; |
| 457 | case RADEON_HPD_6: | 548 | case RADEON_HPD_6: |
| 458 | WREG32(DC_HPD6_CONTROL, tmp); | 549 | WREG32(DC_HPD6_CONTROL, tmp); |
| 459 | rdev->irq.hpd[5] = true; | ||
| 460 | break; | 550 | break; |
| 461 | default: | 551 | default: |
| 462 | break; | 552 | break; |
| 463 | } | 553 | } |
| 464 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 554 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
| 555 | enabled |= 1 << radeon_connector->hpd.hpd; | ||
| 465 | } | 556 | } |
| 466 | if (rdev->irq.installed) | 557 | radeon_irq_kms_enable_hpd(rdev, enabled); |
| 467 | evergreen_irq_set(rdev); | ||
| 468 | } | 558 | } |
| 469 | 559 | ||
| 560 | /** | ||
| 561 | * evergreen_hpd_fini - hpd tear down callback. | ||
| 562 | * | ||
| 563 | * @rdev: radeon_device pointer | ||
| 564 | * | ||
| 565 | * Tear down the hpd pins used by the card (evergreen+). | ||
| 566 | * Disable the hpd interrupts. | ||
| 567 | */ | ||
| 470 | void evergreen_hpd_fini(struct radeon_device *rdev) | 568 | void evergreen_hpd_fini(struct radeon_device *rdev) |
| 471 | { | 569 | { |
| 472 | struct drm_device *dev = rdev->ddev; | 570 | struct drm_device *dev = rdev->ddev; |
| 473 | struct drm_connector *connector; | 571 | struct drm_connector *connector; |
| 572 | unsigned disabled = 0; | ||
| 474 | 573 | ||
| 475 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 574 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 476 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 575 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 477 | switch (radeon_connector->hpd.hpd) { | 576 | switch (radeon_connector->hpd.hpd) { |
| 478 | case RADEON_HPD_1: | 577 | case RADEON_HPD_1: |
| 479 | WREG32(DC_HPD1_CONTROL, 0); | 578 | WREG32(DC_HPD1_CONTROL, 0); |
| 480 | rdev->irq.hpd[0] = false; | ||
| 481 | break; | 579 | break; |
| 482 | case RADEON_HPD_2: | 580 | case RADEON_HPD_2: |
| 483 | WREG32(DC_HPD2_CONTROL, 0); | 581 | WREG32(DC_HPD2_CONTROL, 0); |
| 484 | rdev->irq.hpd[1] = false; | ||
| 485 | break; | 582 | break; |
| 486 | case RADEON_HPD_3: | 583 | case RADEON_HPD_3: |
| 487 | WREG32(DC_HPD3_CONTROL, 0); | 584 | WREG32(DC_HPD3_CONTROL, 0); |
| 488 | rdev->irq.hpd[2] = false; | ||
| 489 | break; | 585 | break; |
| 490 | case RADEON_HPD_4: | 586 | case RADEON_HPD_4: |
| 491 | WREG32(DC_HPD4_CONTROL, 0); | 587 | WREG32(DC_HPD4_CONTROL, 0); |
| 492 | rdev->irq.hpd[3] = false; | ||
| 493 | break; | 588 | break; |
| 494 | case RADEON_HPD_5: | 589 | case RADEON_HPD_5: |
| 495 | WREG32(DC_HPD5_CONTROL, 0); | 590 | WREG32(DC_HPD5_CONTROL, 0); |
| 496 | rdev->irq.hpd[4] = false; | ||
| 497 | break; | 591 | break; |
| 498 | case RADEON_HPD_6: | 592 | case RADEON_HPD_6: |
| 499 | WREG32(DC_HPD6_CONTROL, 0); | 593 | WREG32(DC_HPD6_CONTROL, 0); |
| 500 | rdev->irq.hpd[5] = false; | ||
| 501 | break; | 594 | break; |
| 502 | default: | 595 | default: |
| 503 | break; | 596 | break; |
| 504 | } | 597 | } |
| 598 | disabled |= 1 << radeon_connector->hpd.hpd; | ||
| 505 | } | 599 | } |
| 600 | radeon_irq_kms_disable_hpd(rdev, disabled); | ||
| 506 | } | 601 | } |
| 507 | 602 | ||
| 508 | /* watermark setup */ | 603 | /* watermark setup */ |
| @@ -933,6 +1028,14 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, | |||
| 933 | 1028 | ||
| 934 | } | 1029 | } |
| 935 | 1030 | ||
| 1031 | /** | ||
| 1032 | * evergreen_bandwidth_update - update display watermarks callback. | ||
| 1033 | * | ||
| 1034 | * @rdev: radeon_device pointer | ||
| 1035 | * | ||
| 1036 | * Update the display watermarks based on the requested mode(s) | ||
| 1037 | * (evergreen+). | ||
| 1038 | */ | ||
| 936 | void evergreen_bandwidth_update(struct radeon_device *rdev) | 1039 | void evergreen_bandwidth_update(struct radeon_device *rdev) |
| 937 | { | 1040 | { |
| 938 | struct drm_display_mode *mode0 = NULL; | 1041 | struct drm_display_mode *mode0 = NULL; |
| @@ -956,6 +1059,15 @@ void evergreen_bandwidth_update(struct radeon_device *rdev) | |||
| 956 | } | 1059 | } |
| 957 | } | 1060 | } |
| 958 | 1061 | ||
| 1062 | /** | ||
| 1063 | * evergreen_mc_wait_for_idle - wait for MC idle callback. | ||
| 1064 | * | ||
| 1065 | * @rdev: radeon_device pointer | ||
| 1066 | * | ||
| 1067 | * Wait for the MC (memory controller) to be idle. | ||
| 1068 | * (evergreen+). | ||
| 1069 | * Returns 0 if the MC is idle, -1 if not. | ||
| 1070 | */ | ||
| 959 | int evergreen_mc_wait_for_idle(struct radeon_device *rdev) | 1071 | int evergreen_mc_wait_for_idle(struct radeon_device *rdev) |
| 960 | { | 1072 | { |
| 961 | unsigned i; | 1073 | unsigned i; |
| @@ -1371,12 +1483,28 @@ void evergreen_mc_program(struct radeon_device *rdev) | |||
| 1371 | */ | 1483 | */ |
| 1372 | void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | 1484 | void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) |
| 1373 | { | 1485 | { |
| 1374 | struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; | 1486 | struct radeon_ring *ring = &rdev->ring[ib->ring]; |
| 1487 | u32 next_rptr; | ||
| 1375 | 1488 | ||
| 1376 | /* set to DX10/11 mode */ | 1489 | /* set to DX10/11 mode */ |
| 1377 | radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); | 1490 | radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); |
| 1378 | radeon_ring_write(ring, 1); | 1491 | radeon_ring_write(ring, 1); |
| 1379 | /* FIXME: implement */ | 1492 | |
| 1493 | if (ring->rptr_save_reg) { | ||
| 1494 | next_rptr = ring->wptr + 3 + 4; | ||
| 1495 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
| 1496 | radeon_ring_write(ring, ((ring->rptr_save_reg - | ||
| 1497 | PACKET3_SET_CONFIG_REG_START) >> 2)); | ||
| 1498 | radeon_ring_write(ring, next_rptr); | ||
| 1499 | } else if (rdev->wb.enabled) { | ||
| 1500 | next_rptr = ring->wptr + 5 + 4; | ||
| 1501 | radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3)); | ||
| 1502 | radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); | ||
| 1503 | radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18)); | ||
| 1504 | radeon_ring_write(ring, next_rptr); | ||
| 1505 | radeon_ring_write(ring, 0); | ||
| 1506 | } | ||
| 1507 | |||
| 1380 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); | 1508 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
| 1381 | radeon_ring_write(ring, | 1509 | radeon_ring_write(ring, |
| 1382 | #ifdef __BIG_ENDIAN | 1510 | #ifdef __BIG_ENDIAN |
| @@ -2188,6 +2316,14 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev) | |||
| 2188 | RREG32(GRBM_STATUS_SE1)); | 2316 | RREG32(GRBM_STATUS_SE1)); |
| 2189 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | 2317 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", |
| 2190 | RREG32(SRBM_STATUS)); | 2318 | RREG32(SRBM_STATUS)); |
| 2319 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 2320 | RREG32(CP_STALLED_STAT1)); | ||
| 2321 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 2322 | RREG32(CP_STALLED_STAT2)); | ||
| 2323 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 2324 | RREG32(CP_BUSY_STAT)); | ||
| 2325 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 2326 | RREG32(CP_STAT)); | ||
| 2191 | evergreen_mc_stop(rdev, &save); | 2327 | evergreen_mc_stop(rdev, &save); |
| 2192 | if (evergreen_mc_wait_for_idle(rdev)) { | 2328 | if (evergreen_mc_wait_for_idle(rdev)) { |
| 2193 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | 2329 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); |
| @@ -2225,6 +2361,14 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev) | |||
| 2225 | RREG32(GRBM_STATUS_SE1)); | 2361 | RREG32(GRBM_STATUS_SE1)); |
| 2226 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | 2362 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", |
| 2227 | RREG32(SRBM_STATUS)); | 2363 | RREG32(SRBM_STATUS)); |
| 2364 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 2365 | RREG32(CP_STALLED_STAT1)); | ||
| 2366 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 2367 | RREG32(CP_STALLED_STAT2)); | ||
| 2368 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 2369 | RREG32(CP_BUSY_STAT)); | ||
| 2370 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 2371 | RREG32(CP_STAT)); | ||
| 2228 | evergreen_mc_resume(rdev, &save); | 2372 | evergreen_mc_resume(rdev, &save); |
| 2229 | return 0; | 2373 | return 0; |
| 2230 | } | 2374 | } |
| @@ -2348,20 +2492,20 @@ int evergreen_irq_set(struct radeon_device *rdev) | |||
| 2348 | 2492 | ||
| 2349 | if (rdev->family >= CHIP_CAYMAN) { | 2493 | if (rdev->family >= CHIP_CAYMAN) { |
| 2350 | /* enable CP interrupts on all rings */ | 2494 | /* enable CP interrupts on all rings */ |
| 2351 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 2495 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 2352 | DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); | 2496 | DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); |
| 2353 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | 2497 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; |
| 2354 | } | 2498 | } |
| 2355 | if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP1_INDEX]) { | 2499 | if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) { |
| 2356 | DRM_DEBUG("evergreen_irq_set: sw int cp1\n"); | 2500 | DRM_DEBUG("evergreen_irq_set: sw int cp1\n"); |
| 2357 | cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; | 2501 | cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; |
| 2358 | } | 2502 | } |
| 2359 | if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP2_INDEX]) { | 2503 | if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) { |
| 2360 | DRM_DEBUG("evergreen_irq_set: sw int cp2\n"); | 2504 | DRM_DEBUG("evergreen_irq_set: sw int cp2\n"); |
| 2361 | cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; | 2505 | cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; |
| 2362 | } | 2506 | } |
| 2363 | } else { | 2507 | } else { |
| 2364 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 2508 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 2365 | DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); | 2509 | DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); |
| 2366 | cp_int_cntl |= RB_INT_ENABLE; | 2510 | cp_int_cntl |= RB_INT_ENABLE; |
| 2367 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | 2511 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; |
| @@ -2369,32 +2513,32 @@ int evergreen_irq_set(struct radeon_device *rdev) | |||
| 2369 | } | 2513 | } |
| 2370 | 2514 | ||
| 2371 | if (rdev->irq.crtc_vblank_int[0] || | 2515 | if (rdev->irq.crtc_vblank_int[0] || |
| 2372 | rdev->irq.pflip[0]) { | 2516 | atomic_read(&rdev->irq.pflip[0])) { |
| 2373 | DRM_DEBUG("evergreen_irq_set: vblank 0\n"); | 2517 | DRM_DEBUG("evergreen_irq_set: vblank 0\n"); |
| 2374 | crtc1 |= VBLANK_INT_MASK; | 2518 | crtc1 |= VBLANK_INT_MASK; |
| 2375 | } | 2519 | } |
| 2376 | if (rdev->irq.crtc_vblank_int[1] || | 2520 | if (rdev->irq.crtc_vblank_int[1] || |
| 2377 | rdev->irq.pflip[1]) { | 2521 | atomic_read(&rdev->irq.pflip[1])) { |
| 2378 | DRM_DEBUG("evergreen_irq_set: vblank 1\n"); | 2522 | DRM_DEBUG("evergreen_irq_set: vblank 1\n"); |
| 2379 | crtc2 |= VBLANK_INT_MASK; | 2523 | crtc2 |= VBLANK_INT_MASK; |
| 2380 | } | 2524 | } |
| 2381 | if (rdev->irq.crtc_vblank_int[2] || | 2525 | if (rdev->irq.crtc_vblank_int[2] || |
| 2382 | rdev->irq.pflip[2]) { | 2526 | atomic_read(&rdev->irq.pflip[2])) { |
| 2383 | DRM_DEBUG("evergreen_irq_set: vblank 2\n"); | 2527 | DRM_DEBUG("evergreen_irq_set: vblank 2\n"); |
| 2384 | crtc3 |= VBLANK_INT_MASK; | 2528 | crtc3 |= VBLANK_INT_MASK; |
| 2385 | } | 2529 | } |
| 2386 | if (rdev->irq.crtc_vblank_int[3] || | 2530 | if (rdev->irq.crtc_vblank_int[3] || |
| 2387 | rdev->irq.pflip[3]) { | 2531 | atomic_read(&rdev->irq.pflip[3])) { |
| 2388 | DRM_DEBUG("evergreen_irq_set: vblank 3\n"); | 2532 | DRM_DEBUG("evergreen_irq_set: vblank 3\n"); |
| 2389 | crtc4 |= VBLANK_INT_MASK; | 2533 | crtc4 |= VBLANK_INT_MASK; |
| 2390 | } | 2534 | } |
| 2391 | if (rdev->irq.crtc_vblank_int[4] || | 2535 | if (rdev->irq.crtc_vblank_int[4] || |
| 2392 | rdev->irq.pflip[4]) { | 2536 | atomic_read(&rdev->irq.pflip[4])) { |
| 2393 | DRM_DEBUG("evergreen_irq_set: vblank 4\n"); | 2537 | DRM_DEBUG("evergreen_irq_set: vblank 4\n"); |
| 2394 | crtc5 |= VBLANK_INT_MASK; | 2538 | crtc5 |= VBLANK_INT_MASK; |
| 2395 | } | 2539 | } |
| 2396 | if (rdev->irq.crtc_vblank_int[5] || | 2540 | if (rdev->irq.crtc_vblank_int[5] || |
| 2397 | rdev->irq.pflip[5]) { | 2541 | atomic_read(&rdev->irq.pflip[5])) { |
| 2398 | DRM_DEBUG("evergreen_irq_set: vblank 5\n"); | 2542 | DRM_DEBUG("evergreen_irq_set: vblank 5\n"); |
| 2399 | crtc6 |= VBLANK_INT_MASK; | 2543 | crtc6 |= VBLANK_INT_MASK; |
| 2400 | } | 2544 | } |
| @@ -2676,7 +2820,6 @@ int evergreen_irq_process(struct radeon_device *rdev) | |||
| 2676 | u32 rptr; | 2820 | u32 rptr; |
| 2677 | u32 src_id, src_data; | 2821 | u32 src_id, src_data; |
| 2678 | u32 ring_index; | 2822 | u32 ring_index; |
| 2679 | unsigned long flags; | ||
| 2680 | bool queue_hotplug = false; | 2823 | bool queue_hotplug = false; |
| 2681 | bool queue_hdmi = false; | 2824 | bool queue_hdmi = false; |
| 2682 | 2825 | ||
| @@ -2684,22 +2827,21 @@ int evergreen_irq_process(struct radeon_device *rdev) | |||
| 2684 | return IRQ_NONE; | 2827 | return IRQ_NONE; |
| 2685 | 2828 | ||
| 2686 | wptr = evergreen_get_ih_wptr(rdev); | 2829 | wptr = evergreen_get_ih_wptr(rdev); |
| 2830 | |||
| 2831 | restart_ih: | ||
| 2832 | /* is somebody else already processing irqs? */ | ||
| 2833 | if (atomic_xchg(&rdev->ih.lock, 1)) | ||
| 2834 | return IRQ_NONE; | ||
| 2835 | |||
| 2687 | rptr = rdev->ih.rptr; | 2836 | rptr = rdev->ih.rptr; |
| 2688 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | 2837 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); |
| 2689 | 2838 | ||
| 2690 | spin_lock_irqsave(&rdev->ih.lock, flags); | ||
| 2691 | if (rptr == wptr) { | ||
| 2692 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | ||
| 2693 | return IRQ_NONE; | ||
| 2694 | } | ||
| 2695 | restart_ih: | ||
| 2696 | /* Order reading of wptr vs. reading of IH ring data */ | 2839 | /* Order reading of wptr vs. reading of IH ring data */ |
| 2697 | rmb(); | 2840 | rmb(); |
| 2698 | 2841 | ||
| 2699 | /* display interrupts */ | 2842 | /* display interrupts */ |
| 2700 | evergreen_irq_ack(rdev); | 2843 | evergreen_irq_ack(rdev); |
| 2701 | 2844 | ||
| 2702 | rdev->ih.wptr = wptr; | ||
| 2703 | while (rptr != wptr) { | 2845 | while (rptr != wptr) { |
| 2704 | /* wptr/rptr are in bytes! */ | 2846 | /* wptr/rptr are in bytes! */ |
| 2705 | ring_index = rptr / 4; | 2847 | ring_index = rptr / 4; |
| @@ -2716,7 +2858,7 @@ restart_ih: | |||
| 2716 | rdev->pm.vblank_sync = true; | 2858 | rdev->pm.vblank_sync = true; |
| 2717 | wake_up(&rdev->irq.vblank_queue); | 2859 | wake_up(&rdev->irq.vblank_queue); |
| 2718 | } | 2860 | } |
| 2719 | if (rdev->irq.pflip[0]) | 2861 | if (atomic_read(&rdev->irq.pflip[0])) |
| 2720 | radeon_crtc_handle_flip(rdev, 0); | 2862 | radeon_crtc_handle_flip(rdev, 0); |
| 2721 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | 2863 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; |
| 2722 | DRM_DEBUG("IH: D1 vblank\n"); | 2864 | DRM_DEBUG("IH: D1 vblank\n"); |
| @@ -2742,7 +2884,7 @@ restart_ih: | |||
| 2742 | rdev->pm.vblank_sync = true; | 2884 | rdev->pm.vblank_sync = true; |
| 2743 | wake_up(&rdev->irq.vblank_queue); | 2885 | wake_up(&rdev->irq.vblank_queue); |
| 2744 | } | 2886 | } |
| 2745 | if (rdev->irq.pflip[1]) | 2887 | if (atomic_read(&rdev->irq.pflip[1])) |
| 2746 | radeon_crtc_handle_flip(rdev, 1); | 2888 | radeon_crtc_handle_flip(rdev, 1); |
| 2747 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; | 2889 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; |
| 2748 | DRM_DEBUG("IH: D2 vblank\n"); | 2890 | DRM_DEBUG("IH: D2 vblank\n"); |
| @@ -2768,7 +2910,7 @@ restart_ih: | |||
| 2768 | rdev->pm.vblank_sync = true; | 2910 | rdev->pm.vblank_sync = true; |
| 2769 | wake_up(&rdev->irq.vblank_queue); | 2911 | wake_up(&rdev->irq.vblank_queue); |
| 2770 | } | 2912 | } |
| 2771 | if (rdev->irq.pflip[2]) | 2913 | if (atomic_read(&rdev->irq.pflip[2])) |
| 2772 | radeon_crtc_handle_flip(rdev, 2); | 2914 | radeon_crtc_handle_flip(rdev, 2); |
| 2773 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; | 2915 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; |
| 2774 | DRM_DEBUG("IH: D3 vblank\n"); | 2916 | DRM_DEBUG("IH: D3 vblank\n"); |
| @@ -2794,7 +2936,7 @@ restart_ih: | |||
| 2794 | rdev->pm.vblank_sync = true; | 2936 | rdev->pm.vblank_sync = true; |
| 2795 | wake_up(&rdev->irq.vblank_queue); | 2937 | wake_up(&rdev->irq.vblank_queue); |
| 2796 | } | 2938 | } |
| 2797 | if (rdev->irq.pflip[3]) | 2939 | if (atomic_read(&rdev->irq.pflip[3])) |
| 2798 | radeon_crtc_handle_flip(rdev, 3); | 2940 | radeon_crtc_handle_flip(rdev, 3); |
| 2799 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; | 2941 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; |
| 2800 | DRM_DEBUG("IH: D4 vblank\n"); | 2942 | DRM_DEBUG("IH: D4 vblank\n"); |
| @@ -2820,7 +2962,7 @@ restart_ih: | |||
| 2820 | rdev->pm.vblank_sync = true; | 2962 | rdev->pm.vblank_sync = true; |
| 2821 | wake_up(&rdev->irq.vblank_queue); | 2963 | wake_up(&rdev->irq.vblank_queue); |
| 2822 | } | 2964 | } |
| 2823 | if (rdev->irq.pflip[4]) | 2965 | if (atomic_read(&rdev->irq.pflip[4])) |
| 2824 | radeon_crtc_handle_flip(rdev, 4); | 2966 | radeon_crtc_handle_flip(rdev, 4); |
| 2825 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; | 2967 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; |
| 2826 | DRM_DEBUG("IH: D5 vblank\n"); | 2968 | DRM_DEBUG("IH: D5 vblank\n"); |
| @@ -2846,7 +2988,7 @@ restart_ih: | |||
| 2846 | rdev->pm.vblank_sync = true; | 2988 | rdev->pm.vblank_sync = true; |
| 2847 | wake_up(&rdev->irq.vblank_queue); | 2989 | wake_up(&rdev->irq.vblank_queue); |
| 2848 | } | 2990 | } |
| 2849 | if (rdev->irq.pflip[5]) | 2991 | if (atomic_read(&rdev->irq.pflip[5])) |
| 2850 | radeon_crtc_handle_flip(rdev, 5); | 2992 | radeon_crtc_handle_flip(rdev, 5); |
| 2851 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; | 2993 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; |
| 2852 | DRM_DEBUG("IH: D6 vblank\n"); | 2994 | DRM_DEBUG("IH: D6 vblank\n"); |
| @@ -2986,7 +3128,6 @@ restart_ih: | |||
| 2986 | break; | 3128 | break; |
| 2987 | case 233: /* GUI IDLE */ | 3129 | case 233: /* GUI IDLE */ |
| 2988 | DRM_DEBUG("IH: GUI idle\n"); | 3130 | DRM_DEBUG("IH: GUI idle\n"); |
| 2989 | rdev->pm.gui_idle = true; | ||
| 2990 | wake_up(&rdev->irq.idle_queue); | 3131 | wake_up(&rdev->irq.idle_queue); |
| 2991 | break; | 3132 | break; |
| 2992 | default: | 3133 | default: |
| @@ -2998,17 +3139,19 @@ restart_ih: | |||
| 2998 | rptr += 16; | 3139 | rptr += 16; |
| 2999 | rptr &= rdev->ih.ptr_mask; | 3140 | rptr &= rdev->ih.ptr_mask; |
| 3000 | } | 3141 | } |
| 3001 | /* make sure wptr hasn't changed while processing */ | ||
| 3002 | wptr = evergreen_get_ih_wptr(rdev); | ||
| 3003 | if (wptr != rdev->ih.wptr) | ||
| 3004 | goto restart_ih; | ||
| 3005 | if (queue_hotplug) | 3142 | if (queue_hotplug) |
| 3006 | schedule_work(&rdev->hotplug_work); | 3143 | schedule_work(&rdev->hotplug_work); |
| 3007 | if (queue_hdmi) | 3144 | if (queue_hdmi) |
| 3008 | schedule_work(&rdev->audio_work); | 3145 | schedule_work(&rdev->audio_work); |
| 3009 | rdev->ih.rptr = rptr; | 3146 | rdev->ih.rptr = rptr; |
| 3010 | WREG32(IH_RB_RPTR, rdev->ih.rptr); | 3147 | WREG32(IH_RB_RPTR, rdev->ih.rptr); |
| 3011 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | 3148 | atomic_set(&rdev->ih.lock, 0); |
| 3149 | |||
| 3150 | /* make sure wptr hasn't changed while processing */ | ||
| 3151 | wptr = evergreen_get_ih_wptr(rdev); | ||
| 3152 | if (wptr != rptr) | ||
| 3153 | goto restart_ih; | ||
| 3154 | |||
| 3012 | return IRQ_HANDLED; | 3155 | return IRQ_HANDLED; |
| 3013 | } | 3156 | } |
| 3014 | 3157 | ||
| @@ -3096,13 +3239,11 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
| 3096 | if (r) | 3239 | if (r) |
| 3097 | return r; | 3240 | return r; |
| 3098 | 3241 | ||
| 3099 | r = radeon_ib_pool_start(rdev); | 3242 | r = radeon_ib_pool_init(rdev); |
| 3100 | if (r) | 3243 | if (r) { |
| 3101 | return r; | 3244 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 3102 | |||
| 3103 | r = radeon_ib_ring_tests(rdev); | ||
| 3104 | if (r) | ||
| 3105 | return r; | 3245 | return r; |
| 3246 | } | ||
| 3106 | 3247 | ||
| 3107 | r = r600_audio_init(rdev); | 3248 | r = r600_audio_init(rdev); |
| 3108 | if (r) { | 3249 | if (r) { |
| @@ -3146,9 +3287,6 @@ int evergreen_suspend(struct radeon_device *rdev) | |||
| 3146 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 3287 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 3147 | 3288 | ||
| 3148 | r600_audio_fini(rdev); | 3289 | r600_audio_fini(rdev); |
| 3149 | /* FIXME: we should wait for ring to be empty */ | ||
| 3150 | radeon_ib_pool_suspend(rdev); | ||
| 3151 | r600_blit_suspend(rdev); | ||
| 3152 | r700_cp_stop(rdev); | 3290 | r700_cp_stop(rdev); |
| 3153 | ring->ready = false; | 3291 | ring->ready = false; |
| 3154 | evergreen_irq_suspend(rdev); | 3292 | evergreen_irq_suspend(rdev); |
| @@ -3234,20 +3372,14 @@ int evergreen_init(struct radeon_device *rdev) | |||
| 3234 | if (r) | 3372 | if (r) |
| 3235 | return r; | 3373 | return r; |
| 3236 | 3374 | ||
| 3237 | r = radeon_ib_pool_init(rdev); | ||
| 3238 | rdev->accel_working = true; | 3375 | rdev->accel_working = true; |
| 3239 | if (r) { | ||
| 3240 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 3241 | rdev->accel_working = false; | ||
| 3242 | } | ||
| 3243 | |||
| 3244 | r = evergreen_startup(rdev); | 3376 | r = evergreen_startup(rdev); |
| 3245 | if (r) { | 3377 | if (r) { |
| 3246 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 3378 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
| 3247 | r700_cp_fini(rdev); | 3379 | r700_cp_fini(rdev); |
| 3248 | r600_irq_fini(rdev); | 3380 | r600_irq_fini(rdev); |
| 3249 | radeon_wb_fini(rdev); | 3381 | radeon_wb_fini(rdev); |
| 3250 | r100_ib_fini(rdev); | 3382 | radeon_ib_pool_fini(rdev); |
| 3251 | radeon_irq_kms_fini(rdev); | 3383 | radeon_irq_kms_fini(rdev); |
| 3252 | evergreen_pcie_gart_fini(rdev); | 3384 | evergreen_pcie_gart_fini(rdev); |
| 3253 | rdev->accel_working = false; | 3385 | rdev->accel_working = false; |
| @@ -3274,7 +3406,7 @@ void evergreen_fini(struct radeon_device *rdev) | |||
| 3274 | r700_cp_fini(rdev); | 3406 | r700_cp_fini(rdev); |
| 3275 | r600_irq_fini(rdev); | 3407 | r600_irq_fini(rdev); |
| 3276 | radeon_wb_fini(rdev); | 3408 | radeon_wb_fini(rdev); |
| 3277 | r100_ib_fini(rdev); | 3409 | radeon_ib_pool_fini(rdev); |
| 3278 | radeon_irq_kms_fini(rdev); | 3410 | radeon_irq_kms_fini(rdev); |
| 3279 | evergreen_pcie_gart_fini(rdev); | 3411 | evergreen_pcie_gart_fini(rdev); |
| 3280 | r600_vram_scratch_fini(rdev); | 3412 | r600_vram_scratch_fini(rdev); |
| @@ -3289,7 +3421,8 @@ void evergreen_fini(struct radeon_device *rdev) | |||
| 3289 | 3421 | ||
| 3290 | void evergreen_pcie_gen2_enable(struct radeon_device *rdev) | 3422 | void evergreen_pcie_gen2_enable(struct radeon_device *rdev) |
| 3291 | { | 3423 | { |
| 3292 | u32 link_width_cntl, speed_cntl; | 3424 | u32 link_width_cntl, speed_cntl, mask; |
| 3425 | int ret; | ||
| 3293 | 3426 | ||
| 3294 | if (radeon_pcie_gen2 == 0) | 3427 | if (radeon_pcie_gen2 == 0) |
| 3295 | return; | 3428 | return; |
| @@ -3304,6 +3437,15 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev) | |||
| 3304 | if (ASIC_IS_X2(rdev)) | 3437 | if (ASIC_IS_X2(rdev)) |
| 3305 | return; | 3438 | return; |
| 3306 | 3439 | ||
| 3440 | ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); | ||
| 3441 | if (ret != 0) | ||
| 3442 | return; | ||
| 3443 | |||
| 3444 | if (!(mask & DRM_PCIE_SPEED_50)) | ||
| 3445 | return; | ||
| 3446 | |||
| 3447 | DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); | ||
| 3448 | |||
| 3307 | speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); | 3449 | speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); |
| 3308 | if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) || | 3450 | if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) || |
| 3309 | (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { | 3451 | (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { |
diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c index 1e96bd458cfd..89cb9feb5653 100644 --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c | |||
| @@ -622,7 +622,8 @@ int evergreen_blit_init(struct radeon_device *rdev) | |||
| 622 | rdev->r600_blit.primitives.draw_auto = draw_auto; | 622 | rdev->r600_blit.primitives.draw_auto = draw_auto; |
| 623 | rdev->r600_blit.primitives.set_default_state = set_default_state; | 623 | rdev->r600_blit.primitives.set_default_state = set_default_state; |
| 624 | 624 | ||
| 625 | rdev->r600_blit.ring_size_common = 55; /* shaders + def state */ | 625 | rdev->r600_blit.ring_size_common = 8; /* sync semaphore */ |
| 626 | rdev->r600_blit.ring_size_common += 55; /* shaders + def state */ | ||
| 626 | rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */ | 627 | rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */ |
| 627 | rdev->r600_blit.ring_size_common += 5; /* done copy */ | 628 | rdev->r600_blit.ring_size_common += 5; /* done copy */ |
| 628 | rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ | 629 | rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ |
| @@ -633,10 +634,6 @@ int evergreen_blit_init(struct radeon_device *rdev) | |||
| 633 | 634 | ||
| 634 | rdev->r600_blit.max_dim = 16384; | 635 | rdev->r600_blit.max_dim = 16384; |
| 635 | 636 | ||
| 636 | /* pin copy shader into vram if already initialized */ | ||
| 637 | if (rdev->r600_blit.shader_obj) | ||
| 638 | goto done; | ||
| 639 | |||
| 640 | rdev->r600_blit.state_offset = 0; | 637 | rdev->r600_blit.state_offset = 0; |
| 641 | 638 | ||
| 642 | if (rdev->family < CHIP_CAYMAN) | 639 | if (rdev->family < CHIP_CAYMAN) |
| @@ -667,11 +664,26 @@ int evergreen_blit_init(struct radeon_device *rdev) | |||
| 667 | obj_size += cayman_ps_size * 4; | 664 | obj_size += cayman_ps_size * 4; |
| 668 | obj_size = ALIGN(obj_size, 256); | 665 | obj_size = ALIGN(obj_size, 256); |
| 669 | 666 | ||
| 670 | r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, | 667 | /* pin copy shader into vram if not already initialized */ |
| 671 | NULL, &rdev->r600_blit.shader_obj); | 668 | if (!rdev->r600_blit.shader_obj) { |
| 672 | if (r) { | 669 | r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, |
| 673 | DRM_ERROR("evergreen failed to allocate shader\n"); | 670 | RADEON_GEM_DOMAIN_VRAM, |
| 674 | return r; | 671 | NULL, &rdev->r600_blit.shader_obj); |
| 672 | if (r) { | ||
| 673 | DRM_ERROR("evergreen failed to allocate shader\n"); | ||
| 674 | return r; | ||
| 675 | } | ||
| 676 | |||
| 677 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
| 678 | if (unlikely(r != 0)) | ||
| 679 | return r; | ||
| 680 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | ||
| 681 | &rdev->r600_blit.shader_gpu_addr); | ||
| 682 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
| 683 | if (r) { | ||
| 684 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | ||
| 685 | return r; | ||
| 686 | } | ||
| 675 | } | 687 | } |
| 676 | 688 | ||
| 677 | DRM_DEBUG("evergreen blit allocated bo %08x vs %08x ps %08x\n", | 689 | DRM_DEBUG("evergreen blit allocated bo %08x vs %08x ps %08x\n", |
| @@ -713,17 +725,6 @@ int evergreen_blit_init(struct radeon_device *rdev) | |||
| 713 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); | 725 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); |
| 714 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | 726 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); |
| 715 | 727 | ||
| 716 | done: | ||
| 717 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
| 718 | if (unlikely(r != 0)) | ||
| 719 | return r; | ||
| 720 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | ||
| 721 | &rdev->r600_blit.shader_gpu_addr); | ||
| 722 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
| 723 | if (r) { | ||
| 724 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | ||
| 725 | return r; | ||
| 726 | } | ||
| 727 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); | 728 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); |
| 728 | return 0; | 729 | return 0; |
| 729 | } | 730 | } |
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index b50b15c70498..d3bd098e4e19 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h | |||
| @@ -88,6 +88,10 @@ | |||
| 88 | #define CONFIG_MEMSIZE 0x5428 | 88 | #define CONFIG_MEMSIZE 0x5428 |
| 89 | 89 | ||
| 90 | #define CP_COHER_BASE 0x85F8 | 90 | #define CP_COHER_BASE 0x85F8 |
| 91 | #define CP_STALLED_STAT1 0x8674 | ||
| 92 | #define CP_STALLED_STAT2 0x8678 | ||
| 93 | #define CP_BUSY_STAT 0x867C | ||
| 94 | #define CP_STAT 0x8680 | ||
| 91 | #define CP_ME_CNTL 0x86D8 | 95 | #define CP_ME_CNTL 0x86D8 |
| 92 | #define CP_ME_HALT (1 << 28) | 96 | #define CP_ME_HALT (1 << 28) |
| 93 | #define CP_PFP_HALT (1 << 26) | 97 | #define CP_PFP_HALT (1 << 26) |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index b7bf18e40215..9945d86d9001 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
| @@ -850,11 +850,20 @@ void cayman_fence_ring_emit(struct radeon_device *rdev, | |||
| 850 | 850 | ||
| 851 | void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | 851 | void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) |
| 852 | { | 852 | { |
| 853 | struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; | 853 | struct radeon_ring *ring = &rdev->ring[ib->ring]; |
| 854 | 854 | ||
| 855 | /* set to DX10/11 mode */ | 855 | /* set to DX10/11 mode */ |
| 856 | radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); | 856 | radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); |
| 857 | radeon_ring_write(ring, 1); | 857 | radeon_ring_write(ring, 1); |
| 858 | |||
| 859 | if (ring->rptr_save_reg) { | ||
| 860 | uint32_t next_rptr = ring->wptr + 3 + 4 + 8; | ||
| 861 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
| 862 | radeon_ring_write(ring, ((ring->rptr_save_reg - | ||
| 863 | PACKET3_SET_CONFIG_REG_START) >> 2)); | ||
| 864 | radeon_ring_write(ring, next_rptr); | ||
| 865 | } | ||
| 866 | |||
| 858 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); | 867 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
| 859 | radeon_ring_write(ring, | 868 | radeon_ring_write(ring, |
| 860 | #ifdef __BIG_ENDIAN | 869 | #ifdef __BIG_ENDIAN |
| @@ -981,16 +990,41 @@ static int cayman_cp_start(struct radeon_device *rdev) | |||
| 981 | 990 | ||
| 982 | static void cayman_cp_fini(struct radeon_device *rdev) | 991 | static void cayman_cp_fini(struct radeon_device *rdev) |
| 983 | { | 992 | { |
| 993 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | ||
| 984 | cayman_cp_enable(rdev, false); | 994 | cayman_cp_enable(rdev, false); |
| 985 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | 995 | radeon_ring_fini(rdev, ring); |
| 996 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 986 | } | 997 | } |
| 987 | 998 | ||
| 988 | int cayman_cp_resume(struct radeon_device *rdev) | 999 | int cayman_cp_resume(struct radeon_device *rdev) |
| 989 | { | 1000 | { |
| 1001 | static const int ridx[] = { | ||
| 1002 | RADEON_RING_TYPE_GFX_INDEX, | ||
| 1003 | CAYMAN_RING_TYPE_CP1_INDEX, | ||
| 1004 | CAYMAN_RING_TYPE_CP2_INDEX | ||
| 1005 | }; | ||
| 1006 | static const unsigned cp_rb_cntl[] = { | ||
| 1007 | CP_RB0_CNTL, | ||
| 1008 | CP_RB1_CNTL, | ||
| 1009 | CP_RB2_CNTL, | ||
| 1010 | }; | ||
| 1011 | static const unsigned cp_rb_rptr_addr[] = { | ||
| 1012 | CP_RB0_RPTR_ADDR, | ||
| 1013 | CP_RB1_RPTR_ADDR, | ||
| 1014 | CP_RB2_RPTR_ADDR | ||
| 1015 | }; | ||
| 1016 | static const unsigned cp_rb_rptr_addr_hi[] = { | ||
| 1017 | CP_RB0_RPTR_ADDR_HI, | ||
| 1018 | CP_RB1_RPTR_ADDR_HI, | ||
| 1019 | CP_RB2_RPTR_ADDR_HI | ||
| 1020 | }; | ||
| 1021 | static const unsigned cp_rb_base[] = { | ||
| 1022 | CP_RB0_BASE, | ||
| 1023 | CP_RB1_BASE, | ||
| 1024 | CP_RB2_BASE | ||
| 1025 | }; | ||
| 990 | struct radeon_ring *ring; | 1026 | struct radeon_ring *ring; |
| 991 | u32 tmp; | 1027 | int i, r; |
| 992 | u32 rb_bufsz; | ||
| 993 | int r; | ||
| 994 | 1028 | ||
| 995 | /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ | 1029 | /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ |
| 996 | WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | | 1030 | WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | |
| @@ -1012,91 +1046,47 @@ int cayman_cp_resume(struct radeon_device *rdev) | |||
| 1012 | 1046 | ||
| 1013 | WREG32(CP_DEBUG, (1 << 27)); | 1047 | WREG32(CP_DEBUG, (1 << 27)); |
| 1014 | 1048 | ||
| 1015 | /* ring 0 - compute and gfx */ | ||
| 1016 | /* Set ring buffer size */ | ||
| 1017 | ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | ||
| 1018 | rb_bufsz = drm_order(ring->ring_size / 8); | ||
| 1019 | tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | ||
| 1020 | #ifdef __BIG_ENDIAN | ||
| 1021 | tmp |= BUF_SWAP_32BIT; | ||
| 1022 | #endif | ||
| 1023 | WREG32(CP_RB0_CNTL, tmp); | ||
| 1024 | |||
| 1025 | /* Initialize the ring buffer's read and write pointers */ | ||
| 1026 | WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA); | ||
| 1027 | ring->wptr = 0; | ||
| 1028 | WREG32(CP_RB0_WPTR, ring->wptr); | ||
| 1029 | |||
| 1030 | /* set the wb address wether it's enabled or not */ | 1049 | /* set the wb address wether it's enabled or not */ |
| 1031 | WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); | ||
| 1032 | WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); | ||
| 1033 | WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); | 1050 | WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); |
| 1051 | WREG32(SCRATCH_UMSK, 0xff); | ||
| 1034 | 1052 | ||
| 1035 | if (rdev->wb.enabled) | 1053 | for (i = 0; i < 3; ++i) { |
| 1036 | WREG32(SCRATCH_UMSK, 0xff); | 1054 | uint32_t rb_cntl; |
| 1037 | else { | 1055 | uint64_t addr; |
| 1038 | tmp |= RB_NO_UPDATE; | ||
| 1039 | WREG32(SCRATCH_UMSK, 0); | ||
| 1040 | } | ||
| 1041 | 1056 | ||
| 1042 | mdelay(1); | 1057 | /* Set ring buffer size */ |
| 1043 | WREG32(CP_RB0_CNTL, tmp); | 1058 | ring = &rdev->ring[ridx[i]]; |
| 1044 | 1059 | rb_cntl = drm_order(ring->ring_size / 8); | |
| 1045 | WREG32(CP_RB0_BASE, ring->gpu_addr >> 8); | 1060 | rb_cntl |= drm_order(RADEON_GPU_PAGE_SIZE/8) << 8; |
| 1046 | |||
| 1047 | ring->rptr = RREG32(CP_RB0_RPTR); | ||
| 1048 | |||
| 1049 | /* ring1 - compute only */ | ||
| 1050 | /* Set ring buffer size */ | ||
| 1051 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; | ||
| 1052 | rb_bufsz = drm_order(ring->ring_size / 8); | ||
| 1053 | tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | ||
| 1054 | #ifdef __BIG_ENDIAN | 1061 | #ifdef __BIG_ENDIAN |
| 1055 | tmp |= BUF_SWAP_32BIT; | 1062 | rb_cntl |= BUF_SWAP_32BIT; |
| 1056 | #endif | 1063 | #endif |
| 1057 | WREG32(CP_RB1_CNTL, tmp); | 1064 | WREG32(cp_rb_cntl[i], rb_cntl); |
| 1058 | |||
| 1059 | /* Initialize the ring buffer's read and write pointers */ | ||
| 1060 | WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA); | ||
| 1061 | ring->wptr = 0; | ||
| 1062 | WREG32(CP_RB1_WPTR, ring->wptr); | ||
| 1063 | |||
| 1064 | /* set the wb address wether it's enabled or not */ | ||
| 1065 | WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC); | ||
| 1066 | WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF); | ||
| 1067 | |||
| 1068 | mdelay(1); | ||
| 1069 | WREG32(CP_RB1_CNTL, tmp); | ||
| 1070 | 1065 | ||
| 1071 | WREG32(CP_RB1_BASE, ring->gpu_addr >> 8); | 1066 | /* set the wb address wether it's enabled or not */ |
| 1072 | 1067 | addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET; | |
| 1073 | ring->rptr = RREG32(CP_RB1_RPTR); | 1068 | WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC); |
| 1074 | 1069 | WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF); | |
| 1075 | /* ring2 - compute only */ | 1070 | } |
| 1076 | /* Set ring buffer size */ | ||
| 1077 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; | ||
| 1078 | rb_bufsz = drm_order(ring->ring_size / 8); | ||
| 1079 | tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | ||
| 1080 | #ifdef __BIG_ENDIAN | ||
| 1081 | tmp |= BUF_SWAP_32BIT; | ||
| 1082 | #endif | ||
| 1083 | WREG32(CP_RB2_CNTL, tmp); | ||
| 1084 | |||
| 1085 | /* Initialize the ring buffer's read and write pointers */ | ||
| 1086 | WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA); | ||
| 1087 | ring->wptr = 0; | ||
| 1088 | WREG32(CP_RB2_WPTR, ring->wptr); | ||
| 1089 | 1071 | ||
| 1090 | /* set the wb address wether it's enabled or not */ | 1072 | /* set the rb base addr, this causes an internal reset of ALL rings */ |
| 1091 | WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC); | 1073 | for (i = 0; i < 3; ++i) { |
| 1092 | WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF); | 1074 | ring = &rdev->ring[ridx[i]]; |
| 1075 | WREG32(cp_rb_base[i], ring->gpu_addr >> 8); | ||
| 1076 | } | ||
| 1093 | 1077 | ||
| 1094 | mdelay(1); | 1078 | for (i = 0; i < 3; ++i) { |
| 1095 | WREG32(CP_RB2_CNTL, tmp); | 1079 | /* Initialize the ring buffer's read and write pointers */ |
| 1080 | ring = &rdev->ring[ridx[i]]; | ||
| 1081 | WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA); | ||
| 1096 | 1082 | ||
| 1097 | WREG32(CP_RB2_BASE, ring->gpu_addr >> 8); | 1083 | ring->rptr = ring->wptr = 0; |
| 1084 | WREG32(ring->rptr_reg, ring->rptr); | ||
| 1085 | WREG32(ring->wptr_reg, ring->wptr); | ||
| 1098 | 1086 | ||
| 1099 | ring->rptr = RREG32(CP_RB2_RPTR); | 1087 | mdelay(1); |
| 1088 | WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA); | ||
| 1089 | } | ||
| 1100 | 1090 | ||
| 1101 | /* start the rings */ | 1091 | /* start the rings */ |
| 1102 | cayman_cp_start(rdev); | 1092 | cayman_cp_start(rdev); |
| @@ -1132,6 +1122,14 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev) | |||
| 1132 | RREG32(GRBM_STATUS_SE1)); | 1122 | RREG32(GRBM_STATUS_SE1)); |
| 1133 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | 1123 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", |
| 1134 | RREG32(SRBM_STATUS)); | 1124 | RREG32(SRBM_STATUS)); |
| 1125 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 1126 | RREG32(CP_STALLED_STAT1)); | ||
| 1127 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 1128 | RREG32(CP_STALLED_STAT2)); | ||
| 1129 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 1130 | RREG32(CP_BUSY_STAT)); | ||
| 1131 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 1132 | RREG32(CP_STAT)); | ||
| 1135 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n", | 1133 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n", |
| 1136 | RREG32(0x14F8)); | 1134 | RREG32(0x14F8)); |
| 1137 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n", | 1135 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n", |
| @@ -1180,6 +1178,14 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev) | |||
| 1180 | RREG32(GRBM_STATUS_SE1)); | 1178 | RREG32(GRBM_STATUS_SE1)); |
| 1181 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | 1179 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", |
| 1182 | RREG32(SRBM_STATUS)); | 1180 | RREG32(SRBM_STATUS)); |
| 1181 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 1182 | RREG32(CP_STALLED_STAT1)); | ||
| 1183 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 1184 | RREG32(CP_STALLED_STAT2)); | ||
| 1185 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 1186 | RREG32(CP_BUSY_STAT)); | ||
| 1187 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 1188 | RREG32(CP_STAT)); | ||
| 1183 | evergreen_mc_resume(rdev, &save); | 1189 | evergreen_mc_resume(rdev, &save); |
| 1184 | return 0; | 1190 | return 0; |
| 1185 | } | 1191 | } |
| @@ -1291,17 +1297,17 @@ static int cayman_startup(struct radeon_device *rdev) | |||
| 1291 | if (r) | 1297 | if (r) |
| 1292 | return r; | 1298 | return r; |
| 1293 | 1299 | ||
| 1294 | r = radeon_ib_pool_start(rdev); | 1300 | r = radeon_ib_pool_init(rdev); |
| 1295 | if (r) | 1301 | if (r) { |
| 1296 | return r; | 1302 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 1297 | |||
| 1298 | r = radeon_ib_ring_tests(rdev); | ||
| 1299 | if (r) | ||
| 1300 | return r; | 1303 | return r; |
| 1304 | } | ||
| 1301 | 1305 | ||
| 1302 | r = radeon_vm_manager_start(rdev); | 1306 | r = radeon_vm_manager_init(rdev); |
| 1303 | if (r) | 1307 | if (r) { |
| 1308 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
| 1304 | return r; | 1309 | return r; |
| 1310 | } | ||
| 1305 | 1311 | ||
| 1306 | r = r600_audio_init(rdev); | 1312 | r = r600_audio_init(rdev); |
| 1307 | if (r) | 1313 | if (r) |
| @@ -1334,10 +1340,6 @@ int cayman_resume(struct radeon_device *rdev) | |||
| 1334 | int cayman_suspend(struct radeon_device *rdev) | 1340 | int cayman_suspend(struct radeon_device *rdev) |
| 1335 | { | 1341 | { |
| 1336 | r600_audio_fini(rdev); | 1342 | r600_audio_fini(rdev); |
| 1337 | /* FIXME: we should wait for ring to be empty */ | ||
| 1338 | radeon_ib_pool_suspend(rdev); | ||
| 1339 | radeon_vm_manager_suspend(rdev); | ||
| 1340 | r600_blit_suspend(rdev); | ||
| 1341 | cayman_cp_enable(rdev, false); | 1343 | cayman_cp_enable(rdev, false); |
| 1342 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 1344 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
| 1343 | evergreen_irq_suspend(rdev); | 1345 | evergreen_irq_suspend(rdev); |
| @@ -1413,17 +1415,7 @@ int cayman_init(struct radeon_device *rdev) | |||
| 1413 | if (r) | 1415 | if (r) |
| 1414 | return r; | 1416 | return r; |
| 1415 | 1417 | ||
| 1416 | r = radeon_ib_pool_init(rdev); | ||
| 1417 | rdev->accel_working = true; | 1418 | rdev->accel_working = true; |
| 1418 | if (r) { | ||
| 1419 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 1420 | rdev->accel_working = false; | ||
| 1421 | } | ||
| 1422 | r = radeon_vm_manager_init(rdev); | ||
| 1423 | if (r) { | ||
| 1424 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | r = cayman_startup(rdev); | 1419 | r = cayman_startup(rdev); |
| 1428 | if (r) { | 1420 | if (r) { |
| 1429 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 1421 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
| @@ -1432,7 +1424,7 @@ int cayman_init(struct radeon_device *rdev) | |||
| 1432 | if (rdev->flags & RADEON_IS_IGP) | 1424 | if (rdev->flags & RADEON_IS_IGP) |
| 1433 | si_rlc_fini(rdev); | 1425 | si_rlc_fini(rdev); |
| 1434 | radeon_wb_fini(rdev); | 1426 | radeon_wb_fini(rdev); |
| 1435 | r100_ib_fini(rdev); | 1427 | radeon_ib_pool_fini(rdev); |
| 1436 | radeon_vm_manager_fini(rdev); | 1428 | radeon_vm_manager_fini(rdev); |
| 1437 | radeon_irq_kms_fini(rdev); | 1429 | radeon_irq_kms_fini(rdev); |
| 1438 | cayman_pcie_gart_fini(rdev); | 1430 | cayman_pcie_gart_fini(rdev); |
| @@ -1463,7 +1455,7 @@ void cayman_fini(struct radeon_device *rdev) | |||
| 1463 | si_rlc_fini(rdev); | 1455 | si_rlc_fini(rdev); |
| 1464 | radeon_wb_fini(rdev); | 1456 | radeon_wb_fini(rdev); |
| 1465 | radeon_vm_manager_fini(rdev); | 1457 | radeon_vm_manager_fini(rdev); |
| 1466 | r100_ib_fini(rdev); | 1458 | radeon_ib_pool_fini(rdev); |
| 1467 | radeon_irq_kms_fini(rdev); | 1459 | radeon_irq_kms_fini(rdev); |
| 1468 | cayman_pcie_gart_fini(rdev); | 1460 | cayman_pcie_gart_fini(rdev); |
| 1469 | r600_vram_scratch_fini(rdev); | 1461 | r600_vram_scratch_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index a0b98066e207..870db340d377 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h | |||
| @@ -236,6 +236,10 @@ | |||
| 236 | #define CP_SEM_WAIT_TIMER 0x85BC | 236 | #define CP_SEM_WAIT_TIMER 0x85BC |
| 237 | #define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 | 237 | #define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 |
| 238 | #define CP_COHER_CNTL2 0x85E8 | 238 | #define CP_COHER_CNTL2 0x85E8 |
| 239 | #define CP_STALLED_STAT1 0x8674 | ||
| 240 | #define CP_STALLED_STAT2 0x8678 | ||
| 241 | #define CP_BUSY_STAT 0x867C | ||
| 242 | #define CP_STAT 0x8680 | ||
| 239 | #define CP_ME_CNTL 0x86D8 | 243 | #define CP_ME_CNTL 0x86D8 |
| 240 | #define CP_ME_HALT (1 << 28) | 244 | #define CP_ME_HALT (1 << 28) |
| 241 | #define CP_PFP_HALT (1 << 26) | 245 | #define CP_PFP_HALT (1 << 26) |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index fb44e7e49083..8acb34fd3fd5 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
| @@ -65,6 +65,19 @@ MODULE_FIRMWARE(FIRMWARE_R520); | |||
| 65 | 65 | ||
| 66 | #include "r100_track.h" | 66 | #include "r100_track.h" |
| 67 | 67 | ||
| 68 | /* This files gather functions specifics to: | ||
| 69 | * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 | ||
| 70 | * and others in some cases. | ||
| 71 | */ | ||
| 72 | |||
| 73 | /** | ||
| 74 | * r100_wait_for_vblank - vblank wait asic callback. | ||
| 75 | * | ||
| 76 | * @rdev: radeon_device pointer | ||
| 77 | * @crtc: crtc to wait for vblank on | ||
| 78 | * | ||
| 79 | * Wait for vblank on the requested crtc (r1xx-r4xx). | ||
| 80 | */ | ||
| 68 | void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) | 81 | void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) |
| 69 | { | 82 | { |
| 70 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; | 83 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; |
| @@ -99,128 +112,49 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) | |||
| 99 | } | 112 | } |
| 100 | } | 113 | } |
| 101 | 114 | ||
| 102 | /* This files gather functions specifics to: | 115 | /** |
| 103 | * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 | 116 | * r100_pre_page_flip - pre-pageflip callback. |
| 117 | * | ||
| 118 | * @rdev: radeon_device pointer | ||
| 119 | * @crtc: crtc to prepare for pageflip on | ||
| 120 | * | ||
| 121 | * Pre-pageflip callback (r1xx-r4xx). | ||
| 122 | * Enables the pageflip irq (vblank irq). | ||
| 104 | */ | 123 | */ |
| 105 | |||
| 106 | int r100_reloc_pitch_offset(struct radeon_cs_parser *p, | ||
| 107 | struct radeon_cs_packet *pkt, | ||
| 108 | unsigned idx, | ||
| 109 | unsigned reg) | ||
| 110 | { | ||
| 111 | int r; | ||
| 112 | u32 tile_flags = 0; | ||
| 113 | u32 tmp; | ||
| 114 | struct radeon_cs_reloc *reloc; | ||
| 115 | u32 value; | ||
| 116 | |||
| 117 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 118 | if (r) { | ||
| 119 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
| 120 | idx, reg); | ||
| 121 | r100_cs_dump_packet(p, pkt); | ||
| 122 | return r; | ||
| 123 | } | ||
| 124 | |||
| 125 | value = radeon_get_ib_value(p, idx); | ||
| 126 | tmp = value & 0x003fffff; | ||
| 127 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); | ||
| 128 | |||
| 129 | if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { | ||
| 130 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
| 131 | tile_flags |= RADEON_DST_TILE_MACRO; | ||
| 132 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { | ||
| 133 | if (reg == RADEON_SRC_PITCH_OFFSET) { | ||
| 134 | DRM_ERROR("Cannot src blit from microtiled surface\n"); | ||
| 135 | r100_cs_dump_packet(p, pkt); | ||
| 136 | return -EINVAL; | ||
| 137 | } | ||
| 138 | tile_flags |= RADEON_DST_TILE_MICRO; | ||
| 139 | } | ||
| 140 | |||
| 141 | tmp |= tile_flags; | ||
| 142 | p->ib.ptr[idx] = (value & 0x3fc00000) | tmp; | ||
| 143 | } else | ||
| 144 | p->ib.ptr[idx] = (value & 0xffc00000) | tmp; | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, | ||
| 149 | struct radeon_cs_packet *pkt, | ||
| 150 | int idx) | ||
| 151 | { | ||
| 152 | unsigned c, i; | ||
| 153 | struct radeon_cs_reloc *reloc; | ||
| 154 | struct r100_cs_track *track; | ||
| 155 | int r = 0; | ||
| 156 | volatile uint32_t *ib; | ||
| 157 | u32 idx_value; | ||
| 158 | |||
| 159 | ib = p->ib.ptr; | ||
| 160 | track = (struct r100_cs_track *)p->track; | ||
| 161 | c = radeon_get_ib_value(p, idx++) & 0x1F; | ||
| 162 | if (c > 16) { | ||
| 163 | DRM_ERROR("Only 16 vertex buffers are allowed %d\n", | ||
| 164 | pkt->opcode); | ||
| 165 | r100_cs_dump_packet(p, pkt); | ||
| 166 | return -EINVAL; | ||
| 167 | } | ||
| 168 | track->num_arrays = c; | ||
| 169 | for (i = 0; i < (c - 1); i+=2, idx+=3) { | ||
| 170 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 171 | if (r) { | ||
| 172 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 173 | pkt->opcode); | ||
| 174 | r100_cs_dump_packet(p, pkt); | ||
| 175 | return r; | ||
| 176 | } | ||
| 177 | idx_value = radeon_get_ib_value(p, idx); | ||
| 178 | ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); | ||
| 179 | |||
| 180 | track->arrays[i + 0].esize = idx_value >> 8; | ||
| 181 | track->arrays[i + 0].robj = reloc->robj; | ||
| 182 | track->arrays[i + 0].esize &= 0x7F; | ||
| 183 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 184 | if (r) { | ||
| 185 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 186 | pkt->opcode); | ||
| 187 | r100_cs_dump_packet(p, pkt); | ||
| 188 | return r; | ||
| 189 | } | ||
| 190 | ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); | ||
| 191 | track->arrays[i + 1].robj = reloc->robj; | ||
| 192 | track->arrays[i + 1].esize = idx_value >> 24; | ||
| 193 | track->arrays[i + 1].esize &= 0x7F; | ||
| 194 | } | ||
| 195 | if (c & 1) { | ||
| 196 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 197 | if (r) { | ||
| 198 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 199 | pkt->opcode); | ||
| 200 | r100_cs_dump_packet(p, pkt); | ||
| 201 | return r; | ||
| 202 | } | ||
| 203 | idx_value = radeon_get_ib_value(p, idx); | ||
| 204 | ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); | ||
| 205 | track->arrays[i + 0].robj = reloc->robj; | ||
| 206 | track->arrays[i + 0].esize = idx_value >> 8; | ||
| 207 | track->arrays[i + 0].esize &= 0x7F; | ||
| 208 | } | ||
| 209 | return r; | ||
| 210 | } | ||
| 211 | |||
| 212 | void r100_pre_page_flip(struct radeon_device *rdev, int crtc) | 124 | void r100_pre_page_flip(struct radeon_device *rdev, int crtc) |
| 213 | { | 125 | { |
| 214 | /* enable the pflip int */ | 126 | /* enable the pflip int */ |
| 215 | radeon_irq_kms_pflip_irq_get(rdev, crtc); | 127 | radeon_irq_kms_pflip_irq_get(rdev, crtc); |
| 216 | } | 128 | } |
| 217 | 129 | ||
| 130 | /** | ||
| 131 | * r100_post_page_flip - pos-pageflip callback. | ||
| 132 | * | ||
| 133 | * @rdev: radeon_device pointer | ||
| 134 | * @crtc: crtc to cleanup pageflip on | ||
| 135 | * | ||
| 136 | * Post-pageflip callback (r1xx-r4xx). | ||
| 137 | * Disables the pageflip irq (vblank irq). | ||
| 138 | */ | ||
| 218 | void r100_post_page_flip(struct radeon_device *rdev, int crtc) | 139 | void r100_post_page_flip(struct radeon_device *rdev, int crtc) |
| 219 | { | 140 | { |
| 220 | /* disable the pflip int */ | 141 | /* disable the pflip int */ |
| 221 | radeon_irq_kms_pflip_irq_put(rdev, crtc); | 142 | radeon_irq_kms_pflip_irq_put(rdev, crtc); |
| 222 | } | 143 | } |
| 223 | 144 | ||
| 145 | /** | ||
| 146 | * r100_page_flip - pageflip callback. | ||
| 147 | * | ||
| 148 | * @rdev: radeon_device pointer | ||
| 149 | * @crtc_id: crtc to cleanup pageflip on | ||
| 150 | * @crtc_base: new address of the crtc (GPU MC address) | ||
| 151 | * | ||
| 152 | * Does the actual pageflip (r1xx-r4xx). | ||
| 153 | * During vblank we take the crtc lock and wait for the update_pending | ||
| 154 | * bit to go high, when it does, we release the lock, and allow the | ||
| 155 | * double buffered update to take place. | ||
| 156 | * Returns the current update pending status. | ||
| 157 | */ | ||
| 224 | u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | 158 | u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) |
| 225 | { | 159 | { |
| 226 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 160 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
| @@ -247,6 +181,15 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | |||
| 247 | return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; | 181 | return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; |
| 248 | } | 182 | } |
| 249 | 183 | ||
| 184 | /** | ||
| 185 | * r100_pm_get_dynpm_state - look up dynpm power state callback. | ||
| 186 | * | ||
| 187 | * @rdev: radeon_device pointer | ||
| 188 | * | ||
| 189 | * Look up the optimal power state based on the | ||
| 190 | * current state of the GPU (r1xx-r5xx). | ||
| 191 | * Used for dynpm only. | ||
| 192 | */ | ||
| 250 | void r100_pm_get_dynpm_state(struct radeon_device *rdev) | 193 | void r100_pm_get_dynpm_state(struct radeon_device *rdev) |
| 251 | { | 194 | { |
| 252 | int i; | 195 | int i; |
| @@ -329,6 +272,15 @@ void r100_pm_get_dynpm_state(struct radeon_device *rdev) | |||
| 329 | pcie_lanes); | 272 | pcie_lanes); |
| 330 | } | 273 | } |
| 331 | 274 | ||
| 275 | /** | ||
| 276 | * r100_pm_init_profile - Initialize power profiles callback. | ||
| 277 | * | ||
| 278 | * @rdev: radeon_device pointer | ||
| 279 | * | ||
| 280 | * Initialize the power states used in profile mode | ||
| 281 | * (r1xx-r3xx). | ||
| 282 | * Used for profile mode only. | ||
| 283 | */ | ||
| 332 | void r100_pm_init_profile(struct radeon_device *rdev) | 284 | void r100_pm_init_profile(struct radeon_device *rdev) |
| 333 | { | 285 | { |
| 334 | /* default */ | 286 | /* default */ |
| @@ -368,6 +320,14 @@ void r100_pm_init_profile(struct radeon_device *rdev) | |||
| 368 | rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; | 320 | rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; |
| 369 | } | 321 | } |
| 370 | 322 | ||
| 323 | /** | ||
| 324 | * r100_pm_misc - set additional pm hw parameters callback. | ||
| 325 | * | ||
| 326 | * @rdev: radeon_device pointer | ||
| 327 | * | ||
| 328 | * Set non-clock parameters associated with a power state | ||
| 329 | * (voltage, pcie lanes, etc.) (r1xx-r4xx). | ||
| 330 | */ | ||
| 371 | void r100_pm_misc(struct radeon_device *rdev) | 331 | void r100_pm_misc(struct radeon_device *rdev) |
| 372 | { | 332 | { |
| 373 | int requested_index = rdev->pm.requested_power_state_index; | 333 | int requested_index = rdev->pm.requested_power_state_index; |
| @@ -459,6 +419,13 @@ void r100_pm_misc(struct radeon_device *rdev) | |||
| 459 | } | 419 | } |
| 460 | } | 420 | } |
| 461 | 421 | ||
| 422 | /** | ||
| 423 | * r100_pm_prepare - pre-power state change callback. | ||
| 424 | * | ||
| 425 | * @rdev: radeon_device pointer | ||
| 426 | * | ||
| 427 | * Prepare for a power state change (r1xx-r4xx). | ||
| 428 | */ | ||
| 462 | void r100_pm_prepare(struct radeon_device *rdev) | 429 | void r100_pm_prepare(struct radeon_device *rdev) |
| 463 | { | 430 | { |
| 464 | struct drm_device *ddev = rdev->ddev; | 431 | struct drm_device *ddev = rdev->ddev; |
| @@ -483,6 +450,13 @@ void r100_pm_prepare(struct radeon_device *rdev) | |||
| 483 | } | 450 | } |
| 484 | } | 451 | } |
| 485 | 452 | ||
| 453 | /** | ||
| 454 | * r100_pm_finish - post-power state change callback. | ||
| 455 | * | ||
| 456 | * @rdev: radeon_device pointer | ||
| 457 | * | ||
| 458 | * Clean up after a power state change (r1xx-r4xx). | ||
| 459 | */ | ||
| 486 | void r100_pm_finish(struct radeon_device *rdev) | 460 | void r100_pm_finish(struct radeon_device *rdev) |
| 487 | { | 461 | { |
| 488 | struct drm_device *ddev = rdev->ddev; | 462 | struct drm_device *ddev = rdev->ddev; |
| @@ -507,6 +481,14 @@ void r100_pm_finish(struct radeon_device *rdev) | |||
| 507 | } | 481 | } |
| 508 | } | 482 | } |
| 509 | 483 | ||
| 484 | /** | ||
| 485 | * r100_gui_idle - gui idle callback. | ||
| 486 | * | ||
| 487 | * @rdev: radeon_device pointer | ||
| 488 | * | ||
| 489 | * Check of the GUI (2D/3D engines) are idle (r1xx-r5xx). | ||
| 490 | * Returns true if idle, false if not. | ||
| 491 | */ | ||
| 510 | bool r100_gui_idle(struct radeon_device *rdev) | 492 | bool r100_gui_idle(struct radeon_device *rdev) |
| 511 | { | 493 | { |
| 512 | if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) | 494 | if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) |
| @@ -516,6 +498,15 @@ bool r100_gui_idle(struct radeon_device *rdev) | |||
| 516 | } | 498 | } |
| 517 | 499 | ||
| 518 | /* hpd for digital panel detect/disconnect */ | 500 | /* hpd for digital panel detect/disconnect */ |
| 501 | /** | ||
| 502 | * r100_hpd_sense - hpd sense callback. | ||
| 503 | * | ||
| 504 | * @rdev: radeon_device pointer | ||
| 505 | * @hpd: hpd (hotplug detect) pin | ||
| 506 | * | ||
| 507 | * Checks if a digital monitor is connected (r1xx-r4xx). | ||
| 508 | * Returns true if connected, false if not connected. | ||
| 509 | */ | ||
| 519 | bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | 510 | bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) |
| 520 | { | 511 | { |
| 521 | bool connected = false; | 512 | bool connected = false; |
| @@ -535,6 +526,14 @@ bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | |||
| 535 | return connected; | 526 | return connected; |
| 536 | } | 527 | } |
| 537 | 528 | ||
| 529 | /** | ||
| 530 | * r100_hpd_set_polarity - hpd set polarity callback. | ||
| 531 | * | ||
| 532 | * @rdev: radeon_device pointer | ||
| 533 | * @hpd: hpd (hotplug detect) pin | ||
| 534 | * | ||
| 535 | * Set the polarity of the hpd pin (r1xx-r4xx). | ||
| 536 | */ | ||
| 538 | void r100_hpd_set_polarity(struct radeon_device *rdev, | 537 | void r100_hpd_set_polarity(struct radeon_device *rdev, |
| 539 | enum radeon_hpd_id hpd) | 538 | enum radeon_hpd_id hpd) |
| 540 | { | 539 | { |
| @@ -563,47 +562,47 @@ void r100_hpd_set_polarity(struct radeon_device *rdev, | |||
| 563 | } | 562 | } |
| 564 | } | 563 | } |
| 565 | 564 | ||
| 565 | /** | ||
| 566 | * r100_hpd_init - hpd setup callback. | ||
| 567 | * | ||
| 568 | * @rdev: radeon_device pointer | ||
| 569 | * | ||
| 570 | * Setup the hpd pins used by the card (r1xx-r4xx). | ||
| 571 | * Set the polarity, and enable the hpd interrupts. | ||
| 572 | */ | ||
| 566 | void r100_hpd_init(struct radeon_device *rdev) | 573 | void r100_hpd_init(struct radeon_device *rdev) |
| 567 | { | 574 | { |
| 568 | struct drm_device *dev = rdev->ddev; | 575 | struct drm_device *dev = rdev->ddev; |
| 569 | struct drm_connector *connector; | 576 | struct drm_connector *connector; |
| 577 | unsigned enable = 0; | ||
| 570 | 578 | ||
| 571 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 579 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 572 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 580 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 573 | switch (radeon_connector->hpd.hpd) { | 581 | enable |= 1 << radeon_connector->hpd.hpd; |
| 574 | case RADEON_HPD_1: | ||
| 575 | rdev->irq.hpd[0] = true; | ||
| 576 | break; | ||
| 577 | case RADEON_HPD_2: | ||
| 578 | rdev->irq.hpd[1] = true; | ||
| 579 | break; | ||
| 580 | default: | ||
| 581 | break; | ||
| 582 | } | ||
| 583 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 582 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
| 584 | } | 583 | } |
| 585 | if (rdev->irq.installed) | 584 | radeon_irq_kms_enable_hpd(rdev, enable); |
| 586 | r100_irq_set(rdev); | ||
| 587 | } | 585 | } |
| 588 | 586 | ||
| 587 | /** | ||
| 588 | * r100_hpd_fini - hpd tear down callback. | ||
| 589 | * | ||
| 590 | * @rdev: radeon_device pointer | ||
| 591 | * | ||
| 592 | * Tear down the hpd pins used by the card (r1xx-r4xx). | ||
| 593 | * Disable the hpd interrupts. | ||
| 594 | */ | ||
| 589 | void r100_hpd_fini(struct radeon_device *rdev) | 595 | void r100_hpd_fini(struct radeon_device *rdev) |
| 590 | { | 596 | { |
| 591 | struct drm_device *dev = rdev->ddev; | 597 | struct drm_device *dev = rdev->ddev; |
| 592 | struct drm_connector *connector; | 598 | struct drm_connector *connector; |
| 599 | unsigned disable = 0; | ||
| 593 | 600 | ||
| 594 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 601 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 595 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 602 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 596 | switch (radeon_connector->hpd.hpd) { | 603 | disable |= 1 << radeon_connector->hpd.hpd; |
| 597 | case RADEON_HPD_1: | ||
| 598 | rdev->irq.hpd[0] = false; | ||
| 599 | break; | ||
| 600 | case RADEON_HPD_2: | ||
| 601 | rdev->irq.hpd[1] = false; | ||
| 602 | break; | ||
| 603 | default: | ||
| 604 | break; | ||
| 605 | } | ||
| 606 | } | 604 | } |
| 605 | radeon_irq_kms_disable_hpd(rdev, disable); | ||
| 607 | } | 606 | } |
| 608 | 607 | ||
| 609 | /* | 608 | /* |
| @@ -635,15 +634,6 @@ int r100_pci_gart_init(struct radeon_device *rdev) | |||
| 635 | return radeon_gart_table_ram_alloc(rdev); | 634 | return radeon_gart_table_ram_alloc(rdev); |
| 636 | } | 635 | } |
| 637 | 636 | ||
| 638 | /* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ | ||
| 639 | void r100_enable_bm(struct radeon_device *rdev) | ||
| 640 | { | ||
| 641 | uint32_t tmp; | ||
| 642 | /* Enable bus mastering */ | ||
| 643 | tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; | ||
| 644 | WREG32(RADEON_BUS_CNTL, tmp); | ||
| 645 | } | ||
| 646 | |||
| 647 | int r100_pci_gart_enable(struct radeon_device *rdev) | 637 | int r100_pci_gart_enable(struct radeon_device *rdev) |
| 648 | { | 638 | { |
| 649 | uint32_t tmp; | 639 | uint32_t tmp; |
| @@ -705,18 +695,18 @@ int r100_irq_set(struct radeon_device *rdev) | |||
| 705 | WREG32(R_000040_GEN_INT_CNTL, 0); | 695 | WREG32(R_000040_GEN_INT_CNTL, 0); |
| 706 | return -EINVAL; | 696 | return -EINVAL; |
| 707 | } | 697 | } |
| 708 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 698 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 709 | tmp |= RADEON_SW_INT_ENABLE; | 699 | tmp |= RADEON_SW_INT_ENABLE; |
| 710 | } | 700 | } |
| 711 | if (rdev->irq.gui_idle) { | 701 | if (rdev->irq.gui_idle) { |
| 712 | tmp |= RADEON_GUI_IDLE_MASK; | 702 | tmp |= RADEON_GUI_IDLE_MASK; |
| 713 | } | 703 | } |
| 714 | if (rdev->irq.crtc_vblank_int[0] || | 704 | if (rdev->irq.crtc_vblank_int[0] || |
| 715 | rdev->irq.pflip[0]) { | 705 | atomic_read(&rdev->irq.pflip[0])) { |
| 716 | tmp |= RADEON_CRTC_VBLANK_MASK; | 706 | tmp |= RADEON_CRTC_VBLANK_MASK; |
| 717 | } | 707 | } |
| 718 | if (rdev->irq.crtc_vblank_int[1] || | 708 | if (rdev->irq.crtc_vblank_int[1] || |
| 719 | rdev->irq.pflip[1]) { | 709 | atomic_read(&rdev->irq.pflip[1])) { |
| 720 | tmp |= RADEON_CRTC2_VBLANK_MASK; | 710 | tmp |= RADEON_CRTC2_VBLANK_MASK; |
| 721 | } | 711 | } |
| 722 | if (rdev->irq.hpd[0]) { | 712 | if (rdev->irq.hpd[0]) { |
| @@ -782,7 +772,6 @@ int r100_irq_process(struct radeon_device *rdev) | |||
| 782 | /* gui idle interrupt */ | 772 | /* gui idle interrupt */ |
| 783 | if (status & RADEON_GUI_IDLE_STAT) { | 773 | if (status & RADEON_GUI_IDLE_STAT) { |
| 784 | rdev->irq.gui_idle_acked = true; | 774 | rdev->irq.gui_idle_acked = true; |
| 785 | rdev->pm.gui_idle = true; | ||
| 786 | wake_up(&rdev->irq.idle_queue); | 775 | wake_up(&rdev->irq.idle_queue); |
| 787 | } | 776 | } |
| 788 | /* Vertical blank interrupts */ | 777 | /* Vertical blank interrupts */ |
| @@ -792,7 +781,7 @@ int r100_irq_process(struct radeon_device *rdev) | |||
| 792 | rdev->pm.vblank_sync = true; | 781 | rdev->pm.vblank_sync = true; |
| 793 | wake_up(&rdev->irq.vblank_queue); | 782 | wake_up(&rdev->irq.vblank_queue); |
| 794 | } | 783 | } |
| 795 | if (rdev->irq.pflip[0]) | 784 | if (atomic_read(&rdev->irq.pflip[0])) |
| 796 | radeon_crtc_handle_flip(rdev, 0); | 785 | radeon_crtc_handle_flip(rdev, 0); |
| 797 | } | 786 | } |
| 798 | if (status & RADEON_CRTC2_VBLANK_STAT) { | 787 | if (status & RADEON_CRTC2_VBLANK_STAT) { |
| @@ -801,7 +790,7 @@ int r100_irq_process(struct radeon_device *rdev) | |||
| 801 | rdev->pm.vblank_sync = true; | 790 | rdev->pm.vblank_sync = true; |
| 802 | wake_up(&rdev->irq.vblank_queue); | 791 | wake_up(&rdev->irq.vblank_queue); |
| 803 | } | 792 | } |
| 804 | if (rdev->irq.pflip[1]) | 793 | if (atomic_read(&rdev->irq.pflip[1])) |
| 805 | radeon_crtc_handle_flip(rdev, 1); | 794 | radeon_crtc_handle_flip(rdev, 1); |
| 806 | } | 795 | } |
| 807 | if (status & RADEON_FP_DETECT_STAT) { | 796 | if (status & RADEON_FP_DETECT_STAT) { |
| @@ -883,7 +872,7 @@ int r100_copy_blit(struct radeon_device *rdev, | |||
| 883 | uint64_t src_offset, | 872 | uint64_t src_offset, |
| 884 | uint64_t dst_offset, | 873 | uint64_t dst_offset, |
| 885 | unsigned num_gpu_pages, | 874 | unsigned num_gpu_pages, |
| 886 | struct radeon_fence *fence) | 875 | struct radeon_fence **fence) |
| 887 | { | 876 | { |
| 888 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 877 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 889 | uint32_t cur_pages; | 878 | uint32_t cur_pages; |
| @@ -947,7 +936,7 @@ int r100_copy_blit(struct radeon_device *rdev, | |||
| 947 | RADEON_WAIT_HOST_IDLECLEAN | | 936 | RADEON_WAIT_HOST_IDLECLEAN | |
| 948 | RADEON_WAIT_DMA_GUI_IDLE); | 937 | RADEON_WAIT_DMA_GUI_IDLE); |
| 949 | if (fence) { | 938 | if (fence) { |
| 950 | r = radeon_fence_emit(rdev, fence); | 939 | r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); |
| 951 | } | 940 | } |
| 952 | radeon_ring_unlock_commit(rdev, ring); | 941 | radeon_ring_unlock_commit(rdev, ring); |
| 953 | return r; | 942 | return r; |
| @@ -1192,6 +1181,14 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) | |||
| 1192 | } | 1181 | } |
| 1193 | ring->ready = true; | 1182 | ring->ready = true; |
| 1194 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); | 1183 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); |
| 1184 | |||
| 1185 | if (radeon_ring_supports_scratch_reg(rdev, ring)) { | ||
| 1186 | r = radeon_scratch_get(rdev, &ring->rptr_save_reg); | ||
| 1187 | if (r) { | ||
| 1188 | DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); | ||
| 1189 | ring->rptr_save_reg = 0; | ||
| 1190 | } | ||
| 1191 | } | ||
| 1195 | return 0; | 1192 | return 0; |
| 1196 | } | 1193 | } |
| 1197 | 1194 | ||
| @@ -1202,6 +1199,7 @@ void r100_cp_fini(struct radeon_device *rdev) | |||
| 1202 | } | 1199 | } |
| 1203 | /* Disable ring */ | 1200 | /* Disable ring */ |
| 1204 | r100_cp_disable(rdev); | 1201 | r100_cp_disable(rdev); |
| 1202 | radeon_scratch_free(rdev, rdev->ring[RADEON_RING_TYPE_GFX_INDEX].rptr_save_reg); | ||
| 1205 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | 1203 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); |
| 1206 | DRM_INFO("radeon: cp finalized\n"); | 1204 | DRM_INFO("radeon: cp finalized\n"); |
| 1207 | } | 1205 | } |
| @@ -1223,6 +1221,112 @@ void r100_cp_disable(struct radeon_device *rdev) | |||
| 1223 | /* | 1221 | /* |
| 1224 | * CS functions | 1222 | * CS functions |
| 1225 | */ | 1223 | */ |
| 1224 | int r100_reloc_pitch_offset(struct radeon_cs_parser *p, | ||
| 1225 | struct radeon_cs_packet *pkt, | ||
| 1226 | unsigned idx, | ||
| 1227 | unsigned reg) | ||
| 1228 | { | ||
| 1229 | int r; | ||
| 1230 | u32 tile_flags = 0; | ||
| 1231 | u32 tmp; | ||
| 1232 | struct radeon_cs_reloc *reloc; | ||
| 1233 | u32 value; | ||
| 1234 | |||
| 1235 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1236 | if (r) { | ||
| 1237 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
| 1238 | idx, reg); | ||
| 1239 | r100_cs_dump_packet(p, pkt); | ||
| 1240 | return r; | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | value = radeon_get_ib_value(p, idx); | ||
| 1244 | tmp = value & 0x003fffff; | ||
| 1245 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); | ||
| 1246 | |||
| 1247 | if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { | ||
| 1248 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
| 1249 | tile_flags |= RADEON_DST_TILE_MACRO; | ||
| 1250 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { | ||
| 1251 | if (reg == RADEON_SRC_PITCH_OFFSET) { | ||
| 1252 | DRM_ERROR("Cannot src blit from microtiled surface\n"); | ||
| 1253 | r100_cs_dump_packet(p, pkt); | ||
| 1254 | return -EINVAL; | ||
| 1255 | } | ||
| 1256 | tile_flags |= RADEON_DST_TILE_MICRO; | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | tmp |= tile_flags; | ||
| 1260 | p->ib.ptr[idx] = (value & 0x3fc00000) | tmp; | ||
| 1261 | } else | ||
| 1262 | p->ib.ptr[idx] = (value & 0xffc00000) | tmp; | ||
| 1263 | return 0; | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, | ||
| 1267 | struct radeon_cs_packet *pkt, | ||
| 1268 | int idx) | ||
| 1269 | { | ||
| 1270 | unsigned c, i; | ||
| 1271 | struct radeon_cs_reloc *reloc; | ||
| 1272 | struct r100_cs_track *track; | ||
| 1273 | int r = 0; | ||
| 1274 | volatile uint32_t *ib; | ||
| 1275 | u32 idx_value; | ||
| 1276 | |||
| 1277 | ib = p->ib.ptr; | ||
| 1278 | track = (struct r100_cs_track *)p->track; | ||
| 1279 | c = radeon_get_ib_value(p, idx++) & 0x1F; | ||
| 1280 | if (c > 16) { | ||
| 1281 | DRM_ERROR("Only 16 vertex buffers are allowed %d\n", | ||
| 1282 | pkt->opcode); | ||
| 1283 | r100_cs_dump_packet(p, pkt); | ||
| 1284 | return -EINVAL; | ||
| 1285 | } | ||
| 1286 | track->num_arrays = c; | ||
| 1287 | for (i = 0; i < (c - 1); i+=2, idx+=3) { | ||
| 1288 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1289 | if (r) { | ||
| 1290 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 1291 | pkt->opcode); | ||
| 1292 | r100_cs_dump_packet(p, pkt); | ||
| 1293 | return r; | ||
| 1294 | } | ||
| 1295 | idx_value = radeon_get_ib_value(p, idx); | ||
| 1296 | ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); | ||
| 1297 | |||
| 1298 | track->arrays[i + 0].esize = idx_value >> 8; | ||
| 1299 | track->arrays[i + 0].robj = reloc->robj; | ||
| 1300 | track->arrays[i + 0].esize &= 0x7F; | ||
| 1301 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1302 | if (r) { | ||
| 1303 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 1304 | pkt->opcode); | ||
| 1305 | r100_cs_dump_packet(p, pkt); | ||
| 1306 | return r; | ||
| 1307 | } | ||
| 1308 | ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); | ||
| 1309 | track->arrays[i + 1].robj = reloc->robj; | ||
| 1310 | track->arrays[i + 1].esize = idx_value >> 24; | ||
| 1311 | track->arrays[i + 1].esize &= 0x7F; | ||
| 1312 | } | ||
| 1313 | if (c & 1) { | ||
| 1314 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1315 | if (r) { | ||
| 1316 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 1317 | pkt->opcode); | ||
| 1318 | r100_cs_dump_packet(p, pkt); | ||
| 1319 | return r; | ||
| 1320 | } | ||
| 1321 | idx_value = radeon_get_ib_value(p, idx); | ||
| 1322 | ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); | ||
| 1323 | track->arrays[i + 0].robj = reloc->robj; | ||
| 1324 | track->arrays[i + 0].esize = idx_value >> 8; | ||
| 1325 | track->arrays[i + 0].esize &= 0x7F; | ||
| 1326 | } | ||
| 1327 | return r; | ||
| 1328 | } | ||
| 1329 | |||
| 1226 | int r100_cs_parse_packet0(struct radeon_cs_parser *p, | 1330 | int r100_cs_parse_packet0(struct radeon_cs_parser *p, |
| 1227 | struct radeon_cs_packet *pkt, | 1331 | struct radeon_cs_packet *pkt, |
| 1228 | const unsigned *auth, unsigned n, | 1332 | const unsigned *auth, unsigned n, |
| @@ -2048,6 +2152,379 @@ int r100_cs_parse(struct radeon_cs_parser *p) | |||
| 2048 | return 0; | 2152 | return 0; |
| 2049 | } | 2153 | } |
| 2050 | 2154 | ||
| 2155 | static void r100_cs_track_texture_print(struct r100_cs_track_texture *t) | ||
| 2156 | { | ||
| 2157 | DRM_ERROR("pitch %d\n", t->pitch); | ||
| 2158 | DRM_ERROR("use_pitch %d\n", t->use_pitch); | ||
| 2159 | DRM_ERROR("width %d\n", t->width); | ||
| 2160 | DRM_ERROR("width_11 %d\n", t->width_11); | ||
| 2161 | DRM_ERROR("height %d\n", t->height); | ||
| 2162 | DRM_ERROR("height_11 %d\n", t->height_11); | ||
| 2163 | DRM_ERROR("num levels %d\n", t->num_levels); | ||
| 2164 | DRM_ERROR("depth %d\n", t->txdepth); | ||
| 2165 | DRM_ERROR("bpp %d\n", t->cpp); | ||
| 2166 | DRM_ERROR("coordinate type %d\n", t->tex_coord_type); | ||
| 2167 | DRM_ERROR("width round to power of 2 %d\n", t->roundup_w); | ||
| 2168 | DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); | ||
| 2169 | DRM_ERROR("compress format %d\n", t->compress_format); | ||
| 2170 | } | ||
| 2171 | |||
| 2172 | static int r100_track_compress_size(int compress_format, int w, int h) | ||
| 2173 | { | ||
| 2174 | int block_width, block_height, block_bytes; | ||
| 2175 | int wblocks, hblocks; | ||
| 2176 | int min_wblocks; | ||
| 2177 | int sz; | ||
| 2178 | |||
| 2179 | block_width = 4; | ||
| 2180 | block_height = 4; | ||
| 2181 | |||
| 2182 | switch (compress_format) { | ||
| 2183 | case R100_TRACK_COMP_DXT1: | ||
| 2184 | block_bytes = 8; | ||
| 2185 | min_wblocks = 4; | ||
| 2186 | break; | ||
| 2187 | default: | ||
| 2188 | case R100_TRACK_COMP_DXT35: | ||
| 2189 | block_bytes = 16; | ||
| 2190 | min_wblocks = 2; | ||
| 2191 | break; | ||
| 2192 | } | ||
| 2193 | |||
| 2194 | hblocks = (h + block_height - 1) / block_height; | ||
| 2195 | wblocks = (w + block_width - 1) / block_width; | ||
| 2196 | if (wblocks < min_wblocks) | ||
| 2197 | wblocks = min_wblocks; | ||
| 2198 | sz = wblocks * hblocks * block_bytes; | ||
| 2199 | return sz; | ||
| 2200 | } | ||
| 2201 | |||
| 2202 | static int r100_cs_track_cube(struct radeon_device *rdev, | ||
| 2203 | struct r100_cs_track *track, unsigned idx) | ||
| 2204 | { | ||
| 2205 | unsigned face, w, h; | ||
| 2206 | struct radeon_bo *cube_robj; | ||
| 2207 | unsigned long size; | ||
| 2208 | unsigned compress_format = track->textures[idx].compress_format; | ||
| 2209 | |||
| 2210 | for (face = 0; face < 5; face++) { | ||
| 2211 | cube_robj = track->textures[idx].cube_info[face].robj; | ||
| 2212 | w = track->textures[idx].cube_info[face].width; | ||
| 2213 | h = track->textures[idx].cube_info[face].height; | ||
| 2214 | |||
| 2215 | if (compress_format) { | ||
| 2216 | size = r100_track_compress_size(compress_format, w, h); | ||
| 2217 | } else | ||
| 2218 | size = w * h; | ||
| 2219 | size *= track->textures[idx].cpp; | ||
| 2220 | |||
| 2221 | size += track->textures[idx].cube_info[face].offset; | ||
| 2222 | |||
| 2223 | if (size > radeon_bo_size(cube_robj)) { | ||
| 2224 | DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", | ||
| 2225 | size, radeon_bo_size(cube_robj)); | ||
| 2226 | r100_cs_track_texture_print(&track->textures[idx]); | ||
| 2227 | return -1; | ||
| 2228 | } | ||
| 2229 | } | ||
| 2230 | return 0; | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | static int r100_cs_track_texture_check(struct radeon_device *rdev, | ||
| 2234 | struct r100_cs_track *track) | ||
| 2235 | { | ||
| 2236 | struct radeon_bo *robj; | ||
| 2237 | unsigned long size; | ||
| 2238 | unsigned u, i, w, h, d; | ||
| 2239 | int ret; | ||
| 2240 | |||
| 2241 | for (u = 0; u < track->num_texture; u++) { | ||
| 2242 | if (!track->textures[u].enabled) | ||
| 2243 | continue; | ||
| 2244 | if (track->textures[u].lookup_disable) | ||
| 2245 | continue; | ||
| 2246 | robj = track->textures[u].robj; | ||
| 2247 | if (robj == NULL) { | ||
| 2248 | DRM_ERROR("No texture bound to unit %u\n", u); | ||
| 2249 | return -EINVAL; | ||
| 2250 | } | ||
| 2251 | size = 0; | ||
| 2252 | for (i = 0; i <= track->textures[u].num_levels; i++) { | ||
| 2253 | if (track->textures[u].use_pitch) { | ||
| 2254 | if (rdev->family < CHIP_R300) | ||
| 2255 | w = (track->textures[u].pitch / track->textures[u].cpp) / (1 << i); | ||
| 2256 | else | ||
| 2257 | w = track->textures[u].pitch / (1 << i); | ||
| 2258 | } else { | ||
| 2259 | w = track->textures[u].width; | ||
| 2260 | if (rdev->family >= CHIP_RV515) | ||
| 2261 | w |= track->textures[u].width_11; | ||
| 2262 | w = w / (1 << i); | ||
| 2263 | if (track->textures[u].roundup_w) | ||
| 2264 | w = roundup_pow_of_two(w); | ||
| 2265 | } | ||
| 2266 | h = track->textures[u].height; | ||
| 2267 | if (rdev->family >= CHIP_RV515) | ||
| 2268 | h |= track->textures[u].height_11; | ||
| 2269 | h = h / (1 << i); | ||
| 2270 | if (track->textures[u].roundup_h) | ||
| 2271 | h = roundup_pow_of_two(h); | ||
| 2272 | if (track->textures[u].tex_coord_type == 1) { | ||
| 2273 | d = (1 << track->textures[u].txdepth) / (1 << i); | ||
| 2274 | if (!d) | ||
| 2275 | d = 1; | ||
| 2276 | } else { | ||
| 2277 | d = 1; | ||
| 2278 | } | ||
| 2279 | if (track->textures[u].compress_format) { | ||
| 2280 | |||
| 2281 | size += r100_track_compress_size(track->textures[u].compress_format, w, h) * d; | ||
| 2282 | /* compressed textures are block based */ | ||
| 2283 | } else | ||
| 2284 | size += w * h * d; | ||
| 2285 | } | ||
| 2286 | size *= track->textures[u].cpp; | ||
| 2287 | |||
| 2288 | switch (track->textures[u].tex_coord_type) { | ||
| 2289 | case 0: | ||
| 2290 | case 1: | ||
| 2291 | break; | ||
| 2292 | case 2: | ||
| 2293 | if (track->separate_cube) { | ||
| 2294 | ret = r100_cs_track_cube(rdev, track, u); | ||
| 2295 | if (ret) | ||
| 2296 | return ret; | ||
| 2297 | } else | ||
| 2298 | size *= 6; | ||
| 2299 | break; | ||
| 2300 | default: | ||
| 2301 | DRM_ERROR("Invalid texture coordinate type %u for unit " | ||
| 2302 | "%u\n", track->textures[u].tex_coord_type, u); | ||
| 2303 | return -EINVAL; | ||
| 2304 | } | ||
| 2305 | if (size > radeon_bo_size(robj)) { | ||
| 2306 | DRM_ERROR("Texture of unit %u needs %lu bytes but is " | ||
| 2307 | "%lu\n", u, size, radeon_bo_size(robj)); | ||
| 2308 | r100_cs_track_texture_print(&track->textures[u]); | ||
| 2309 | return -EINVAL; | ||
| 2310 | } | ||
| 2311 | } | ||
| 2312 | return 0; | ||
| 2313 | } | ||
| 2314 | |||
| 2315 | int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) | ||
| 2316 | { | ||
| 2317 | unsigned i; | ||
| 2318 | unsigned long size; | ||
| 2319 | unsigned prim_walk; | ||
| 2320 | unsigned nverts; | ||
| 2321 | unsigned num_cb = track->cb_dirty ? track->num_cb : 0; | ||
| 2322 | |||
| 2323 | if (num_cb && !track->zb_cb_clear && !track->color_channel_mask && | ||
| 2324 | !track->blend_read_enable) | ||
| 2325 | num_cb = 0; | ||
| 2326 | |||
| 2327 | for (i = 0; i < num_cb; i++) { | ||
| 2328 | if (track->cb[i].robj == NULL) { | ||
| 2329 | DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); | ||
| 2330 | return -EINVAL; | ||
| 2331 | } | ||
| 2332 | size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; | ||
| 2333 | size += track->cb[i].offset; | ||
| 2334 | if (size > radeon_bo_size(track->cb[i].robj)) { | ||
| 2335 | DRM_ERROR("[drm] Buffer too small for color buffer %d " | ||
| 2336 | "(need %lu have %lu) !\n", i, size, | ||
| 2337 | radeon_bo_size(track->cb[i].robj)); | ||
| 2338 | DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", | ||
| 2339 | i, track->cb[i].pitch, track->cb[i].cpp, | ||
| 2340 | track->cb[i].offset, track->maxy); | ||
| 2341 | return -EINVAL; | ||
| 2342 | } | ||
| 2343 | } | ||
| 2344 | track->cb_dirty = false; | ||
| 2345 | |||
| 2346 | if (track->zb_dirty && track->z_enabled) { | ||
| 2347 | if (track->zb.robj == NULL) { | ||
| 2348 | DRM_ERROR("[drm] No buffer for z buffer !\n"); | ||
| 2349 | return -EINVAL; | ||
| 2350 | } | ||
| 2351 | size = track->zb.pitch * track->zb.cpp * track->maxy; | ||
| 2352 | size += track->zb.offset; | ||
| 2353 | if (size > radeon_bo_size(track->zb.robj)) { | ||
| 2354 | DRM_ERROR("[drm] Buffer too small for z buffer " | ||
| 2355 | "(need %lu have %lu) !\n", size, | ||
| 2356 | radeon_bo_size(track->zb.robj)); | ||
| 2357 | DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", | ||
| 2358 | track->zb.pitch, track->zb.cpp, | ||
| 2359 | track->zb.offset, track->maxy); | ||
| 2360 | return -EINVAL; | ||
| 2361 | } | ||
| 2362 | } | ||
| 2363 | track->zb_dirty = false; | ||
| 2364 | |||
| 2365 | if (track->aa_dirty && track->aaresolve) { | ||
| 2366 | if (track->aa.robj == NULL) { | ||
| 2367 | DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i); | ||
| 2368 | return -EINVAL; | ||
| 2369 | } | ||
| 2370 | /* I believe the format comes from colorbuffer0. */ | ||
| 2371 | size = track->aa.pitch * track->cb[0].cpp * track->maxy; | ||
| 2372 | size += track->aa.offset; | ||
| 2373 | if (size > radeon_bo_size(track->aa.robj)) { | ||
| 2374 | DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d " | ||
| 2375 | "(need %lu have %lu) !\n", i, size, | ||
| 2376 | radeon_bo_size(track->aa.robj)); | ||
| 2377 | DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n", | ||
| 2378 | i, track->aa.pitch, track->cb[0].cpp, | ||
| 2379 | track->aa.offset, track->maxy); | ||
| 2380 | return -EINVAL; | ||
| 2381 | } | ||
| 2382 | } | ||
| 2383 | track->aa_dirty = false; | ||
| 2384 | |||
| 2385 | prim_walk = (track->vap_vf_cntl >> 4) & 0x3; | ||
| 2386 | if (track->vap_vf_cntl & (1 << 14)) { | ||
| 2387 | nverts = track->vap_alt_nverts; | ||
| 2388 | } else { | ||
| 2389 | nverts = (track->vap_vf_cntl >> 16) & 0xFFFF; | ||
| 2390 | } | ||
| 2391 | switch (prim_walk) { | ||
| 2392 | case 1: | ||
| 2393 | for (i = 0; i < track->num_arrays; i++) { | ||
| 2394 | size = track->arrays[i].esize * track->max_indx * 4; | ||
| 2395 | if (track->arrays[i].robj == NULL) { | ||
| 2396 | DRM_ERROR("(PW %u) Vertex array %u no buffer " | ||
| 2397 | "bound\n", prim_walk, i); | ||
| 2398 | return -EINVAL; | ||
| 2399 | } | ||
| 2400 | if (size > radeon_bo_size(track->arrays[i].robj)) { | ||
| 2401 | dev_err(rdev->dev, "(PW %u) Vertex array %u " | ||
| 2402 | "need %lu dwords have %lu dwords\n", | ||
| 2403 | prim_walk, i, size >> 2, | ||
| 2404 | radeon_bo_size(track->arrays[i].robj) | ||
| 2405 | >> 2); | ||
| 2406 | DRM_ERROR("Max indices %u\n", track->max_indx); | ||
| 2407 | return -EINVAL; | ||
| 2408 | } | ||
| 2409 | } | ||
| 2410 | break; | ||
| 2411 | case 2: | ||
| 2412 | for (i = 0; i < track->num_arrays; i++) { | ||
| 2413 | size = track->arrays[i].esize * (nverts - 1) * 4; | ||
| 2414 | if (track->arrays[i].robj == NULL) { | ||
| 2415 | DRM_ERROR("(PW %u) Vertex array %u no buffer " | ||
| 2416 | "bound\n", prim_walk, i); | ||
| 2417 | return -EINVAL; | ||
| 2418 | } | ||
| 2419 | if (size > radeon_bo_size(track->arrays[i].robj)) { | ||
| 2420 | dev_err(rdev->dev, "(PW %u) Vertex array %u " | ||
| 2421 | "need %lu dwords have %lu dwords\n", | ||
| 2422 | prim_walk, i, size >> 2, | ||
| 2423 | radeon_bo_size(track->arrays[i].robj) | ||
| 2424 | >> 2); | ||
| 2425 | return -EINVAL; | ||
| 2426 | } | ||
| 2427 | } | ||
| 2428 | break; | ||
| 2429 | case 3: | ||
| 2430 | size = track->vtx_size * nverts; | ||
| 2431 | if (size != track->immd_dwords) { | ||
| 2432 | DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n", | ||
| 2433 | track->immd_dwords, size); | ||
| 2434 | DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n", | ||
| 2435 | nverts, track->vtx_size); | ||
| 2436 | return -EINVAL; | ||
| 2437 | } | ||
| 2438 | break; | ||
| 2439 | default: | ||
| 2440 | DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n", | ||
| 2441 | prim_walk); | ||
| 2442 | return -EINVAL; | ||
| 2443 | } | ||
| 2444 | |||
| 2445 | if (track->tex_dirty) { | ||
| 2446 | track->tex_dirty = false; | ||
| 2447 | return r100_cs_track_texture_check(rdev, track); | ||
| 2448 | } | ||
| 2449 | return 0; | ||
| 2450 | } | ||
| 2451 | |||
| 2452 | void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track) | ||
| 2453 | { | ||
| 2454 | unsigned i, face; | ||
| 2455 | |||
| 2456 | track->cb_dirty = true; | ||
| 2457 | track->zb_dirty = true; | ||
| 2458 | track->tex_dirty = true; | ||
| 2459 | track->aa_dirty = true; | ||
| 2460 | |||
| 2461 | if (rdev->family < CHIP_R300) { | ||
| 2462 | track->num_cb = 1; | ||
| 2463 | if (rdev->family <= CHIP_RS200) | ||
| 2464 | track->num_texture = 3; | ||
| 2465 | else | ||
| 2466 | track->num_texture = 6; | ||
| 2467 | track->maxy = 2048; | ||
| 2468 | track->separate_cube = 1; | ||
| 2469 | } else { | ||
| 2470 | track->num_cb = 4; | ||
| 2471 | track->num_texture = 16; | ||
| 2472 | track->maxy = 4096; | ||
| 2473 | track->separate_cube = 0; | ||
| 2474 | track->aaresolve = false; | ||
| 2475 | track->aa.robj = NULL; | ||
| 2476 | } | ||
| 2477 | |||
| 2478 | for (i = 0; i < track->num_cb; i++) { | ||
| 2479 | track->cb[i].robj = NULL; | ||
| 2480 | track->cb[i].pitch = 8192; | ||
| 2481 | track->cb[i].cpp = 16; | ||
| 2482 | track->cb[i].offset = 0; | ||
| 2483 | } | ||
| 2484 | track->z_enabled = true; | ||
| 2485 | track->zb.robj = NULL; | ||
| 2486 | track->zb.pitch = 8192; | ||
| 2487 | track->zb.cpp = 4; | ||
| 2488 | track->zb.offset = 0; | ||
| 2489 | track->vtx_size = 0x7F; | ||
| 2490 | track->immd_dwords = 0xFFFFFFFFUL; | ||
| 2491 | track->num_arrays = 11; | ||
| 2492 | track->max_indx = 0x00FFFFFFUL; | ||
| 2493 | for (i = 0; i < track->num_arrays; i++) { | ||
| 2494 | track->arrays[i].robj = NULL; | ||
| 2495 | track->arrays[i].esize = 0x7F; | ||
| 2496 | } | ||
| 2497 | for (i = 0; i < track->num_texture; i++) { | ||
| 2498 | track->textures[i].compress_format = R100_TRACK_COMP_NONE; | ||
| 2499 | track->textures[i].pitch = 16536; | ||
| 2500 | track->textures[i].width = 16536; | ||
| 2501 | track->textures[i].height = 16536; | ||
| 2502 | track->textures[i].width_11 = 1 << 11; | ||
| 2503 | track->textures[i].height_11 = 1 << 11; | ||
| 2504 | track->textures[i].num_levels = 12; | ||
| 2505 | if (rdev->family <= CHIP_RS200) { | ||
| 2506 | track->textures[i].tex_coord_type = 0; | ||
| 2507 | track->textures[i].txdepth = 0; | ||
| 2508 | } else { | ||
| 2509 | track->textures[i].txdepth = 16; | ||
| 2510 | track->textures[i].tex_coord_type = 1; | ||
| 2511 | } | ||
| 2512 | track->textures[i].cpp = 64; | ||
| 2513 | track->textures[i].robj = NULL; | ||
| 2514 | /* CS IB emission code makes sure texture unit are disabled */ | ||
| 2515 | track->textures[i].enabled = false; | ||
| 2516 | track->textures[i].lookup_disable = false; | ||
| 2517 | track->textures[i].roundup_w = true; | ||
| 2518 | track->textures[i].roundup_h = true; | ||
| 2519 | if (track->separate_cube) | ||
| 2520 | for (face = 0; face < 5; face++) { | ||
| 2521 | track->textures[i].cube_info[face].robj = NULL; | ||
| 2522 | track->textures[i].cube_info[face].width = 16536; | ||
| 2523 | track->textures[i].cube_info[face].height = 16536; | ||
| 2524 | track->textures[i].cube_info[face].offset = 0; | ||
| 2525 | } | ||
| 2526 | } | ||
| 2527 | } | ||
| 2051 | 2528 | ||
| 2052 | /* | 2529 | /* |
| 2053 | * Global GPU functions | 2530 | * Global GPU functions |
| @@ -2175,6 +2652,15 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2175 | return radeon_ring_test_lockup(rdev, ring); | 2652 | return radeon_ring_test_lockup(rdev, ring); |
| 2176 | } | 2653 | } |
| 2177 | 2654 | ||
| 2655 | /* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ | ||
| 2656 | void r100_enable_bm(struct radeon_device *rdev) | ||
| 2657 | { | ||
| 2658 | uint32_t tmp; | ||
| 2659 | /* Enable bus mastering */ | ||
| 2660 | tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; | ||
| 2661 | WREG32(RADEON_BUS_CNTL, tmp); | ||
| 2662 | } | ||
| 2663 | |||
| 2178 | void r100_bm_disable(struct radeon_device *rdev) | 2664 | void r100_bm_disable(struct radeon_device *rdev) |
| 2179 | { | 2665 | { |
| 2180 | u32 tmp; | 2666 | u32 tmp; |
| @@ -3261,380 +3747,6 @@ void r100_bandwidth_update(struct radeon_device *rdev) | |||
| 3261 | } | 3747 | } |
| 3262 | } | 3748 | } |
| 3263 | 3749 | ||
| 3264 | static void r100_cs_track_texture_print(struct r100_cs_track_texture *t) | ||
| 3265 | { | ||
| 3266 | DRM_ERROR("pitch %d\n", t->pitch); | ||
| 3267 | DRM_ERROR("use_pitch %d\n", t->use_pitch); | ||
| 3268 | DRM_ERROR("width %d\n", t->width); | ||
| 3269 | DRM_ERROR("width_11 %d\n", t->width_11); | ||
| 3270 | DRM_ERROR("height %d\n", t->height); | ||
| 3271 | DRM_ERROR("height_11 %d\n", t->height_11); | ||
| 3272 | DRM_ERROR("num levels %d\n", t->num_levels); | ||
| 3273 | DRM_ERROR("depth %d\n", t->txdepth); | ||
| 3274 | DRM_ERROR("bpp %d\n", t->cpp); | ||
| 3275 | DRM_ERROR("coordinate type %d\n", t->tex_coord_type); | ||
| 3276 | DRM_ERROR("width round to power of 2 %d\n", t->roundup_w); | ||
| 3277 | DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); | ||
| 3278 | DRM_ERROR("compress format %d\n", t->compress_format); | ||
| 3279 | } | ||
| 3280 | |||
| 3281 | static int r100_track_compress_size(int compress_format, int w, int h) | ||
| 3282 | { | ||
| 3283 | int block_width, block_height, block_bytes; | ||
| 3284 | int wblocks, hblocks; | ||
| 3285 | int min_wblocks; | ||
| 3286 | int sz; | ||
| 3287 | |||
| 3288 | block_width = 4; | ||
| 3289 | block_height = 4; | ||
| 3290 | |||
| 3291 | switch (compress_format) { | ||
| 3292 | case R100_TRACK_COMP_DXT1: | ||
| 3293 | block_bytes = 8; | ||
| 3294 | min_wblocks = 4; | ||
| 3295 | break; | ||
| 3296 | default: | ||
| 3297 | case R100_TRACK_COMP_DXT35: | ||
| 3298 | block_bytes = 16; | ||
| 3299 | min_wblocks = 2; | ||
| 3300 | break; | ||
| 3301 | } | ||
| 3302 | |||
| 3303 | hblocks = (h + block_height - 1) / block_height; | ||
| 3304 | wblocks = (w + block_width - 1) / block_width; | ||
| 3305 | if (wblocks < min_wblocks) | ||
| 3306 | wblocks = min_wblocks; | ||
| 3307 | sz = wblocks * hblocks * block_bytes; | ||
| 3308 | return sz; | ||
| 3309 | } | ||
| 3310 | |||
| 3311 | static int r100_cs_track_cube(struct radeon_device *rdev, | ||
| 3312 | struct r100_cs_track *track, unsigned idx) | ||
| 3313 | { | ||
| 3314 | unsigned face, w, h; | ||
| 3315 | struct radeon_bo *cube_robj; | ||
| 3316 | unsigned long size; | ||
| 3317 | unsigned compress_format = track->textures[idx].compress_format; | ||
| 3318 | |||
| 3319 | for (face = 0; face < 5; face++) { | ||
| 3320 | cube_robj = track->textures[idx].cube_info[face].robj; | ||
| 3321 | w = track->textures[idx].cube_info[face].width; | ||
| 3322 | h = track->textures[idx].cube_info[face].height; | ||
| 3323 | |||
| 3324 | if (compress_format) { | ||
| 3325 | size = r100_track_compress_size(compress_format, w, h); | ||
| 3326 | } else | ||
| 3327 | size = w * h; | ||
| 3328 | size *= track->textures[idx].cpp; | ||
| 3329 | |||
| 3330 | size += track->textures[idx].cube_info[face].offset; | ||
| 3331 | |||
| 3332 | if (size > radeon_bo_size(cube_robj)) { | ||
| 3333 | DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", | ||
| 3334 | size, radeon_bo_size(cube_robj)); | ||
| 3335 | r100_cs_track_texture_print(&track->textures[idx]); | ||
| 3336 | return -1; | ||
| 3337 | } | ||
| 3338 | } | ||
| 3339 | return 0; | ||
| 3340 | } | ||
| 3341 | |||
| 3342 | static int r100_cs_track_texture_check(struct radeon_device *rdev, | ||
| 3343 | struct r100_cs_track *track) | ||
| 3344 | { | ||
| 3345 | struct radeon_bo *robj; | ||
| 3346 | unsigned long size; | ||
| 3347 | unsigned u, i, w, h, d; | ||
| 3348 | int ret; | ||
| 3349 | |||
| 3350 | for (u = 0; u < track->num_texture; u++) { | ||
| 3351 | if (!track->textures[u].enabled) | ||
| 3352 | continue; | ||
| 3353 | if (track->textures[u].lookup_disable) | ||
| 3354 | continue; | ||
| 3355 | robj = track->textures[u].robj; | ||
| 3356 | if (robj == NULL) { | ||
| 3357 | DRM_ERROR("No texture bound to unit %u\n", u); | ||
| 3358 | return -EINVAL; | ||
| 3359 | } | ||
| 3360 | size = 0; | ||
| 3361 | for (i = 0; i <= track->textures[u].num_levels; i++) { | ||
| 3362 | if (track->textures[u].use_pitch) { | ||
| 3363 | if (rdev->family < CHIP_R300) | ||
| 3364 | w = (track->textures[u].pitch / track->textures[u].cpp) / (1 << i); | ||
| 3365 | else | ||
| 3366 | w = track->textures[u].pitch / (1 << i); | ||
| 3367 | } else { | ||
| 3368 | w = track->textures[u].width; | ||
| 3369 | if (rdev->family >= CHIP_RV515) | ||
| 3370 | w |= track->textures[u].width_11; | ||
| 3371 | w = w / (1 << i); | ||
| 3372 | if (track->textures[u].roundup_w) | ||
| 3373 | w = roundup_pow_of_two(w); | ||
| 3374 | } | ||
| 3375 | h = track->textures[u].height; | ||
| 3376 | if (rdev->family >= CHIP_RV515) | ||
| 3377 | h |= track->textures[u].height_11; | ||
| 3378 | h = h / (1 << i); | ||
| 3379 | if (track->textures[u].roundup_h) | ||
| 3380 | h = roundup_pow_of_two(h); | ||
| 3381 | if (track->textures[u].tex_coord_type == 1) { | ||
| 3382 | d = (1 << track->textures[u].txdepth) / (1 << i); | ||
| 3383 | if (!d) | ||
| 3384 | d = 1; | ||
| 3385 | } else { | ||
| 3386 | d = 1; | ||
| 3387 | } | ||
| 3388 | if (track->textures[u].compress_format) { | ||
| 3389 | |||
| 3390 | size += r100_track_compress_size(track->textures[u].compress_format, w, h) * d; | ||
| 3391 | /* compressed textures are block based */ | ||
| 3392 | } else | ||
| 3393 | size += w * h * d; | ||
| 3394 | } | ||
| 3395 | size *= track->textures[u].cpp; | ||
| 3396 | |||
| 3397 | switch (track->textures[u].tex_coord_type) { | ||
| 3398 | case 0: | ||
| 3399 | case 1: | ||
| 3400 | break; | ||
| 3401 | case 2: | ||
| 3402 | if (track->separate_cube) { | ||
| 3403 | ret = r100_cs_track_cube(rdev, track, u); | ||
| 3404 | if (ret) | ||
| 3405 | return ret; | ||
| 3406 | } else | ||
| 3407 | size *= 6; | ||
| 3408 | break; | ||
| 3409 | default: | ||
| 3410 | DRM_ERROR("Invalid texture coordinate type %u for unit " | ||
| 3411 | "%u\n", track->textures[u].tex_coord_type, u); | ||
| 3412 | return -EINVAL; | ||
| 3413 | } | ||
| 3414 | if (size > radeon_bo_size(robj)) { | ||
| 3415 | DRM_ERROR("Texture of unit %u needs %lu bytes but is " | ||
| 3416 | "%lu\n", u, size, radeon_bo_size(robj)); | ||
| 3417 | r100_cs_track_texture_print(&track->textures[u]); | ||
| 3418 | return -EINVAL; | ||
| 3419 | } | ||
| 3420 | } | ||
| 3421 | return 0; | ||
| 3422 | } | ||
| 3423 | |||
| 3424 | int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) | ||
| 3425 | { | ||
| 3426 | unsigned i; | ||
| 3427 | unsigned long size; | ||
| 3428 | unsigned prim_walk; | ||
| 3429 | unsigned nverts; | ||
| 3430 | unsigned num_cb = track->cb_dirty ? track->num_cb : 0; | ||
| 3431 | |||
| 3432 | if (num_cb && !track->zb_cb_clear && !track->color_channel_mask && | ||
| 3433 | !track->blend_read_enable) | ||
| 3434 | num_cb = 0; | ||
| 3435 | |||
| 3436 | for (i = 0; i < num_cb; i++) { | ||
| 3437 | if (track->cb[i].robj == NULL) { | ||
| 3438 | DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); | ||
| 3439 | return -EINVAL; | ||
| 3440 | } | ||
| 3441 | size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; | ||
| 3442 | size += track->cb[i].offset; | ||
| 3443 | if (size > radeon_bo_size(track->cb[i].robj)) { | ||
| 3444 | DRM_ERROR("[drm] Buffer too small for color buffer %d " | ||
| 3445 | "(need %lu have %lu) !\n", i, size, | ||
| 3446 | radeon_bo_size(track->cb[i].robj)); | ||
| 3447 | DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", | ||
| 3448 | i, track->cb[i].pitch, track->cb[i].cpp, | ||
| 3449 | track->cb[i].offset, track->maxy); | ||
| 3450 | return -EINVAL; | ||
| 3451 | } | ||
| 3452 | } | ||
| 3453 | track->cb_dirty = false; | ||
| 3454 | |||
| 3455 | if (track->zb_dirty && track->z_enabled) { | ||
| 3456 | if (track->zb.robj == NULL) { | ||
| 3457 | DRM_ERROR("[drm] No buffer for z buffer !\n"); | ||
| 3458 | return -EINVAL; | ||
| 3459 | } | ||
| 3460 | size = track->zb.pitch * track->zb.cpp * track->maxy; | ||
| 3461 | size += track->zb.offset; | ||
| 3462 | if (size > radeon_bo_size(track->zb.robj)) { | ||
| 3463 | DRM_ERROR("[drm] Buffer too small for z buffer " | ||
| 3464 | "(need %lu have %lu) !\n", size, | ||
| 3465 | radeon_bo_size(track->zb.robj)); | ||
| 3466 | DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", | ||
| 3467 | track->zb.pitch, track->zb.cpp, | ||
| 3468 | track->zb.offset, track->maxy); | ||
| 3469 | return -EINVAL; | ||
| 3470 | } | ||
| 3471 | } | ||
| 3472 | track->zb_dirty = false; | ||
| 3473 | |||
| 3474 | if (track->aa_dirty && track->aaresolve) { | ||
| 3475 | if (track->aa.robj == NULL) { | ||
| 3476 | DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i); | ||
| 3477 | return -EINVAL; | ||
| 3478 | } | ||
| 3479 | /* I believe the format comes from colorbuffer0. */ | ||
| 3480 | size = track->aa.pitch * track->cb[0].cpp * track->maxy; | ||
| 3481 | size += track->aa.offset; | ||
| 3482 | if (size > radeon_bo_size(track->aa.robj)) { | ||
| 3483 | DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d " | ||
| 3484 | "(need %lu have %lu) !\n", i, size, | ||
| 3485 | radeon_bo_size(track->aa.robj)); | ||
| 3486 | DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n", | ||
| 3487 | i, track->aa.pitch, track->cb[0].cpp, | ||
| 3488 | track->aa.offset, track->maxy); | ||
| 3489 | return -EINVAL; | ||
| 3490 | } | ||
| 3491 | } | ||
| 3492 | track->aa_dirty = false; | ||
| 3493 | |||
| 3494 | prim_walk = (track->vap_vf_cntl >> 4) & 0x3; | ||
| 3495 | if (track->vap_vf_cntl & (1 << 14)) { | ||
| 3496 | nverts = track->vap_alt_nverts; | ||
| 3497 | } else { | ||
| 3498 | nverts = (track->vap_vf_cntl >> 16) & 0xFFFF; | ||
| 3499 | } | ||
| 3500 | switch (prim_walk) { | ||
| 3501 | case 1: | ||
| 3502 | for (i = 0; i < track->num_arrays; i++) { | ||
| 3503 | size = track->arrays[i].esize * track->max_indx * 4; | ||
| 3504 | if (track->arrays[i].robj == NULL) { | ||
| 3505 | DRM_ERROR("(PW %u) Vertex array %u no buffer " | ||
| 3506 | "bound\n", prim_walk, i); | ||
| 3507 | return -EINVAL; | ||
| 3508 | } | ||
| 3509 | if (size > radeon_bo_size(track->arrays[i].robj)) { | ||
| 3510 | dev_err(rdev->dev, "(PW %u) Vertex array %u " | ||
| 3511 | "need %lu dwords have %lu dwords\n", | ||
| 3512 | prim_walk, i, size >> 2, | ||
| 3513 | radeon_bo_size(track->arrays[i].robj) | ||
| 3514 | >> 2); | ||
| 3515 | DRM_ERROR("Max indices %u\n", track->max_indx); | ||
| 3516 | return -EINVAL; | ||
| 3517 | } | ||
| 3518 | } | ||
| 3519 | break; | ||
| 3520 | case 2: | ||
| 3521 | for (i = 0; i < track->num_arrays; i++) { | ||
| 3522 | size = track->arrays[i].esize * (nverts - 1) * 4; | ||
| 3523 | if (track->arrays[i].robj == NULL) { | ||
| 3524 | DRM_ERROR("(PW %u) Vertex array %u no buffer " | ||
| 3525 | "bound\n", prim_walk, i); | ||
| 3526 | return -EINVAL; | ||
| 3527 | } | ||
| 3528 | if (size > radeon_bo_size(track->arrays[i].robj)) { | ||
| 3529 | dev_err(rdev->dev, "(PW %u) Vertex array %u " | ||
| 3530 | "need %lu dwords have %lu dwords\n", | ||
| 3531 | prim_walk, i, size >> 2, | ||
| 3532 | radeon_bo_size(track->arrays[i].robj) | ||
| 3533 | >> 2); | ||
| 3534 | return -EINVAL; | ||
| 3535 | } | ||
| 3536 | } | ||
| 3537 | break; | ||
| 3538 | case 3: | ||
| 3539 | size = track->vtx_size * nverts; | ||
| 3540 | if (size != track->immd_dwords) { | ||
| 3541 | DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n", | ||
| 3542 | track->immd_dwords, size); | ||
| 3543 | DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n", | ||
| 3544 | nverts, track->vtx_size); | ||
| 3545 | return -EINVAL; | ||
| 3546 | } | ||
| 3547 | break; | ||
| 3548 | default: | ||
| 3549 | DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n", | ||
| 3550 | prim_walk); | ||
| 3551 | return -EINVAL; | ||
| 3552 | } | ||
| 3553 | |||
| 3554 | if (track->tex_dirty) { | ||
| 3555 | track->tex_dirty = false; | ||
| 3556 | return r100_cs_track_texture_check(rdev, track); | ||
| 3557 | } | ||
| 3558 | return 0; | ||
| 3559 | } | ||
| 3560 | |||
| 3561 | void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track) | ||
| 3562 | { | ||
| 3563 | unsigned i, face; | ||
| 3564 | |||
| 3565 | track->cb_dirty = true; | ||
| 3566 | track->zb_dirty = true; | ||
| 3567 | track->tex_dirty = true; | ||
| 3568 | track->aa_dirty = true; | ||
| 3569 | |||
| 3570 | if (rdev->family < CHIP_R300) { | ||
| 3571 | track->num_cb = 1; | ||
| 3572 | if (rdev->family <= CHIP_RS200) | ||
| 3573 | track->num_texture = 3; | ||
| 3574 | else | ||
| 3575 | track->num_texture = 6; | ||
| 3576 | track->maxy = 2048; | ||
| 3577 | track->separate_cube = 1; | ||
| 3578 | } else { | ||
| 3579 | track->num_cb = 4; | ||
| 3580 | track->num_texture = 16; | ||
| 3581 | track->maxy = 4096; | ||
| 3582 | track->separate_cube = 0; | ||
| 3583 | track->aaresolve = false; | ||
| 3584 | track->aa.robj = NULL; | ||
| 3585 | } | ||
| 3586 | |||
| 3587 | for (i = 0; i < track->num_cb; i++) { | ||
| 3588 | track->cb[i].robj = NULL; | ||
| 3589 | track->cb[i].pitch = 8192; | ||
| 3590 | track->cb[i].cpp = 16; | ||
| 3591 | track->cb[i].offset = 0; | ||
| 3592 | } | ||
| 3593 | track->z_enabled = true; | ||
| 3594 | track->zb.robj = NULL; | ||
| 3595 | track->zb.pitch = 8192; | ||
| 3596 | track->zb.cpp = 4; | ||
| 3597 | track->zb.offset = 0; | ||
| 3598 | track->vtx_size = 0x7F; | ||
| 3599 | track->immd_dwords = 0xFFFFFFFFUL; | ||
| 3600 | track->num_arrays = 11; | ||
| 3601 | track->max_indx = 0x00FFFFFFUL; | ||
| 3602 | for (i = 0; i < track->num_arrays; i++) { | ||
| 3603 | track->arrays[i].robj = NULL; | ||
| 3604 | track->arrays[i].esize = 0x7F; | ||
| 3605 | } | ||
| 3606 | for (i = 0; i < track->num_texture; i++) { | ||
| 3607 | track->textures[i].compress_format = R100_TRACK_COMP_NONE; | ||
| 3608 | track->textures[i].pitch = 16536; | ||
| 3609 | track->textures[i].width = 16536; | ||
| 3610 | track->textures[i].height = 16536; | ||
| 3611 | track->textures[i].width_11 = 1 << 11; | ||
| 3612 | track->textures[i].height_11 = 1 << 11; | ||
| 3613 | track->textures[i].num_levels = 12; | ||
| 3614 | if (rdev->family <= CHIP_RS200) { | ||
| 3615 | track->textures[i].tex_coord_type = 0; | ||
| 3616 | track->textures[i].txdepth = 0; | ||
| 3617 | } else { | ||
| 3618 | track->textures[i].txdepth = 16; | ||
| 3619 | track->textures[i].tex_coord_type = 1; | ||
| 3620 | } | ||
| 3621 | track->textures[i].cpp = 64; | ||
| 3622 | track->textures[i].robj = NULL; | ||
| 3623 | /* CS IB emission code makes sure texture unit are disabled */ | ||
| 3624 | track->textures[i].enabled = false; | ||
| 3625 | track->textures[i].lookup_disable = false; | ||
| 3626 | track->textures[i].roundup_w = true; | ||
| 3627 | track->textures[i].roundup_h = true; | ||
| 3628 | if (track->separate_cube) | ||
| 3629 | for (face = 0; face < 5; face++) { | ||
| 3630 | track->textures[i].cube_info[face].robj = NULL; | ||
| 3631 | track->textures[i].cube_info[face].width = 16536; | ||
| 3632 | track->textures[i].cube_info[face].height = 16536; | ||
| 3633 | track->textures[i].cube_info[face].offset = 0; | ||
| 3634 | } | ||
| 3635 | } | ||
| 3636 | } | ||
| 3637 | |||
| 3638 | int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) | 3750 | int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) |
| 3639 | { | 3751 | { |
| 3640 | uint32_t scratch; | 3752 | uint32_t scratch; |
| @@ -3679,6 +3791,12 @@ void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 3679 | { | 3791 | { |
| 3680 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 3792 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 3681 | 3793 | ||
| 3794 | if (ring->rptr_save_reg) { | ||
| 3795 | u32 next_rptr = ring->wptr + 2 + 3; | ||
| 3796 | radeon_ring_write(ring, PACKET0(ring->rptr_save_reg, 0)); | ||
| 3797 | radeon_ring_write(ring, next_rptr); | ||
| 3798 | } | ||
| 3799 | |||
| 3682 | radeon_ring_write(ring, PACKET0(RADEON_CP_IB_BASE, 1)); | 3800 | radeon_ring_write(ring, PACKET0(RADEON_CP_IB_BASE, 1)); |
| 3683 | radeon_ring_write(ring, ib->gpu_addr); | 3801 | radeon_ring_write(ring, ib->gpu_addr); |
| 3684 | radeon_ring_write(ring, ib->length_dw); | 3802 | radeon_ring_write(ring, ib->length_dw); |
| @@ -3711,7 +3829,7 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 3711 | ib.ptr[6] = PACKET2(0); | 3829 | ib.ptr[6] = PACKET2(0); |
| 3712 | ib.ptr[7] = PACKET2(0); | 3830 | ib.ptr[7] = PACKET2(0); |
| 3713 | ib.length_dw = 8; | 3831 | ib.length_dw = 8; |
| 3714 | r = radeon_ib_schedule(rdev, &ib); | 3832 | r = radeon_ib_schedule(rdev, &ib, NULL); |
| 3715 | if (r) { | 3833 | if (r) { |
| 3716 | radeon_scratch_free(rdev, scratch); | 3834 | radeon_scratch_free(rdev, scratch); |
| 3717 | radeon_ib_free(rdev, &ib); | 3835 | radeon_ib_free(rdev, &ib); |
| @@ -3740,12 +3858,6 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 3740 | return r; | 3858 | return r; |
| 3741 | } | 3859 | } |
| 3742 | 3860 | ||
| 3743 | void r100_ib_fini(struct radeon_device *rdev) | ||
| 3744 | { | ||
| 3745 | radeon_ib_pool_suspend(rdev); | ||
| 3746 | radeon_ib_pool_fini(rdev); | ||
| 3747 | } | ||
| 3748 | |||
| 3749 | void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save) | 3861 | void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save) |
| 3750 | { | 3862 | { |
| 3751 | /* Shutdown CP we shouldn't need to do that but better be safe than | 3863 | /* Shutdown CP we shouldn't need to do that but better be safe than |
| @@ -3905,13 +4017,11 @@ static int r100_startup(struct radeon_device *rdev) | |||
| 3905 | return r; | 4017 | return r; |
| 3906 | } | 4018 | } |
| 3907 | 4019 | ||
| 3908 | r = radeon_ib_pool_start(rdev); | 4020 | r = radeon_ib_pool_init(rdev); |
| 3909 | if (r) | 4021 | if (r) { |
| 3910 | return r; | 4022 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 3911 | |||
| 3912 | r = radeon_ib_ring_tests(rdev); | ||
| 3913 | if (r) | ||
| 3914 | return r; | 4023 | return r; |
| 4024 | } | ||
| 3915 | 4025 | ||
| 3916 | return 0; | 4026 | return 0; |
| 3917 | } | 4027 | } |
| @@ -3948,7 +4058,6 @@ int r100_resume(struct radeon_device *rdev) | |||
| 3948 | 4058 | ||
| 3949 | int r100_suspend(struct radeon_device *rdev) | 4059 | int r100_suspend(struct radeon_device *rdev) |
| 3950 | { | 4060 | { |
| 3951 | radeon_ib_pool_suspend(rdev); | ||
| 3952 | r100_cp_disable(rdev); | 4061 | r100_cp_disable(rdev); |
| 3953 | radeon_wb_disable(rdev); | 4062 | radeon_wb_disable(rdev); |
| 3954 | r100_irq_disable(rdev); | 4063 | r100_irq_disable(rdev); |
| @@ -3961,7 +4070,7 @@ void r100_fini(struct radeon_device *rdev) | |||
| 3961 | { | 4070 | { |
| 3962 | r100_cp_fini(rdev); | 4071 | r100_cp_fini(rdev); |
| 3963 | radeon_wb_fini(rdev); | 4072 | radeon_wb_fini(rdev); |
| 3964 | r100_ib_fini(rdev); | 4073 | radeon_ib_pool_fini(rdev); |
| 3965 | radeon_gem_fini(rdev); | 4074 | radeon_gem_fini(rdev); |
| 3966 | if (rdev->flags & RADEON_IS_PCI) | 4075 | if (rdev->flags & RADEON_IS_PCI) |
| 3967 | r100_pci_gart_fini(rdev); | 4076 | r100_pci_gart_fini(rdev); |
| @@ -4068,20 +4177,14 @@ int r100_init(struct radeon_device *rdev) | |||
| 4068 | } | 4177 | } |
| 4069 | r100_set_safe_registers(rdev); | 4178 | r100_set_safe_registers(rdev); |
| 4070 | 4179 | ||
| 4071 | r = radeon_ib_pool_init(rdev); | ||
| 4072 | rdev->accel_working = true; | 4180 | rdev->accel_working = true; |
| 4073 | if (r) { | ||
| 4074 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 4075 | rdev->accel_working = false; | ||
| 4076 | } | ||
| 4077 | |||
| 4078 | r = r100_startup(rdev); | 4181 | r = r100_startup(rdev); |
| 4079 | if (r) { | 4182 | if (r) { |
| 4080 | /* Somethings want wront with the accel init stop accel */ | 4183 | /* Somethings want wront with the accel init stop accel */ |
| 4081 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 4184 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 4082 | r100_cp_fini(rdev); | 4185 | r100_cp_fini(rdev); |
| 4083 | radeon_wb_fini(rdev); | 4186 | radeon_wb_fini(rdev); |
| 4084 | r100_ib_fini(rdev); | 4187 | radeon_ib_pool_fini(rdev); |
| 4085 | radeon_irq_kms_fini(rdev); | 4188 | radeon_irq_kms_fini(rdev); |
| 4086 | if (rdev->flags & RADEON_IS_PCI) | 4189 | if (rdev->flags & RADEON_IS_PCI) |
| 4087 | r100_pci_gart_fini(rdev); | 4190 | r100_pci_gart_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c index a26144d01207..f0889259eb08 100644 --- a/drivers/gpu/drm/radeon/r200.c +++ b/drivers/gpu/drm/radeon/r200.c | |||
| @@ -85,7 +85,7 @@ int r200_copy_dma(struct radeon_device *rdev, | |||
| 85 | uint64_t src_offset, | 85 | uint64_t src_offset, |
| 86 | uint64_t dst_offset, | 86 | uint64_t dst_offset, |
| 87 | unsigned num_gpu_pages, | 87 | unsigned num_gpu_pages, |
| 88 | struct radeon_fence *fence) | 88 | struct radeon_fence **fence) |
| 89 | { | 89 | { |
| 90 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 90 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 91 | uint32_t size; | 91 | uint32_t size; |
| @@ -120,7 +120,7 @@ int r200_copy_dma(struct radeon_device *rdev, | |||
| 120 | radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); | 120 | radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); |
| 121 | radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE); | 121 | radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE); |
| 122 | if (fence) { | 122 | if (fence) { |
| 123 | r = radeon_fence_emit(rdev, fence); | 123 | r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); |
| 124 | } | 124 | } |
| 125 | radeon_ring_unlock_commit(rdev, ring); | 125 | radeon_ring_unlock_commit(rdev, ring); |
| 126 | return r; | 126 | return r; |
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 97722a33e513..646a1927dda7 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c | |||
| @@ -1391,13 +1391,11 @@ static int r300_startup(struct radeon_device *rdev) | |||
| 1391 | return r; | 1391 | return r; |
| 1392 | } | 1392 | } |
| 1393 | 1393 | ||
| 1394 | r = radeon_ib_pool_start(rdev); | 1394 | r = radeon_ib_pool_init(rdev); |
| 1395 | if (r) | 1395 | if (r) { |
| 1396 | return r; | 1396 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 1397 | |||
| 1398 | r = radeon_ib_ring_tests(rdev); | ||
| 1399 | if (r) | ||
| 1400 | return r; | 1397 | return r; |
| 1398 | } | ||
| 1401 | 1399 | ||
| 1402 | return 0; | 1400 | return 0; |
| 1403 | } | 1401 | } |
| @@ -1436,7 +1434,6 @@ int r300_resume(struct radeon_device *rdev) | |||
| 1436 | 1434 | ||
| 1437 | int r300_suspend(struct radeon_device *rdev) | 1435 | int r300_suspend(struct radeon_device *rdev) |
| 1438 | { | 1436 | { |
| 1439 | radeon_ib_pool_suspend(rdev); | ||
| 1440 | r100_cp_disable(rdev); | 1437 | r100_cp_disable(rdev); |
| 1441 | radeon_wb_disable(rdev); | 1438 | radeon_wb_disable(rdev); |
| 1442 | r100_irq_disable(rdev); | 1439 | r100_irq_disable(rdev); |
| @@ -1451,7 +1448,7 @@ void r300_fini(struct radeon_device *rdev) | |||
| 1451 | { | 1448 | { |
| 1452 | r100_cp_fini(rdev); | 1449 | r100_cp_fini(rdev); |
| 1453 | radeon_wb_fini(rdev); | 1450 | radeon_wb_fini(rdev); |
| 1454 | r100_ib_fini(rdev); | 1451 | radeon_ib_pool_fini(rdev); |
| 1455 | radeon_gem_fini(rdev); | 1452 | radeon_gem_fini(rdev); |
| 1456 | if (rdev->flags & RADEON_IS_PCIE) | 1453 | if (rdev->flags & RADEON_IS_PCIE) |
| 1457 | rv370_pcie_gart_fini(rdev); | 1454 | rv370_pcie_gart_fini(rdev); |
| @@ -1538,20 +1535,14 @@ int r300_init(struct radeon_device *rdev) | |||
| 1538 | } | 1535 | } |
| 1539 | r300_set_reg_safe(rdev); | 1536 | r300_set_reg_safe(rdev); |
| 1540 | 1537 | ||
| 1541 | r = radeon_ib_pool_init(rdev); | ||
| 1542 | rdev->accel_working = true; | 1538 | rdev->accel_working = true; |
| 1543 | if (r) { | ||
| 1544 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 1545 | rdev->accel_working = false; | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | r = r300_startup(rdev); | 1539 | r = r300_startup(rdev); |
| 1549 | if (r) { | 1540 | if (r) { |
| 1550 | /* Somethings want wront with the accel init stop accel */ | 1541 | /* Somethings want wront with the accel init stop accel */ |
| 1551 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 1542 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 1552 | r100_cp_fini(rdev); | 1543 | r100_cp_fini(rdev); |
| 1553 | radeon_wb_fini(rdev); | 1544 | radeon_wb_fini(rdev); |
| 1554 | r100_ib_fini(rdev); | 1545 | radeon_ib_pool_fini(rdev); |
| 1555 | radeon_irq_kms_fini(rdev); | 1546 | radeon_irq_kms_fini(rdev); |
| 1556 | if (rdev->flags & RADEON_IS_PCIE) | 1547 | if (rdev->flags & RADEON_IS_PCIE) |
| 1557 | rv370_pcie_gart_fini(rdev); | 1548 | rv370_pcie_gart_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 99137be7a300..f2f5bf6d339f 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c | |||
| @@ -275,13 +275,11 @@ static int r420_startup(struct radeon_device *rdev) | |||
| 275 | } | 275 | } |
| 276 | r420_cp_errata_init(rdev); | 276 | r420_cp_errata_init(rdev); |
| 277 | 277 | ||
| 278 | r = radeon_ib_pool_start(rdev); | 278 | r = radeon_ib_pool_init(rdev); |
| 279 | if (r) | 279 | if (r) { |
| 280 | return r; | 280 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 281 | |||
| 282 | r = radeon_ib_ring_tests(rdev); | ||
| 283 | if (r) | ||
| 284 | return r; | 281 | return r; |
| 282 | } | ||
| 285 | 283 | ||
| 286 | return 0; | 284 | return 0; |
| 287 | } | 285 | } |
| @@ -324,7 +322,6 @@ int r420_resume(struct radeon_device *rdev) | |||
| 324 | 322 | ||
| 325 | int r420_suspend(struct radeon_device *rdev) | 323 | int r420_suspend(struct radeon_device *rdev) |
| 326 | { | 324 | { |
| 327 | radeon_ib_pool_suspend(rdev); | ||
| 328 | r420_cp_errata_fini(rdev); | 325 | r420_cp_errata_fini(rdev); |
| 329 | r100_cp_disable(rdev); | 326 | r100_cp_disable(rdev); |
| 330 | radeon_wb_disable(rdev); | 327 | radeon_wb_disable(rdev); |
| @@ -340,7 +337,7 @@ void r420_fini(struct radeon_device *rdev) | |||
| 340 | { | 337 | { |
| 341 | r100_cp_fini(rdev); | 338 | r100_cp_fini(rdev); |
| 342 | radeon_wb_fini(rdev); | 339 | radeon_wb_fini(rdev); |
| 343 | r100_ib_fini(rdev); | 340 | radeon_ib_pool_fini(rdev); |
| 344 | radeon_gem_fini(rdev); | 341 | radeon_gem_fini(rdev); |
| 345 | if (rdev->flags & RADEON_IS_PCIE) | 342 | if (rdev->flags & RADEON_IS_PCIE) |
| 346 | rv370_pcie_gart_fini(rdev); | 343 | rv370_pcie_gart_fini(rdev); |
| @@ -438,20 +435,14 @@ int r420_init(struct radeon_device *rdev) | |||
| 438 | } | 435 | } |
| 439 | r420_set_reg_safe(rdev); | 436 | r420_set_reg_safe(rdev); |
| 440 | 437 | ||
| 441 | r = radeon_ib_pool_init(rdev); | ||
| 442 | rdev->accel_working = true; | 438 | rdev->accel_working = true; |
| 443 | if (r) { | ||
| 444 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 445 | rdev->accel_working = false; | ||
| 446 | } | ||
| 447 | |||
| 448 | r = r420_startup(rdev); | 439 | r = r420_startup(rdev); |
| 449 | if (r) { | 440 | if (r) { |
| 450 | /* Somethings want wront with the accel init stop accel */ | 441 | /* Somethings want wront with the accel init stop accel */ |
| 451 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 442 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 452 | r100_cp_fini(rdev); | 443 | r100_cp_fini(rdev); |
| 453 | radeon_wb_fini(rdev); | 444 | radeon_wb_fini(rdev); |
| 454 | r100_ib_fini(rdev); | 445 | radeon_ib_pool_fini(rdev); |
| 455 | radeon_irq_kms_fini(rdev); | 446 | radeon_irq_kms_fini(rdev); |
| 456 | if (rdev->flags & RADEON_IS_PCIE) | 447 | if (rdev->flags & RADEON_IS_PCIE) |
| 457 | rv370_pcie_gart_fini(rdev); | 448 | rv370_pcie_gart_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index b5cf8375cd25..079d3c52c08a 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c | |||
| @@ -203,13 +203,11 @@ static int r520_startup(struct radeon_device *rdev) | |||
| 203 | return r; | 203 | return r; |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | r = radeon_ib_pool_start(rdev); | 206 | r = radeon_ib_pool_init(rdev); |
| 207 | if (r) | 207 | if (r) { |
| 208 | return r; | 208 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 209 | |||
| 210 | r = radeon_ib_ring_tests(rdev); | ||
| 211 | if (r) | ||
| 212 | return r; | 209 | return r; |
| 210 | } | ||
| 213 | 211 | ||
| 214 | return 0; | 212 | return 0; |
| 215 | } | 213 | } |
| @@ -311,20 +309,14 @@ int r520_init(struct radeon_device *rdev) | |||
| 311 | return r; | 309 | return r; |
| 312 | rv515_set_safe_registers(rdev); | 310 | rv515_set_safe_registers(rdev); |
| 313 | 311 | ||
| 314 | r = radeon_ib_pool_init(rdev); | ||
| 315 | rdev->accel_working = true; | 312 | rdev->accel_working = true; |
| 316 | if (r) { | ||
| 317 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 318 | rdev->accel_working = false; | ||
| 319 | } | ||
| 320 | |||
| 321 | r = r520_startup(rdev); | 313 | r = r520_startup(rdev); |
| 322 | if (r) { | 314 | if (r) { |
| 323 | /* Somethings want wront with the accel init stop accel */ | 315 | /* Somethings want wront with the accel init stop accel */ |
| 324 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 316 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 325 | r100_cp_fini(rdev); | 317 | r100_cp_fini(rdev); |
| 326 | radeon_wb_fini(rdev); | 318 | radeon_wb_fini(rdev); |
| 327 | r100_ib_fini(rdev); | 319 | radeon_ib_pool_fini(rdev); |
| 328 | radeon_irq_kms_fini(rdev); | 320 | radeon_irq_kms_fini(rdev); |
| 329 | rv370_pcie_gart_fini(rdev); | 321 | rv370_pcie_gart_fini(rdev); |
| 330 | radeon_agp_fini(rdev); | 322 | radeon_agp_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index bff627293812..637280f541a3 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -709,6 +709,7 @@ void r600_hpd_init(struct radeon_device *rdev) | |||
| 709 | { | 709 | { |
| 710 | struct drm_device *dev = rdev->ddev; | 710 | struct drm_device *dev = rdev->ddev; |
| 711 | struct drm_connector *connector; | 711 | struct drm_connector *connector; |
| 712 | unsigned enable = 0; | ||
| 712 | 713 | ||
| 713 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 714 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 714 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 715 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| @@ -729,28 +730,22 @@ void r600_hpd_init(struct radeon_device *rdev) | |||
| 729 | switch (radeon_connector->hpd.hpd) { | 730 | switch (radeon_connector->hpd.hpd) { |
| 730 | case RADEON_HPD_1: | 731 | case RADEON_HPD_1: |
| 731 | WREG32(DC_HPD1_CONTROL, tmp); | 732 | WREG32(DC_HPD1_CONTROL, tmp); |
| 732 | rdev->irq.hpd[0] = true; | ||
| 733 | break; | 733 | break; |
| 734 | case RADEON_HPD_2: | 734 | case RADEON_HPD_2: |
| 735 | WREG32(DC_HPD2_CONTROL, tmp); | 735 | WREG32(DC_HPD2_CONTROL, tmp); |
| 736 | rdev->irq.hpd[1] = true; | ||
| 737 | break; | 736 | break; |
| 738 | case RADEON_HPD_3: | 737 | case RADEON_HPD_3: |
| 739 | WREG32(DC_HPD3_CONTROL, tmp); | 738 | WREG32(DC_HPD3_CONTROL, tmp); |
| 740 | rdev->irq.hpd[2] = true; | ||
| 741 | break; | 739 | break; |
| 742 | case RADEON_HPD_4: | 740 | case RADEON_HPD_4: |
| 743 | WREG32(DC_HPD4_CONTROL, tmp); | 741 | WREG32(DC_HPD4_CONTROL, tmp); |
| 744 | rdev->irq.hpd[3] = true; | ||
| 745 | break; | 742 | break; |
| 746 | /* DCE 3.2 */ | 743 | /* DCE 3.2 */ |
| 747 | case RADEON_HPD_5: | 744 | case RADEON_HPD_5: |
| 748 | WREG32(DC_HPD5_CONTROL, tmp); | 745 | WREG32(DC_HPD5_CONTROL, tmp); |
| 749 | rdev->irq.hpd[4] = true; | ||
| 750 | break; | 746 | break; |
| 751 | case RADEON_HPD_6: | 747 | case RADEON_HPD_6: |
| 752 | WREG32(DC_HPD6_CONTROL, tmp); | 748 | WREG32(DC_HPD6_CONTROL, tmp); |
| 753 | rdev->irq.hpd[5] = true; | ||
| 754 | break; | 749 | break; |
| 755 | default: | 750 | default: |
| 756 | break; | 751 | break; |
| @@ -759,85 +754,73 @@ void r600_hpd_init(struct radeon_device *rdev) | |||
| 759 | switch (radeon_connector->hpd.hpd) { | 754 | switch (radeon_connector->hpd.hpd) { |
| 760 | case RADEON_HPD_1: | 755 | case RADEON_HPD_1: |
| 761 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); | 756 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
| 762 | rdev->irq.hpd[0] = true; | ||
| 763 | break; | 757 | break; |
| 764 | case RADEON_HPD_2: | 758 | case RADEON_HPD_2: |
| 765 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); | 759 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
| 766 | rdev->irq.hpd[1] = true; | ||
| 767 | break; | 760 | break; |
| 768 | case RADEON_HPD_3: | 761 | case RADEON_HPD_3: |
| 769 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); | 762 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
| 770 | rdev->irq.hpd[2] = true; | ||
| 771 | break; | 763 | break; |
| 772 | default: | 764 | default: |
| 773 | break; | 765 | break; |
| 774 | } | 766 | } |
| 775 | } | 767 | } |
| 768 | enable |= 1 << radeon_connector->hpd.hpd; | ||
| 776 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 769 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
| 777 | } | 770 | } |
| 778 | if (rdev->irq.installed) | 771 | radeon_irq_kms_enable_hpd(rdev, enable); |
| 779 | r600_irq_set(rdev); | ||
| 780 | } | 772 | } |
| 781 | 773 | ||
| 782 | void r600_hpd_fini(struct radeon_device *rdev) | 774 | void r600_hpd_fini(struct radeon_device *rdev) |
| 783 | { | 775 | { |
| 784 | struct drm_device *dev = rdev->ddev; | 776 | struct drm_device *dev = rdev->ddev; |
| 785 | struct drm_connector *connector; | 777 | struct drm_connector *connector; |
| 778 | unsigned disable = 0; | ||
| 786 | 779 | ||
| 787 | if (ASIC_IS_DCE3(rdev)) { | 780 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 788 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 781 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 789 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 782 | if (ASIC_IS_DCE3(rdev)) { |
| 790 | switch (radeon_connector->hpd.hpd) { | 783 | switch (radeon_connector->hpd.hpd) { |
| 791 | case RADEON_HPD_1: | 784 | case RADEON_HPD_1: |
| 792 | WREG32(DC_HPD1_CONTROL, 0); | 785 | WREG32(DC_HPD1_CONTROL, 0); |
| 793 | rdev->irq.hpd[0] = false; | ||
| 794 | break; | 786 | break; |
| 795 | case RADEON_HPD_2: | 787 | case RADEON_HPD_2: |
| 796 | WREG32(DC_HPD2_CONTROL, 0); | 788 | WREG32(DC_HPD2_CONTROL, 0); |
| 797 | rdev->irq.hpd[1] = false; | ||
| 798 | break; | 789 | break; |
| 799 | case RADEON_HPD_3: | 790 | case RADEON_HPD_3: |
| 800 | WREG32(DC_HPD3_CONTROL, 0); | 791 | WREG32(DC_HPD3_CONTROL, 0); |
| 801 | rdev->irq.hpd[2] = false; | ||
| 802 | break; | 792 | break; |
| 803 | case RADEON_HPD_4: | 793 | case RADEON_HPD_4: |
| 804 | WREG32(DC_HPD4_CONTROL, 0); | 794 | WREG32(DC_HPD4_CONTROL, 0); |
| 805 | rdev->irq.hpd[3] = false; | ||
| 806 | break; | 795 | break; |
| 807 | /* DCE 3.2 */ | 796 | /* DCE 3.2 */ |
| 808 | case RADEON_HPD_5: | 797 | case RADEON_HPD_5: |
| 809 | WREG32(DC_HPD5_CONTROL, 0); | 798 | WREG32(DC_HPD5_CONTROL, 0); |
| 810 | rdev->irq.hpd[4] = false; | ||
| 811 | break; | 799 | break; |
| 812 | case RADEON_HPD_6: | 800 | case RADEON_HPD_6: |
| 813 | WREG32(DC_HPD6_CONTROL, 0); | 801 | WREG32(DC_HPD6_CONTROL, 0); |
| 814 | rdev->irq.hpd[5] = false; | ||
| 815 | break; | 802 | break; |
| 816 | default: | 803 | default: |
| 817 | break; | 804 | break; |
| 818 | } | 805 | } |
| 819 | } | 806 | } else { |
| 820 | } else { | ||
| 821 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 822 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 823 | switch (radeon_connector->hpd.hpd) { | 807 | switch (radeon_connector->hpd.hpd) { |
| 824 | case RADEON_HPD_1: | 808 | case RADEON_HPD_1: |
| 825 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); | 809 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); |
| 826 | rdev->irq.hpd[0] = false; | ||
| 827 | break; | 810 | break; |
| 828 | case RADEON_HPD_2: | 811 | case RADEON_HPD_2: |
| 829 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); | 812 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); |
| 830 | rdev->irq.hpd[1] = false; | ||
| 831 | break; | 813 | break; |
| 832 | case RADEON_HPD_3: | 814 | case RADEON_HPD_3: |
| 833 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); | 815 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); |
| 834 | rdev->irq.hpd[2] = false; | ||
| 835 | break; | 816 | break; |
| 836 | default: | 817 | default: |
| 837 | break; | 818 | break; |
| 838 | } | 819 | } |
| 839 | } | 820 | } |
| 821 | disable |= 1 << radeon_connector->hpd.hpd; | ||
| 840 | } | 822 | } |
| 823 | radeon_irq_kms_disable_hpd(rdev, disable); | ||
| 841 | } | 824 | } |
| 842 | 825 | ||
| 843 | /* | 826 | /* |
| @@ -1306,6 +1289,14 @@ int r600_gpu_soft_reset(struct radeon_device *rdev) | |||
| 1306 | RREG32(R_008014_GRBM_STATUS2)); | 1289 | RREG32(R_008014_GRBM_STATUS2)); |
| 1307 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", | 1290 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", |
| 1308 | RREG32(R_000E50_SRBM_STATUS)); | 1291 | RREG32(R_000E50_SRBM_STATUS)); |
| 1292 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 1293 | RREG32(CP_STALLED_STAT1)); | ||
| 1294 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 1295 | RREG32(CP_STALLED_STAT2)); | ||
| 1296 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 1297 | RREG32(CP_BUSY_STAT)); | ||
| 1298 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 1299 | RREG32(CP_STAT)); | ||
| 1309 | rv515_mc_stop(rdev, &save); | 1300 | rv515_mc_stop(rdev, &save); |
| 1310 | if (r600_mc_wait_for_idle(rdev)) { | 1301 | if (r600_mc_wait_for_idle(rdev)) { |
| 1311 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | 1302 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); |
| @@ -1349,6 +1340,14 @@ int r600_gpu_soft_reset(struct radeon_device *rdev) | |||
| 1349 | RREG32(R_008014_GRBM_STATUS2)); | 1340 | RREG32(R_008014_GRBM_STATUS2)); |
| 1350 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", | 1341 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", |
| 1351 | RREG32(R_000E50_SRBM_STATUS)); | 1342 | RREG32(R_000E50_SRBM_STATUS)); |
| 1343 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 1344 | RREG32(CP_STALLED_STAT1)); | ||
| 1345 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 1346 | RREG32(CP_STALLED_STAT2)); | ||
| 1347 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 1348 | RREG32(CP_BUSY_STAT)); | ||
| 1349 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 1350 | RREG32(CP_STAT)); | ||
| 1352 | rv515_mc_resume(rdev, &save); | 1351 | rv515_mc_resume(rdev, &save); |
| 1353 | return 0; | 1352 | return 0; |
| 1354 | } | 1353 | } |
| @@ -2172,18 +2171,29 @@ int r600_cp_resume(struct radeon_device *rdev) | |||
| 2172 | void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size) | 2171 | void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size) |
| 2173 | { | 2172 | { |
| 2174 | u32 rb_bufsz; | 2173 | u32 rb_bufsz; |
| 2174 | int r; | ||
| 2175 | 2175 | ||
| 2176 | /* Align ring size */ | 2176 | /* Align ring size */ |
| 2177 | rb_bufsz = drm_order(ring_size / 8); | 2177 | rb_bufsz = drm_order(ring_size / 8); |
| 2178 | ring_size = (1 << (rb_bufsz + 1)) * 4; | 2178 | ring_size = (1 << (rb_bufsz + 1)) * 4; |
| 2179 | ring->ring_size = ring_size; | 2179 | ring->ring_size = ring_size; |
| 2180 | ring->align_mask = 16 - 1; | 2180 | ring->align_mask = 16 - 1; |
| 2181 | |||
| 2182 | if (radeon_ring_supports_scratch_reg(rdev, ring)) { | ||
| 2183 | r = radeon_scratch_get(rdev, &ring->rptr_save_reg); | ||
| 2184 | if (r) { | ||
| 2185 | DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); | ||
| 2186 | ring->rptr_save_reg = 0; | ||
| 2187 | } | ||
| 2188 | } | ||
| 2181 | } | 2189 | } |
| 2182 | 2190 | ||
| 2183 | void r600_cp_fini(struct radeon_device *rdev) | 2191 | void r600_cp_fini(struct radeon_device *rdev) |
| 2184 | { | 2192 | { |
| 2193 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | ||
| 2185 | r600_cp_stop(rdev); | 2194 | r600_cp_stop(rdev); |
| 2186 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | 2195 | radeon_ring_fini(rdev, ring); |
| 2196 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 2187 | } | 2197 | } |
| 2188 | 2198 | ||
| 2189 | 2199 | ||
| @@ -2206,7 +2216,7 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2206 | { | 2216 | { |
| 2207 | uint32_t scratch; | 2217 | uint32_t scratch; |
| 2208 | uint32_t tmp = 0; | 2218 | uint32_t tmp = 0; |
| 2209 | unsigned i, ridx = radeon_ring_index(rdev, ring); | 2219 | unsigned i; |
| 2210 | int r; | 2220 | int r; |
| 2211 | 2221 | ||
| 2212 | r = radeon_scratch_get(rdev, &scratch); | 2222 | r = radeon_scratch_get(rdev, &scratch); |
| @@ -2217,7 +2227,7 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2217 | WREG32(scratch, 0xCAFEDEAD); | 2227 | WREG32(scratch, 0xCAFEDEAD); |
| 2218 | r = radeon_ring_lock(rdev, ring, 3); | 2228 | r = radeon_ring_lock(rdev, ring, 3); |
| 2219 | if (r) { | 2229 | if (r) { |
| 2220 | DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ridx, r); | 2230 | DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ring->idx, r); |
| 2221 | radeon_scratch_free(rdev, scratch); | 2231 | radeon_scratch_free(rdev, scratch); |
| 2222 | return r; | 2232 | return r; |
| 2223 | } | 2233 | } |
| @@ -2232,10 +2242,10 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2232 | DRM_UDELAY(1); | 2242 | DRM_UDELAY(1); |
| 2233 | } | 2243 | } |
| 2234 | if (i < rdev->usec_timeout) { | 2244 | if (i < rdev->usec_timeout) { |
| 2235 | DRM_INFO("ring test on %d succeeded in %d usecs\n", ridx, i); | 2245 | DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); |
| 2236 | } else { | 2246 | } else { |
| 2237 | DRM_ERROR("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n", | 2247 | DRM_ERROR("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n", |
| 2238 | ridx, scratch, tmp); | 2248 | ring->idx, scratch, tmp); |
| 2239 | r = -EINVAL; | 2249 | r = -EINVAL; |
| 2240 | } | 2250 | } |
| 2241 | radeon_scratch_free(rdev, scratch); | 2251 | radeon_scratch_free(rdev, scratch); |
| @@ -2309,34 +2319,21 @@ int r600_copy_blit(struct radeon_device *rdev, | |||
| 2309 | uint64_t src_offset, | 2319 | uint64_t src_offset, |
| 2310 | uint64_t dst_offset, | 2320 | uint64_t dst_offset, |
| 2311 | unsigned num_gpu_pages, | 2321 | unsigned num_gpu_pages, |
| 2312 | struct radeon_fence *fence) | 2322 | struct radeon_fence **fence) |
| 2313 | { | 2323 | { |
| 2324 | struct radeon_semaphore *sem = NULL; | ||
| 2314 | struct radeon_sa_bo *vb = NULL; | 2325 | struct radeon_sa_bo *vb = NULL; |
| 2315 | int r; | 2326 | int r; |
| 2316 | 2327 | ||
| 2317 | r = r600_blit_prepare_copy(rdev, num_gpu_pages, &vb); | 2328 | r = r600_blit_prepare_copy(rdev, num_gpu_pages, fence, &vb, &sem); |
| 2318 | if (r) { | 2329 | if (r) { |
| 2319 | return r; | 2330 | return r; |
| 2320 | } | 2331 | } |
| 2321 | r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages, vb); | 2332 | r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages, vb); |
| 2322 | r600_blit_done_copy(rdev, fence, vb); | 2333 | r600_blit_done_copy(rdev, fence, vb, sem); |
| 2323 | return 0; | 2334 | return 0; |
| 2324 | } | 2335 | } |
| 2325 | 2336 | ||
| 2326 | void r600_blit_suspend(struct radeon_device *rdev) | ||
| 2327 | { | ||
| 2328 | int r; | ||
| 2329 | |||
| 2330 | /* unpin shaders bo */ | ||
| 2331 | if (rdev->r600_blit.shader_obj) { | ||
| 2332 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
| 2333 | if (!r) { | ||
| 2334 | radeon_bo_unpin(rdev->r600_blit.shader_obj); | ||
| 2335 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
| 2336 | } | ||
| 2337 | } | ||
| 2338 | } | ||
| 2339 | |||
| 2340 | int r600_set_surface_reg(struct radeon_device *rdev, int reg, | 2337 | int r600_set_surface_reg(struct radeon_device *rdev, int reg, |
| 2341 | uint32_t tiling_flags, uint32_t pitch, | 2338 | uint32_t tiling_flags, uint32_t pitch, |
| 2342 | uint32_t offset, uint32_t obj_size) | 2339 | uint32_t offset, uint32_t obj_size) |
| @@ -2419,13 +2416,11 @@ int r600_startup(struct radeon_device *rdev) | |||
| 2419 | if (r) | 2416 | if (r) |
| 2420 | return r; | 2417 | return r; |
| 2421 | 2418 | ||
| 2422 | r = radeon_ib_pool_start(rdev); | 2419 | r = radeon_ib_pool_init(rdev); |
| 2423 | if (r) | 2420 | if (r) { |
| 2424 | return r; | 2421 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 2425 | |||
| 2426 | r = radeon_ib_ring_tests(rdev); | ||
| 2427 | if (r) | ||
| 2428 | return r; | 2422 | return r; |
| 2423 | } | ||
| 2429 | 2424 | ||
| 2430 | r = r600_audio_init(rdev); | 2425 | r = r600_audio_init(rdev); |
| 2431 | if (r) { | 2426 | if (r) { |
| @@ -2475,9 +2470,6 @@ int r600_resume(struct radeon_device *rdev) | |||
| 2475 | int r600_suspend(struct radeon_device *rdev) | 2470 | int r600_suspend(struct radeon_device *rdev) |
| 2476 | { | 2471 | { |
| 2477 | r600_audio_fini(rdev); | 2472 | r600_audio_fini(rdev); |
| 2478 | radeon_ib_pool_suspend(rdev); | ||
| 2479 | r600_blit_suspend(rdev); | ||
| 2480 | /* FIXME: we should wait for ring to be empty */ | ||
| 2481 | r600_cp_stop(rdev); | 2473 | r600_cp_stop(rdev); |
| 2482 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 2474 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
| 2483 | r600_irq_suspend(rdev); | 2475 | r600_irq_suspend(rdev); |
| @@ -2559,20 +2551,14 @@ int r600_init(struct radeon_device *rdev) | |||
| 2559 | if (r) | 2551 | if (r) |
| 2560 | return r; | 2552 | return r; |
| 2561 | 2553 | ||
| 2562 | r = radeon_ib_pool_init(rdev); | ||
| 2563 | rdev->accel_working = true; | 2554 | rdev->accel_working = true; |
| 2564 | if (r) { | ||
| 2565 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 2566 | rdev->accel_working = false; | ||
| 2567 | } | ||
| 2568 | |||
| 2569 | r = r600_startup(rdev); | 2555 | r = r600_startup(rdev); |
| 2570 | if (r) { | 2556 | if (r) { |
| 2571 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 2557 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
| 2572 | r600_cp_fini(rdev); | 2558 | r600_cp_fini(rdev); |
| 2573 | r600_irq_fini(rdev); | 2559 | r600_irq_fini(rdev); |
| 2574 | radeon_wb_fini(rdev); | 2560 | radeon_wb_fini(rdev); |
| 2575 | r100_ib_fini(rdev); | 2561 | radeon_ib_pool_fini(rdev); |
| 2576 | radeon_irq_kms_fini(rdev); | 2562 | radeon_irq_kms_fini(rdev); |
| 2577 | r600_pcie_gart_fini(rdev); | 2563 | r600_pcie_gart_fini(rdev); |
| 2578 | rdev->accel_working = false; | 2564 | rdev->accel_working = false; |
| @@ -2588,7 +2574,7 @@ void r600_fini(struct radeon_device *rdev) | |||
| 2588 | r600_cp_fini(rdev); | 2574 | r600_cp_fini(rdev); |
| 2589 | r600_irq_fini(rdev); | 2575 | r600_irq_fini(rdev); |
| 2590 | radeon_wb_fini(rdev); | 2576 | radeon_wb_fini(rdev); |
| 2591 | r100_ib_fini(rdev); | 2577 | radeon_ib_pool_fini(rdev); |
| 2592 | radeon_irq_kms_fini(rdev); | 2578 | radeon_irq_kms_fini(rdev); |
| 2593 | r600_pcie_gart_fini(rdev); | 2579 | r600_pcie_gart_fini(rdev); |
| 2594 | r600_vram_scratch_fini(rdev); | 2580 | r600_vram_scratch_fini(rdev); |
| @@ -2607,9 +2593,24 @@ void r600_fini(struct radeon_device *rdev) | |||
| 2607 | */ | 2593 | */ |
| 2608 | void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | 2594 | void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) |
| 2609 | { | 2595 | { |
| 2610 | struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; | 2596 | struct radeon_ring *ring = &rdev->ring[ib->ring]; |
| 2597 | u32 next_rptr; | ||
| 2598 | |||
| 2599 | if (ring->rptr_save_reg) { | ||
| 2600 | next_rptr = ring->wptr + 3 + 4; | ||
| 2601 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
| 2602 | radeon_ring_write(ring, ((ring->rptr_save_reg - | ||
| 2603 | PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); | ||
| 2604 | radeon_ring_write(ring, next_rptr); | ||
| 2605 | } else if (rdev->wb.enabled) { | ||
| 2606 | next_rptr = ring->wptr + 5 + 4; | ||
| 2607 | radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3)); | ||
| 2608 | radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); | ||
| 2609 | radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18)); | ||
| 2610 | radeon_ring_write(ring, next_rptr); | ||
| 2611 | radeon_ring_write(ring, 0); | ||
| 2612 | } | ||
| 2611 | 2613 | ||
| 2612 | /* FIXME: implement */ | ||
| 2613 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); | 2614 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
| 2614 | radeon_ring_write(ring, | 2615 | radeon_ring_write(ring, |
| 2615 | #ifdef __BIG_ENDIAN | 2616 | #ifdef __BIG_ENDIAN |
| @@ -2627,7 +2628,6 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2627 | uint32_t tmp = 0; | 2628 | uint32_t tmp = 0; |
| 2628 | unsigned i; | 2629 | unsigned i; |
| 2629 | int r; | 2630 | int r; |
| 2630 | int ring_index = radeon_ring_index(rdev, ring); | ||
| 2631 | 2631 | ||
| 2632 | r = radeon_scratch_get(rdev, &scratch); | 2632 | r = radeon_scratch_get(rdev, &scratch); |
| 2633 | if (r) { | 2633 | if (r) { |
| @@ -2635,7 +2635,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2635 | return r; | 2635 | return r; |
| 2636 | } | 2636 | } |
| 2637 | WREG32(scratch, 0xCAFEDEAD); | 2637 | WREG32(scratch, 0xCAFEDEAD); |
| 2638 | r = radeon_ib_get(rdev, ring_index, &ib, 256); | 2638 | r = radeon_ib_get(rdev, ring->idx, &ib, 256); |
| 2639 | if (r) { | 2639 | if (r) { |
| 2640 | DRM_ERROR("radeon: failed to get ib (%d).\n", r); | 2640 | DRM_ERROR("radeon: failed to get ib (%d).\n", r); |
| 2641 | return r; | 2641 | return r; |
| @@ -2644,7 +2644,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2644 | ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); | 2644 | ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); |
| 2645 | ib.ptr[2] = 0xDEADBEEF; | 2645 | ib.ptr[2] = 0xDEADBEEF; |
| 2646 | ib.length_dw = 3; | 2646 | ib.length_dw = 3; |
| 2647 | r = radeon_ib_schedule(rdev, &ib); | 2647 | r = radeon_ib_schedule(rdev, &ib, NULL); |
| 2648 | if (r) { | 2648 | if (r) { |
| 2649 | radeon_scratch_free(rdev, scratch); | 2649 | radeon_scratch_free(rdev, scratch); |
| 2650 | radeon_ib_free(rdev, &ib); | 2650 | radeon_ib_free(rdev, &ib); |
| @@ -2857,7 +2857,6 @@ void r600_disable_interrupts(struct radeon_device *rdev) | |||
| 2857 | WREG32(IH_RB_RPTR, 0); | 2857 | WREG32(IH_RB_RPTR, 0); |
| 2858 | WREG32(IH_RB_WPTR, 0); | 2858 | WREG32(IH_RB_WPTR, 0); |
| 2859 | rdev->ih.enabled = false; | 2859 | rdev->ih.enabled = false; |
| 2860 | rdev->ih.wptr = 0; | ||
| 2861 | rdev->ih.rptr = 0; | 2860 | rdev->ih.rptr = 0; |
| 2862 | } | 2861 | } |
| 2863 | 2862 | ||
| @@ -3042,18 +3041,18 @@ int r600_irq_set(struct radeon_device *rdev) | |||
| 3042 | hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; | 3041 | hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; |
| 3043 | } | 3042 | } |
| 3044 | 3043 | ||
| 3045 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 3044 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 3046 | DRM_DEBUG("r600_irq_set: sw int\n"); | 3045 | DRM_DEBUG("r600_irq_set: sw int\n"); |
| 3047 | cp_int_cntl |= RB_INT_ENABLE; | 3046 | cp_int_cntl |= RB_INT_ENABLE; |
| 3048 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | 3047 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; |
| 3049 | } | 3048 | } |
| 3050 | if (rdev->irq.crtc_vblank_int[0] || | 3049 | if (rdev->irq.crtc_vblank_int[0] || |
| 3051 | rdev->irq.pflip[0]) { | 3050 | atomic_read(&rdev->irq.pflip[0])) { |
| 3052 | DRM_DEBUG("r600_irq_set: vblank 0\n"); | 3051 | DRM_DEBUG("r600_irq_set: vblank 0\n"); |
| 3053 | mode_int |= D1MODE_VBLANK_INT_MASK; | 3052 | mode_int |= D1MODE_VBLANK_INT_MASK; |
| 3054 | } | 3053 | } |
| 3055 | if (rdev->irq.crtc_vblank_int[1] || | 3054 | if (rdev->irq.crtc_vblank_int[1] || |
| 3056 | rdev->irq.pflip[1]) { | 3055 | atomic_read(&rdev->irq.pflip[1])) { |
| 3057 | DRM_DEBUG("r600_irq_set: vblank 1\n"); | 3056 | DRM_DEBUG("r600_irq_set: vblank 1\n"); |
| 3058 | mode_int |= D2MODE_VBLANK_INT_MASK; | 3057 | mode_int |= D2MODE_VBLANK_INT_MASK; |
| 3059 | } | 3058 | } |
| @@ -3309,7 +3308,6 @@ int r600_irq_process(struct radeon_device *rdev) | |||
| 3309 | u32 rptr; | 3308 | u32 rptr; |
| 3310 | u32 src_id, src_data; | 3309 | u32 src_id, src_data; |
| 3311 | u32 ring_index; | 3310 | u32 ring_index; |
| 3312 | unsigned long flags; | ||
| 3313 | bool queue_hotplug = false; | 3311 | bool queue_hotplug = false; |
| 3314 | bool queue_hdmi = false; | 3312 | bool queue_hdmi = false; |
| 3315 | 3313 | ||
| @@ -3321,24 +3319,21 @@ int r600_irq_process(struct radeon_device *rdev) | |||
| 3321 | RREG32(IH_RB_WPTR); | 3319 | RREG32(IH_RB_WPTR); |
| 3322 | 3320 | ||
| 3323 | wptr = r600_get_ih_wptr(rdev); | 3321 | wptr = r600_get_ih_wptr(rdev); |
| 3324 | rptr = rdev->ih.rptr; | ||
| 3325 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | ||
| 3326 | |||
| 3327 | spin_lock_irqsave(&rdev->ih.lock, flags); | ||
| 3328 | 3322 | ||
| 3329 | if (rptr == wptr) { | 3323 | restart_ih: |
| 3330 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | 3324 | /* is somebody else already processing irqs? */ |
| 3325 | if (atomic_xchg(&rdev->ih.lock, 1)) | ||
| 3331 | return IRQ_NONE; | 3326 | return IRQ_NONE; |
| 3332 | } | ||
| 3333 | 3327 | ||
| 3334 | restart_ih: | 3328 | rptr = rdev->ih.rptr; |
| 3329 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | ||
| 3330 | |||
| 3335 | /* Order reading of wptr vs. reading of IH ring data */ | 3331 | /* Order reading of wptr vs. reading of IH ring data */ |
| 3336 | rmb(); | 3332 | rmb(); |
| 3337 | 3333 | ||
| 3338 | /* display interrupts */ | 3334 | /* display interrupts */ |
| 3339 | r600_irq_ack(rdev); | 3335 | r600_irq_ack(rdev); |
| 3340 | 3336 | ||
| 3341 | rdev->ih.wptr = wptr; | ||
| 3342 | while (rptr != wptr) { | 3337 | while (rptr != wptr) { |
| 3343 | /* wptr/rptr are in bytes! */ | 3338 | /* wptr/rptr are in bytes! */ |
| 3344 | ring_index = rptr / 4; | 3339 | ring_index = rptr / 4; |
| @@ -3355,7 +3350,7 @@ restart_ih: | |||
| 3355 | rdev->pm.vblank_sync = true; | 3350 | rdev->pm.vblank_sync = true; |
| 3356 | wake_up(&rdev->irq.vblank_queue); | 3351 | wake_up(&rdev->irq.vblank_queue); |
| 3357 | } | 3352 | } |
| 3358 | if (rdev->irq.pflip[0]) | 3353 | if (atomic_read(&rdev->irq.pflip[0])) |
| 3359 | radeon_crtc_handle_flip(rdev, 0); | 3354 | radeon_crtc_handle_flip(rdev, 0); |
| 3360 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | 3355 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; |
| 3361 | DRM_DEBUG("IH: D1 vblank\n"); | 3356 | DRM_DEBUG("IH: D1 vblank\n"); |
| @@ -3381,7 +3376,7 @@ restart_ih: | |||
| 3381 | rdev->pm.vblank_sync = true; | 3376 | rdev->pm.vblank_sync = true; |
| 3382 | wake_up(&rdev->irq.vblank_queue); | 3377 | wake_up(&rdev->irq.vblank_queue); |
| 3383 | } | 3378 | } |
| 3384 | if (rdev->irq.pflip[1]) | 3379 | if (atomic_read(&rdev->irq.pflip[1])) |
| 3385 | radeon_crtc_handle_flip(rdev, 1); | 3380 | radeon_crtc_handle_flip(rdev, 1); |
| 3386 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; | 3381 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; |
| 3387 | DRM_DEBUG("IH: D2 vblank\n"); | 3382 | DRM_DEBUG("IH: D2 vblank\n"); |
| @@ -3480,7 +3475,6 @@ restart_ih: | |||
| 3480 | break; | 3475 | break; |
| 3481 | case 233: /* GUI IDLE */ | 3476 | case 233: /* GUI IDLE */ |
| 3482 | DRM_DEBUG("IH: GUI idle\n"); | 3477 | DRM_DEBUG("IH: GUI idle\n"); |
| 3483 | rdev->pm.gui_idle = true; | ||
| 3484 | wake_up(&rdev->irq.idle_queue); | 3478 | wake_up(&rdev->irq.idle_queue); |
| 3485 | break; | 3479 | break; |
| 3486 | default: | 3480 | default: |
| @@ -3492,17 +3486,19 @@ restart_ih: | |||
| 3492 | rptr += 16; | 3486 | rptr += 16; |
| 3493 | rptr &= rdev->ih.ptr_mask; | 3487 | rptr &= rdev->ih.ptr_mask; |
| 3494 | } | 3488 | } |
| 3495 | /* make sure wptr hasn't changed while processing */ | ||
| 3496 | wptr = r600_get_ih_wptr(rdev); | ||
| 3497 | if (wptr != rdev->ih.wptr) | ||
| 3498 | goto restart_ih; | ||
| 3499 | if (queue_hotplug) | 3489 | if (queue_hotplug) |
| 3500 | schedule_work(&rdev->hotplug_work); | 3490 | schedule_work(&rdev->hotplug_work); |
| 3501 | if (queue_hdmi) | 3491 | if (queue_hdmi) |
| 3502 | schedule_work(&rdev->audio_work); | 3492 | schedule_work(&rdev->audio_work); |
| 3503 | rdev->ih.rptr = rptr; | 3493 | rdev->ih.rptr = rptr; |
| 3504 | WREG32(IH_RB_RPTR, rdev->ih.rptr); | 3494 | WREG32(IH_RB_RPTR, rdev->ih.rptr); |
| 3505 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | 3495 | atomic_set(&rdev->ih.lock, 0); |
| 3496 | |||
| 3497 | /* make sure wptr hasn't changed while processing */ | ||
| 3498 | wptr = r600_get_ih_wptr(rdev); | ||
| 3499 | if (wptr != rptr) | ||
| 3500 | goto restart_ih; | ||
| 3501 | |||
| 3506 | return IRQ_HANDLED; | 3502 | return IRQ_HANDLED; |
| 3507 | } | 3503 | } |
| 3508 | 3504 | ||
| @@ -3685,6 +3681,8 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) | |||
| 3685 | { | 3681 | { |
| 3686 | u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp; | 3682 | u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp; |
| 3687 | u16 link_cntl2; | 3683 | u16 link_cntl2; |
| 3684 | u32 mask; | ||
| 3685 | int ret; | ||
| 3688 | 3686 | ||
| 3689 | if (radeon_pcie_gen2 == 0) | 3687 | if (radeon_pcie_gen2 == 0) |
| 3690 | return; | 3688 | return; |
| @@ -3703,6 +3701,15 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) | |||
| 3703 | if (rdev->family <= CHIP_R600) | 3701 | if (rdev->family <= CHIP_R600) |
| 3704 | return; | 3702 | return; |
| 3705 | 3703 | ||
| 3704 | ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); | ||
| 3705 | if (ret != 0) | ||
| 3706 | return; | ||
| 3707 | |||
| 3708 | if (!(mask & DRM_PCIE_SPEED_50)) | ||
| 3709 | return; | ||
| 3710 | |||
| 3711 | DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); | ||
| 3712 | |||
| 3706 | /* 55 nm r6xx asics */ | 3713 | /* 55 nm r6xx asics */ |
| 3707 | if ((rdev->family == CHIP_RV670) || | 3714 | if ((rdev->family == CHIP_RV670) || |
| 3708 | (rdev->family == CHIP_RV620) || | 3715 | (rdev->family == CHIP_RV620) || |
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index 03b6e0d3d503..2bef8549ddfe 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
| @@ -512,7 +512,8 @@ int r600_blit_init(struct radeon_device *rdev) | |||
| 512 | rdev->r600_blit.primitives.draw_auto = draw_auto; | 512 | rdev->r600_blit.primitives.draw_auto = draw_auto; |
| 513 | rdev->r600_blit.primitives.set_default_state = set_default_state; | 513 | rdev->r600_blit.primitives.set_default_state = set_default_state; |
| 514 | 514 | ||
| 515 | rdev->r600_blit.ring_size_common = 40; /* shaders + def state */ | 515 | rdev->r600_blit.ring_size_common = 8; /* sync semaphore */ |
| 516 | rdev->r600_blit.ring_size_common += 40; /* shaders + def state */ | ||
| 516 | rdev->r600_blit.ring_size_common += 5; /* done copy */ | 517 | rdev->r600_blit.ring_size_common += 5; /* done copy */ |
| 517 | rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ | 518 | rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ |
| 518 | 519 | ||
| @@ -523,10 +524,6 @@ int r600_blit_init(struct radeon_device *rdev) | |||
| 523 | 524 | ||
| 524 | rdev->r600_blit.max_dim = 8192; | 525 | rdev->r600_blit.max_dim = 8192; |
| 525 | 526 | ||
| 526 | /* pin copy shader into vram if already initialized */ | ||
| 527 | if (rdev->r600_blit.shader_obj) | ||
| 528 | goto done; | ||
| 529 | |||
| 530 | rdev->r600_blit.state_offset = 0; | 527 | rdev->r600_blit.state_offset = 0; |
| 531 | 528 | ||
| 532 | if (rdev->family >= CHIP_RV770) | 529 | if (rdev->family >= CHIP_RV770) |
| @@ -551,11 +548,26 @@ int r600_blit_init(struct radeon_device *rdev) | |||
| 551 | obj_size += r6xx_ps_size * 4; | 548 | obj_size += r6xx_ps_size * 4; |
| 552 | obj_size = ALIGN(obj_size, 256); | 549 | obj_size = ALIGN(obj_size, 256); |
| 553 | 550 | ||
| 554 | r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, | 551 | /* pin copy shader into vram if not already initialized */ |
| 555 | NULL, &rdev->r600_blit.shader_obj); | 552 | if (rdev->r600_blit.shader_obj == NULL) { |
| 556 | if (r) { | 553 | r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, |
| 557 | DRM_ERROR("r600 failed to allocate shader\n"); | 554 | RADEON_GEM_DOMAIN_VRAM, |
| 558 | return r; | 555 | NULL, &rdev->r600_blit.shader_obj); |
| 556 | if (r) { | ||
| 557 | DRM_ERROR("r600 failed to allocate shader\n"); | ||
| 558 | return r; | ||
| 559 | } | ||
| 560 | |||
| 561 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
| 562 | if (unlikely(r != 0)) | ||
| 563 | return r; | ||
| 564 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | ||
| 565 | &rdev->r600_blit.shader_gpu_addr); | ||
| 566 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
| 567 | if (r) { | ||
| 568 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | ||
| 569 | return r; | ||
| 570 | } | ||
| 559 | } | 571 | } |
| 560 | 572 | ||
| 561 | DRM_DEBUG("r6xx blit allocated bo %08x vs %08x ps %08x\n", | 573 | DRM_DEBUG("r6xx blit allocated bo %08x vs %08x ps %08x\n", |
| @@ -586,17 +598,6 @@ int r600_blit_init(struct radeon_device *rdev) | |||
| 586 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); | 598 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); |
| 587 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | 599 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); |
| 588 | 600 | ||
| 589 | done: | ||
| 590 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
| 591 | if (unlikely(r != 0)) | ||
| 592 | return r; | ||
| 593 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | ||
| 594 | &rdev->r600_blit.shader_gpu_addr); | ||
| 595 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
| 596 | if (r) { | ||
| 597 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | ||
| 598 | return r; | ||
| 599 | } | ||
| 600 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); | 601 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); |
| 601 | return 0; | 602 | return 0; |
| 602 | } | 603 | } |
| @@ -666,7 +667,8 @@ static unsigned r600_blit_create_rect(unsigned num_gpu_pages, | |||
| 666 | 667 | ||
| 667 | 668 | ||
| 668 | int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, | 669 | int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, |
| 669 | struct radeon_sa_bo **vb) | 670 | struct radeon_fence **fence, struct radeon_sa_bo **vb, |
| 671 | struct radeon_semaphore **sem) | ||
| 670 | { | 672 | { |
| 671 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 673 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 672 | int r; | 674 | int r; |
| @@ -689,34 +691,50 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, | |||
| 689 | return r; | 691 | return r; |
| 690 | } | 692 | } |
| 691 | 693 | ||
| 694 | r = radeon_semaphore_create(rdev, sem); | ||
| 695 | if (r) { | ||
| 696 | radeon_sa_bo_free(rdev, vb, NULL); | ||
| 697 | return r; | ||
| 698 | } | ||
| 699 | |||
| 692 | /* calculate number of loops correctly */ | 700 | /* calculate number of loops correctly */ |
| 693 | ring_size = num_loops * dwords_per_loop; | 701 | ring_size = num_loops * dwords_per_loop; |
| 694 | ring_size += rdev->r600_blit.ring_size_common; | 702 | ring_size += rdev->r600_blit.ring_size_common; |
| 695 | r = radeon_ring_lock(rdev, ring, ring_size); | 703 | r = radeon_ring_lock(rdev, ring, ring_size); |
| 696 | if (r) { | 704 | if (r) { |
| 697 | radeon_sa_bo_free(rdev, vb, NULL); | 705 | radeon_sa_bo_free(rdev, vb, NULL); |
| 706 | radeon_semaphore_free(rdev, sem, NULL); | ||
| 698 | return r; | 707 | return r; |
| 699 | } | 708 | } |
| 700 | 709 | ||
| 710 | if (radeon_fence_need_sync(*fence, RADEON_RING_TYPE_GFX_INDEX)) { | ||
| 711 | radeon_semaphore_sync_rings(rdev, *sem, (*fence)->ring, | ||
| 712 | RADEON_RING_TYPE_GFX_INDEX); | ||
| 713 | radeon_fence_note_sync(*fence, RADEON_RING_TYPE_GFX_INDEX); | ||
| 714 | } else { | ||
| 715 | radeon_semaphore_free(rdev, sem, NULL); | ||
| 716 | } | ||
| 717 | |||
| 701 | rdev->r600_blit.primitives.set_default_state(rdev); | 718 | rdev->r600_blit.primitives.set_default_state(rdev); |
| 702 | rdev->r600_blit.primitives.set_shaders(rdev); | 719 | rdev->r600_blit.primitives.set_shaders(rdev); |
| 703 | return 0; | 720 | return 0; |
| 704 | } | 721 | } |
| 705 | 722 | ||
| 706 | void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence, | 723 | void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence **fence, |
| 707 | struct radeon_sa_bo *vb) | 724 | struct radeon_sa_bo *vb, struct radeon_semaphore *sem) |
| 708 | { | 725 | { |
| 709 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 726 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 710 | int r; | 727 | int r; |
| 711 | 728 | ||
| 712 | r = radeon_fence_emit(rdev, fence); | 729 | r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); |
| 713 | if (r) { | 730 | if (r) { |
| 714 | radeon_ring_unlock_undo(rdev, ring); | 731 | radeon_ring_unlock_undo(rdev, ring); |
| 715 | return; | 732 | return; |
| 716 | } | 733 | } |
| 717 | 734 | ||
| 718 | radeon_ring_unlock_commit(rdev, ring); | 735 | radeon_ring_unlock_commit(rdev, ring); |
| 719 | radeon_sa_bo_free(rdev, &vb, fence); | 736 | radeon_sa_bo_free(rdev, &vb, *fence); |
| 737 | radeon_semaphore_free(rdev, &sem, *fence); | ||
| 720 | } | 738 | } |
| 721 | 739 | ||
| 722 | void r600_kms_blit_copy(struct radeon_device *rdev, | 740 | void r600_kms_blit_copy(struct radeon_device *rdev, |
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 82a0a4c919c0..e3558c3ef24a 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
| @@ -519,8 +519,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder) | |||
| 519 | 519 | ||
| 520 | if (rdev->irq.installed) { | 520 | if (rdev->irq.installed) { |
| 521 | /* if irq is available use it */ | 521 | /* if irq is available use it */ |
| 522 | rdev->irq.afmt[dig->afmt->id] = true; | 522 | radeon_irq_kms_enable_afmt(rdev, dig->afmt->id); |
| 523 | radeon_irq_set(rdev); | ||
| 524 | } | 523 | } |
| 525 | 524 | ||
| 526 | dig->afmt->enabled = true; | 525 | dig->afmt->enabled = true; |
| @@ -556,8 +555,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder) | |||
| 556 | offset, radeon_encoder->encoder_id); | 555 | offset, radeon_encoder->encoder_id); |
| 557 | 556 | ||
| 558 | /* disable irq */ | 557 | /* disable irq */ |
| 559 | rdev->irq.afmt[dig->afmt->id] = false; | 558 | radeon_irq_kms_disable_afmt(rdev, dig->afmt->id); |
| 560 | radeon_irq_set(rdev); | ||
| 561 | 559 | ||
| 562 | /* Older chipsets not handled by AtomBIOS */ | 560 | /* Older chipsets not handled by AtomBIOS */ |
| 563 | if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { | 561 | if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { |
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 025fd5b6c08c..4b116ae75fc2 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
| @@ -153,6 +153,9 @@ | |||
| 153 | 153 | ||
| 154 | #define CONFIG_MEMSIZE 0x5428 | 154 | #define CONFIG_MEMSIZE 0x5428 |
| 155 | #define CONFIG_CNTL 0x5424 | 155 | #define CONFIG_CNTL 0x5424 |
| 156 | #define CP_STALLED_STAT1 0x8674 | ||
| 157 | #define CP_STALLED_STAT2 0x8678 | ||
| 158 | #define CP_BUSY_STAT 0x867C | ||
| 156 | #define CP_STAT 0x8680 | 159 | #define CP_STAT 0x8680 |
| 157 | #define CP_COHER_BASE 0x85F8 | 160 | #define CP_COHER_BASE 0x85F8 |
| 158 | #define CP_DEBUG 0xC1FC | 161 | #define CP_DEBUG 0xC1FC |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index fefcca55c1eb..5431af292408 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -113,7 +113,6 @@ extern int radeon_lockup_timeout; | |||
| 113 | 113 | ||
| 114 | /* fence seq are set to this number when signaled */ | 114 | /* fence seq are set to this number when signaled */ |
| 115 | #define RADEON_FENCE_SIGNALED_SEQ 0LL | 115 | #define RADEON_FENCE_SIGNALED_SEQ 0LL |
| 116 | #define RADEON_FENCE_NOTEMITED_SEQ (~0LL) | ||
| 117 | 116 | ||
| 118 | /* internal ring indices */ | 117 | /* internal ring indices */ |
| 119 | /* r1xx+ has gfx CP ring */ | 118 | /* r1xx+ has gfx CP ring */ |
| @@ -160,48 +159,6 @@ static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len) | |||
| 160 | #endif | 159 | #endif |
| 161 | bool radeon_get_bios(struct radeon_device *rdev); | 160 | bool radeon_get_bios(struct radeon_device *rdev); |
| 162 | 161 | ||
| 163 | |||
| 164 | /* | ||
| 165 | * Mutex which allows recursive locking from the same process. | ||
| 166 | */ | ||
| 167 | struct radeon_mutex { | ||
| 168 | struct mutex mutex; | ||
| 169 | struct task_struct *owner; | ||
| 170 | int level; | ||
| 171 | }; | ||
| 172 | |||
| 173 | static inline void radeon_mutex_init(struct radeon_mutex *mutex) | ||
| 174 | { | ||
| 175 | mutex_init(&mutex->mutex); | ||
| 176 | mutex->owner = NULL; | ||
| 177 | mutex->level = 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | static inline void radeon_mutex_lock(struct radeon_mutex *mutex) | ||
| 181 | { | ||
| 182 | if (mutex_trylock(&mutex->mutex)) { | ||
| 183 | /* The mutex was unlocked before, so it's ours now */ | ||
| 184 | mutex->owner = current; | ||
| 185 | } else if (mutex->owner != current) { | ||
| 186 | /* Another process locked the mutex, take it */ | ||
| 187 | mutex_lock(&mutex->mutex); | ||
| 188 | mutex->owner = current; | ||
| 189 | } | ||
| 190 | /* Otherwise the mutex was already locked by this process */ | ||
| 191 | |||
| 192 | mutex->level++; | ||
| 193 | } | ||
| 194 | |||
| 195 | static inline void radeon_mutex_unlock(struct radeon_mutex *mutex) | ||
| 196 | { | ||
| 197 | if (--mutex->level > 0) | ||
| 198 | return; | ||
| 199 | |||
| 200 | mutex->owner = NULL; | ||
| 201 | mutex_unlock(&mutex->mutex); | ||
| 202 | } | ||
| 203 | |||
| 204 | |||
| 205 | /* | 162 | /* |
| 206 | * Dummy page | 163 | * Dummy page |
| 207 | */ | 164 | */ |
| @@ -258,8 +215,8 @@ struct radeon_fence_driver { | |||
| 258 | uint32_t scratch_reg; | 215 | uint32_t scratch_reg; |
| 259 | uint64_t gpu_addr; | 216 | uint64_t gpu_addr; |
| 260 | volatile uint32_t *cpu_addr; | 217 | volatile uint32_t *cpu_addr; |
| 261 | /* seq is protected by ring emission lock */ | 218 | /* sync_seq is protected by ring emission lock */ |
| 262 | uint64_t seq; | 219 | uint64_t sync_seq[RADEON_NUM_RINGS]; |
| 263 | atomic64_t last_seq; | 220 | atomic64_t last_seq; |
| 264 | unsigned long last_activity; | 221 | unsigned long last_activity; |
| 265 | bool initialized; | 222 | bool initialized; |
| @@ -277,19 +234,39 @@ struct radeon_fence { | |||
| 277 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); | 234 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); |
| 278 | int radeon_fence_driver_init(struct radeon_device *rdev); | 235 | int radeon_fence_driver_init(struct radeon_device *rdev); |
| 279 | void radeon_fence_driver_fini(struct radeon_device *rdev); | 236 | void radeon_fence_driver_fini(struct radeon_device *rdev); |
| 280 | int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence, int ring); | 237 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); |
| 281 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence); | ||
| 282 | void radeon_fence_process(struct radeon_device *rdev, int ring); | 238 | void radeon_fence_process(struct radeon_device *rdev, int ring); |
| 283 | bool radeon_fence_signaled(struct radeon_fence *fence); | 239 | bool radeon_fence_signaled(struct radeon_fence *fence); |
| 284 | int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); | 240 | int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); |
| 285 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); | 241 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); |
| 286 | int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); | 242 | void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); |
| 287 | int radeon_fence_wait_any(struct radeon_device *rdev, | 243 | int radeon_fence_wait_any(struct radeon_device *rdev, |
| 288 | struct radeon_fence **fences, | 244 | struct radeon_fence **fences, |
| 289 | bool intr); | 245 | bool intr); |
| 290 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); | 246 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); |
| 291 | void radeon_fence_unref(struct radeon_fence **fence); | 247 | void radeon_fence_unref(struct radeon_fence **fence); |
| 292 | unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring); | 248 | unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring); |
| 249 | bool radeon_fence_need_sync(struct radeon_fence *fence, int ring); | ||
| 250 | void radeon_fence_note_sync(struct radeon_fence *fence, int ring); | ||
| 251 | static inline struct radeon_fence *radeon_fence_later(struct radeon_fence *a, | ||
| 252 | struct radeon_fence *b) | ||
| 253 | { | ||
| 254 | if (!a) { | ||
| 255 | return b; | ||
| 256 | } | ||
| 257 | |||
| 258 | if (!b) { | ||
| 259 | return a; | ||
| 260 | } | ||
| 261 | |||
| 262 | BUG_ON(a->ring != b->ring); | ||
| 263 | |||
| 264 | if (a->seq > b->seq) { | ||
| 265 | return a; | ||
| 266 | } else { | ||
| 267 | return b; | ||
| 268 | } | ||
| 269 | } | ||
| 293 | 270 | ||
| 294 | /* | 271 | /* |
| 295 | * Tiling registers | 272 | * Tiling registers |
| @@ -385,7 +362,7 @@ struct radeon_bo_list { | |||
| 385 | * alignment). | 362 | * alignment). |
| 386 | */ | 363 | */ |
| 387 | struct radeon_sa_manager { | 364 | struct radeon_sa_manager { |
| 388 | spinlock_t lock; | 365 | wait_queue_head_t wq; |
| 389 | struct radeon_bo *bo; | 366 | struct radeon_bo *bo; |
| 390 | struct list_head *hole; | 367 | struct list_head *hole; |
| 391 | struct list_head flist[RADEON_NUM_RINGS]; | 368 | struct list_head flist[RADEON_NUM_RINGS]; |
| @@ -451,10 +428,9 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, | |||
| 451 | struct radeon_semaphore *semaphore); | 428 | struct radeon_semaphore *semaphore); |
| 452 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, | 429 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, |
| 453 | struct radeon_semaphore *semaphore, | 430 | struct radeon_semaphore *semaphore, |
| 454 | bool sync_to[RADEON_NUM_RINGS], | 431 | int signaler, int waiter); |
| 455 | int dst_ring); | ||
| 456 | void radeon_semaphore_free(struct radeon_device *rdev, | 432 | void radeon_semaphore_free(struct radeon_device *rdev, |
| 457 | struct radeon_semaphore *semaphore, | 433 | struct radeon_semaphore **semaphore, |
| 458 | struct radeon_fence *fence); | 434 | struct radeon_fence *fence); |
| 459 | 435 | ||
| 460 | /* | 436 | /* |
| @@ -597,21 +573,18 @@ union radeon_irq_stat_regs { | |||
| 597 | #define RADEON_MAX_AFMT_BLOCKS 6 | 573 | #define RADEON_MAX_AFMT_BLOCKS 6 |
| 598 | 574 | ||
| 599 | struct radeon_irq { | 575 | struct radeon_irq { |
| 600 | bool installed; | 576 | bool installed; |
| 601 | bool sw_int[RADEON_NUM_RINGS]; | 577 | spinlock_t lock; |
| 602 | bool crtc_vblank_int[RADEON_MAX_CRTCS]; | 578 | atomic_t ring_int[RADEON_NUM_RINGS]; |
| 603 | bool pflip[RADEON_MAX_CRTCS]; | 579 | bool crtc_vblank_int[RADEON_MAX_CRTCS]; |
| 604 | wait_queue_head_t vblank_queue; | 580 | atomic_t pflip[RADEON_MAX_CRTCS]; |
| 605 | bool hpd[RADEON_MAX_HPD_PINS]; | 581 | wait_queue_head_t vblank_queue; |
| 606 | bool gui_idle; | 582 | bool hpd[RADEON_MAX_HPD_PINS]; |
| 607 | bool gui_idle_acked; | 583 | bool gui_idle; |
| 608 | wait_queue_head_t idle_queue; | 584 | bool gui_idle_acked; |
| 609 | bool afmt[RADEON_MAX_AFMT_BLOCKS]; | 585 | wait_queue_head_t idle_queue; |
| 610 | spinlock_t sw_lock; | 586 | bool afmt[RADEON_MAX_AFMT_BLOCKS]; |
| 611 | int sw_refcount[RADEON_NUM_RINGS]; | 587 | union radeon_irq_stat_regs stat_regs; |
| 612 | union radeon_irq_stat_regs stat_regs; | ||
| 613 | spinlock_t pflip_lock[RADEON_MAX_CRTCS]; | ||
| 614 | int pflip_refcount[RADEON_MAX_CRTCS]; | ||
| 615 | }; | 588 | }; |
| 616 | 589 | ||
| 617 | int radeon_irq_kms_init(struct radeon_device *rdev); | 590 | int radeon_irq_kms_init(struct radeon_device *rdev); |
| @@ -620,6 +593,11 @@ void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring); | |||
| 620 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring); | 593 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring); |
| 621 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc); | 594 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc); |
| 622 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc); | 595 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc); |
| 596 | void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block); | ||
| 597 | void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block); | ||
| 598 | void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask); | ||
| 599 | void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask); | ||
| 600 | int radeon_irq_kms_wait_gui_idle(struct radeon_device *rdev); | ||
| 623 | 601 | ||
| 624 | /* | 602 | /* |
| 625 | * CP & rings. | 603 | * CP & rings. |
| @@ -630,9 +608,11 @@ struct radeon_ib { | |||
| 630 | uint32_t length_dw; | 608 | uint32_t length_dw; |
| 631 | uint64_t gpu_addr; | 609 | uint64_t gpu_addr; |
| 632 | uint32_t *ptr; | 610 | uint32_t *ptr; |
| 611 | int ring; | ||
| 633 | struct radeon_fence *fence; | 612 | struct radeon_fence *fence; |
| 634 | unsigned vm_id; | 613 | unsigned vm_id; |
| 635 | bool is_const_ib; | 614 | bool is_const_ib; |
| 615 | struct radeon_fence *sync_to[RADEON_NUM_RINGS]; | ||
| 636 | struct radeon_semaphore *semaphore; | 616 | struct radeon_semaphore *semaphore; |
| 637 | }; | 617 | }; |
| 638 | 618 | ||
| @@ -642,6 +622,9 @@ struct radeon_ring { | |||
| 642 | unsigned rptr; | 622 | unsigned rptr; |
| 643 | unsigned rptr_offs; | 623 | unsigned rptr_offs; |
| 644 | unsigned rptr_reg; | 624 | unsigned rptr_reg; |
| 625 | unsigned rptr_save_reg; | ||
| 626 | u64 next_rptr_gpu_addr; | ||
| 627 | volatile u32 *next_rptr_cpu_addr; | ||
| 645 | unsigned wptr; | 628 | unsigned wptr; |
| 646 | unsigned wptr_old; | 629 | unsigned wptr_old; |
| 647 | unsigned wptr_reg; | 630 | unsigned wptr_reg; |
| @@ -657,6 +640,7 @@ struct radeon_ring { | |||
| 657 | u32 ptr_reg_shift; | 640 | u32 ptr_reg_shift; |
| 658 | u32 ptr_reg_mask; | 641 | u32 ptr_reg_mask; |
| 659 | u32 nop; | 642 | u32 nop; |
| 643 | u32 idx; | ||
| 660 | }; | 644 | }; |
| 661 | 645 | ||
| 662 | /* | 646 | /* |
| @@ -690,6 +674,7 @@ struct radeon_vm_funcs { | |||
| 690 | }; | 674 | }; |
| 691 | 675 | ||
| 692 | struct radeon_vm_manager { | 676 | struct radeon_vm_manager { |
| 677 | struct mutex lock; | ||
| 693 | struct list_head lru_vm; | 678 | struct list_head lru_vm; |
| 694 | uint32_t use_bitmap; | 679 | uint32_t use_bitmap; |
| 695 | struct radeon_sa_manager sa_manager; | 680 | struct radeon_sa_manager sa_manager; |
| @@ -718,13 +703,10 @@ struct r600_ih { | |||
| 718 | struct radeon_bo *ring_obj; | 703 | struct radeon_bo *ring_obj; |
| 719 | volatile uint32_t *ring; | 704 | volatile uint32_t *ring; |
| 720 | unsigned rptr; | 705 | unsigned rptr; |
| 721 | unsigned rptr_offs; | ||
| 722 | unsigned wptr; | ||
| 723 | unsigned wptr_old; | ||
| 724 | unsigned ring_size; | 706 | unsigned ring_size; |
| 725 | uint64_t gpu_addr; | 707 | uint64_t gpu_addr; |
| 726 | uint32_t ptr_mask; | 708 | uint32_t ptr_mask; |
| 727 | spinlock_t lock; | 709 | atomic_t lock; |
| 728 | bool enabled; | 710 | bool enabled; |
| 729 | }; | 711 | }; |
| 730 | 712 | ||
| @@ -757,8 +739,6 @@ struct r600_blit { | |||
| 757 | u32 state_len; | 739 | u32 state_len; |
| 758 | }; | 740 | }; |
| 759 | 741 | ||
| 760 | void r600_blit_suspend(struct radeon_device *rdev); | ||
| 761 | |||
| 762 | /* | 742 | /* |
| 763 | * SI RLC stuff | 743 | * SI RLC stuff |
| 764 | */ | 744 | */ |
| @@ -774,14 +754,14 @@ struct si_rlc { | |||
| 774 | int radeon_ib_get(struct radeon_device *rdev, int ring, | 754 | int radeon_ib_get(struct radeon_device *rdev, int ring, |
| 775 | struct radeon_ib *ib, unsigned size); | 755 | struct radeon_ib *ib, unsigned size); |
| 776 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib); | 756 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib); |
| 777 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib); | 757 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, |
| 758 | struct radeon_ib *const_ib); | ||
| 778 | int radeon_ib_pool_init(struct radeon_device *rdev); | 759 | int radeon_ib_pool_init(struct radeon_device *rdev); |
| 779 | void radeon_ib_pool_fini(struct radeon_device *rdev); | 760 | void radeon_ib_pool_fini(struct radeon_device *rdev); |
| 780 | int radeon_ib_pool_start(struct radeon_device *rdev); | ||
| 781 | int radeon_ib_pool_suspend(struct radeon_device *rdev); | ||
| 782 | int radeon_ib_ring_tests(struct radeon_device *rdev); | 761 | int radeon_ib_ring_tests(struct radeon_device *rdev); |
| 783 | /* Ring access between begin & end cannot sleep */ | 762 | /* Ring access between begin & end cannot sleep */ |
| 784 | int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *cp); | 763 | bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, |
| 764 | struct radeon_ring *ring); | ||
| 785 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp); | 765 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp); |
| 786 | int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); | 766 | int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); |
| 787 | int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); | 767 | int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); |
| @@ -793,6 +773,10 @@ int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); | |||
| 793 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring); | 773 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring); |
| 794 | void radeon_ring_lockup_update(struct radeon_ring *ring); | 774 | void radeon_ring_lockup_update(struct radeon_ring *ring); |
| 795 | bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring); | 775 | bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring); |
| 776 | unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, | ||
| 777 | uint32_t **data); | ||
| 778 | int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, | ||
| 779 | unsigned size, uint32_t *data); | ||
| 796 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size, | 780 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size, |
| 797 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, | 781 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, |
| 798 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop); | 782 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop); |
| @@ -891,6 +875,7 @@ struct radeon_wb { | |||
| 891 | }; | 875 | }; |
| 892 | 876 | ||
| 893 | #define RADEON_WB_SCRATCH_OFFSET 0 | 877 | #define RADEON_WB_SCRATCH_OFFSET 0 |
| 878 | #define RADEON_WB_RING0_NEXT_RPTR 256 | ||
| 894 | #define RADEON_WB_CP_RPTR_OFFSET 1024 | 879 | #define RADEON_WB_CP_RPTR_OFFSET 1024 |
| 895 | #define RADEON_WB_CP1_RPTR_OFFSET 1280 | 880 | #define RADEON_WB_CP1_RPTR_OFFSET 1280 |
| 896 | #define RADEON_WB_CP2_RPTR_OFFSET 1536 | 881 | #define RADEON_WB_CP2_RPTR_OFFSET 1536 |
| @@ -1039,11 +1024,12 @@ struct radeon_power_state { | |||
| 1039 | 1024 | ||
| 1040 | struct radeon_pm { | 1025 | struct radeon_pm { |
| 1041 | struct mutex mutex; | 1026 | struct mutex mutex; |
| 1027 | /* write locked while reprogramming mclk */ | ||
| 1028 | struct rw_semaphore mclk_lock; | ||
| 1042 | u32 active_crtcs; | 1029 | u32 active_crtcs; |
| 1043 | int active_crtc_count; | 1030 | int active_crtc_count; |
| 1044 | int req_vblank; | 1031 | int req_vblank; |
| 1045 | bool vblank_sync; | 1032 | bool vblank_sync; |
| 1046 | bool gui_idle; | ||
| 1047 | fixed20_12 max_bandwidth; | 1033 | fixed20_12 max_bandwidth; |
| 1048 | fixed20_12 igp_sideport_mclk; | 1034 | fixed20_12 igp_sideport_mclk; |
| 1049 | fixed20_12 igp_system_mclk; | 1035 | fixed20_12 igp_system_mclk; |
| @@ -1192,20 +1178,20 @@ struct radeon_asic { | |||
| 1192 | uint64_t src_offset, | 1178 | uint64_t src_offset, |
| 1193 | uint64_t dst_offset, | 1179 | uint64_t dst_offset, |
| 1194 | unsigned num_gpu_pages, | 1180 | unsigned num_gpu_pages, |
| 1195 | struct radeon_fence *fence); | 1181 | struct radeon_fence **fence); |
| 1196 | u32 blit_ring_index; | 1182 | u32 blit_ring_index; |
| 1197 | int (*dma)(struct radeon_device *rdev, | 1183 | int (*dma)(struct radeon_device *rdev, |
| 1198 | uint64_t src_offset, | 1184 | uint64_t src_offset, |
| 1199 | uint64_t dst_offset, | 1185 | uint64_t dst_offset, |
| 1200 | unsigned num_gpu_pages, | 1186 | unsigned num_gpu_pages, |
| 1201 | struct radeon_fence *fence); | 1187 | struct radeon_fence **fence); |
| 1202 | u32 dma_ring_index; | 1188 | u32 dma_ring_index; |
| 1203 | /* method used for bo copy */ | 1189 | /* method used for bo copy */ |
| 1204 | int (*copy)(struct radeon_device *rdev, | 1190 | int (*copy)(struct radeon_device *rdev, |
| 1205 | uint64_t src_offset, | 1191 | uint64_t src_offset, |
| 1206 | uint64_t dst_offset, | 1192 | uint64_t dst_offset, |
| 1207 | unsigned num_gpu_pages, | 1193 | unsigned num_gpu_pages, |
| 1208 | struct radeon_fence *fence); | 1194 | struct radeon_fence **fence); |
| 1209 | /* ring used for bo copies */ | 1195 | /* ring used for bo copies */ |
| 1210 | u32 copy_ring_index; | 1196 | u32 copy_ring_index; |
| 1211 | } copy; | 1197 | } copy; |
| @@ -1467,6 +1453,7 @@ struct radeon_device { | |||
| 1467 | struct device *dev; | 1453 | struct device *dev; |
| 1468 | struct drm_device *ddev; | 1454 | struct drm_device *ddev; |
| 1469 | struct pci_dev *pdev; | 1455 | struct pci_dev *pdev; |
| 1456 | struct rw_semaphore exclusive_lock; | ||
| 1470 | /* ASIC */ | 1457 | /* ASIC */ |
| 1471 | union radeon_asic_config config; | 1458 | union radeon_asic_config config; |
| 1472 | enum radeon_family family; | 1459 | enum radeon_family family; |
| @@ -1512,7 +1499,6 @@ struct radeon_device { | |||
| 1512 | struct radeon_gem gem; | 1499 | struct radeon_gem gem; |
| 1513 | struct radeon_pm pm; | 1500 | struct radeon_pm pm; |
| 1514 | uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; | 1501 | uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; |
| 1515 | struct radeon_mutex cs_mutex; | ||
| 1516 | struct radeon_wb wb; | 1502 | struct radeon_wb wb; |
| 1517 | struct radeon_dummy_page dummy_page; | 1503 | struct radeon_dummy_page dummy_page; |
| 1518 | bool shutdown; | 1504 | bool shutdown; |
| @@ -1534,7 +1520,6 @@ struct radeon_device { | |||
| 1534 | struct work_struct audio_work; | 1520 | struct work_struct audio_work; |
| 1535 | int num_crtc; /* number of crtcs */ | 1521 | int num_crtc; /* number of crtcs */ |
| 1536 | struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ | 1522 | struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ |
| 1537 | struct mutex vram_mutex; | ||
| 1538 | bool audio_enabled; | 1523 | bool audio_enabled; |
| 1539 | struct r600_audio audio_status; /* audio stuff */ | 1524 | struct r600_audio audio_status; /* audio stuff */ |
| 1540 | struct notifier_block acpi_nb; | 1525 | struct notifier_block acpi_nb; |
| @@ -1785,8 +1770,6 @@ extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size | |||
| 1785 | */ | 1770 | */ |
| 1786 | int radeon_vm_manager_init(struct radeon_device *rdev); | 1771 | int radeon_vm_manager_init(struct radeon_device *rdev); |
| 1787 | void radeon_vm_manager_fini(struct radeon_device *rdev); | 1772 | void radeon_vm_manager_fini(struct radeon_device *rdev); |
| 1788 | int radeon_vm_manager_start(struct radeon_device *rdev); | ||
| 1789 | int radeon_vm_manager_suspend(struct radeon_device *rdev); | ||
| 1790 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); | 1773 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); |
| 1791 | void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); | 1774 | void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); |
| 1792 | int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm); | 1775 | int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm); |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index f533df5f7d50..973417c4b014 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
| @@ -40,6 +40,16 @@ | |||
| 40 | /* | 40 | /* |
| 41 | * Registers accessors functions. | 41 | * Registers accessors functions. |
| 42 | */ | 42 | */ |
| 43 | /** | ||
| 44 | * radeon_invalid_rreg - dummy reg read function | ||
| 45 | * | ||
| 46 | * @rdev: radeon device pointer | ||
| 47 | * @reg: offset of register | ||
| 48 | * | ||
| 49 | * Dummy register read function. Used for register blocks | ||
| 50 | * that certain asics don't have (all asics). | ||
| 51 | * Returns the value in the register. | ||
| 52 | */ | ||
| 43 | static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) | 53 | static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) |
| 44 | { | 54 | { |
| 45 | DRM_ERROR("Invalid callback to read register 0x%04X\n", reg); | 55 | DRM_ERROR("Invalid callback to read register 0x%04X\n", reg); |
| @@ -47,6 +57,16 @@ static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) | |||
| 47 | return 0; | 57 | return 0; |
| 48 | } | 58 | } |
| 49 | 59 | ||
| 60 | /** | ||
| 61 | * radeon_invalid_wreg - dummy reg write function | ||
| 62 | * | ||
| 63 | * @rdev: radeon device pointer | ||
| 64 | * @reg: offset of register | ||
| 65 | * @v: value to write to the register | ||
| 66 | * | ||
| 67 | * Dummy register read function. Used for register blocks | ||
| 68 | * that certain asics don't have (all asics). | ||
| 69 | */ | ||
| 50 | static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | 70 | static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) |
| 51 | { | 71 | { |
| 52 | DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n", | 72 | DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n", |
| @@ -54,6 +74,14 @@ static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32 | |||
| 54 | BUG_ON(1); | 74 | BUG_ON(1); |
| 55 | } | 75 | } |
| 56 | 76 | ||
| 77 | /** | ||
| 78 | * radeon_register_accessor_init - sets up the register accessor callbacks | ||
| 79 | * | ||
| 80 | * @rdev: radeon device pointer | ||
| 81 | * | ||
| 82 | * Sets up the register accessor callbacks for various register | ||
| 83 | * apertures. Not all asics have all apertures (all asics). | ||
| 84 | */ | ||
| 57 | static void radeon_register_accessor_init(struct radeon_device *rdev) | 85 | static void radeon_register_accessor_init(struct radeon_device *rdev) |
| 58 | { | 86 | { |
| 59 | rdev->mc_rreg = &radeon_invalid_rreg; | 87 | rdev->mc_rreg = &radeon_invalid_rreg; |
| @@ -102,6 +130,14 @@ static void radeon_register_accessor_init(struct radeon_device *rdev) | |||
| 102 | 130 | ||
| 103 | 131 | ||
| 104 | /* helper to disable agp */ | 132 | /* helper to disable agp */ |
| 133 | /** | ||
| 134 | * radeon_agp_disable - AGP disable helper function | ||
| 135 | * | ||
| 136 | * @rdev: radeon device pointer | ||
| 137 | * | ||
| 138 | * Removes AGP flags and changes the gart callbacks on AGP | ||
| 139 | * cards when using the internal gart rather than AGP (all asics). | ||
| 140 | */ | ||
| 105 | void radeon_agp_disable(struct radeon_device *rdev) | 141 | void radeon_agp_disable(struct radeon_device *rdev) |
| 106 | { | 142 | { |
| 107 | rdev->flags &= ~RADEON_IS_AGP; | 143 | rdev->flags &= ~RADEON_IS_AGP; |
| @@ -1608,6 +1644,16 @@ static struct radeon_asic si_asic = { | |||
| 1608 | }, | 1644 | }, |
| 1609 | }; | 1645 | }; |
| 1610 | 1646 | ||
| 1647 | /** | ||
| 1648 | * radeon_asic_init - register asic specific callbacks | ||
| 1649 | * | ||
| 1650 | * @rdev: radeon device pointer | ||
| 1651 | * | ||
| 1652 | * Registers the appropriate asic specific callbacks for each | ||
| 1653 | * chip family. Also sets other asics specific info like the number | ||
| 1654 | * of crtcs and the register aperture accessors (all asics). | ||
| 1655 | * Returns 0 for success. | ||
| 1656 | */ | ||
| 1611 | int radeon_asic_init(struct radeon_device *rdev) | 1657 | int radeon_asic_init(struct radeon_device *rdev) |
| 1612 | { | 1658 | { |
| 1613 | radeon_register_accessor_init(rdev); | 1659 | radeon_register_accessor_init(rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index e76a941ef14e..f4af24310438 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
| @@ -79,7 +79,7 @@ int r100_copy_blit(struct radeon_device *rdev, | |||
| 79 | uint64_t src_offset, | 79 | uint64_t src_offset, |
| 80 | uint64_t dst_offset, | 80 | uint64_t dst_offset, |
| 81 | unsigned num_gpu_pages, | 81 | unsigned num_gpu_pages, |
| 82 | struct radeon_fence *fence); | 82 | struct radeon_fence **fence); |
| 83 | int r100_set_surface_reg(struct radeon_device *rdev, int reg, | 83 | int r100_set_surface_reg(struct radeon_device *rdev, int reg, |
| 84 | uint32_t tiling_flags, uint32_t pitch, | 84 | uint32_t tiling_flags, uint32_t pitch, |
| 85 | uint32_t offset, uint32_t obj_size); | 85 | uint32_t offset, uint32_t obj_size); |
| @@ -103,7 +103,6 @@ int r100_pci_gart_enable(struct radeon_device *rdev); | |||
| 103 | void r100_pci_gart_disable(struct radeon_device *rdev); | 103 | void r100_pci_gart_disable(struct radeon_device *rdev); |
| 104 | int r100_debugfs_mc_info_init(struct radeon_device *rdev); | 104 | int r100_debugfs_mc_info_init(struct radeon_device *rdev); |
| 105 | int r100_gui_wait_for_idle(struct radeon_device *rdev); | 105 | int r100_gui_wait_for_idle(struct radeon_device *rdev); |
| 106 | void r100_ib_fini(struct radeon_device *rdev); | ||
| 107 | int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); | 106 | int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); |
| 108 | void r100_irq_disable(struct radeon_device *rdev); | 107 | void r100_irq_disable(struct radeon_device *rdev); |
| 109 | void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save); | 108 | void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save); |
| @@ -144,7 +143,7 @@ extern int r200_copy_dma(struct radeon_device *rdev, | |||
| 144 | uint64_t src_offset, | 143 | uint64_t src_offset, |
| 145 | uint64_t dst_offset, | 144 | uint64_t dst_offset, |
| 146 | unsigned num_gpu_pages, | 145 | unsigned num_gpu_pages, |
| 147 | struct radeon_fence *fence); | 146 | struct radeon_fence **fence); |
| 148 | void r200_set_safe_registers(struct radeon_device *rdev); | 147 | void r200_set_safe_registers(struct radeon_device *rdev); |
| 149 | 148 | ||
| 150 | /* | 149 | /* |
| @@ -318,7 +317,7 @@ void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); | |||
| 318 | int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); | 317 | int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); |
| 319 | int r600_copy_blit(struct radeon_device *rdev, | 318 | int r600_copy_blit(struct radeon_device *rdev, |
| 320 | uint64_t src_offset, uint64_t dst_offset, | 319 | uint64_t src_offset, uint64_t dst_offset, |
| 321 | unsigned num_gpu_pages, struct radeon_fence *fence); | 320 | unsigned num_gpu_pages, struct radeon_fence **fence); |
| 322 | void r600_hpd_init(struct radeon_device *rdev); | 321 | void r600_hpd_init(struct radeon_device *rdev); |
| 323 | void r600_hpd_fini(struct radeon_device *rdev); | 322 | void r600_hpd_fini(struct radeon_device *rdev); |
| 324 | bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); | 323 | bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); |
| @@ -363,9 +362,10 @@ int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); | |||
| 363 | void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); | 362 | void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); |
| 364 | /* r600 blit */ | 363 | /* r600 blit */ |
| 365 | int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, | 364 | int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, |
| 366 | struct radeon_sa_bo **vb); | 365 | struct radeon_fence **fence, struct radeon_sa_bo **vb, |
| 367 | void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence, | 366 | struct radeon_semaphore **sem); |
| 368 | struct radeon_sa_bo *vb); | 367 | void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence **fence, |
| 368 | struct radeon_sa_bo *vb, struct radeon_semaphore *sem); | ||
| 369 | void r600_kms_blit_copy(struct radeon_device *rdev, | 369 | void r600_kms_blit_copy(struct radeon_device *rdev, |
| 370 | u64 src_gpu_addr, u64 dst_gpu_addr, | 370 | u64 src_gpu_addr, u64 dst_gpu_addr, |
| 371 | unsigned num_gpu_pages, | 371 | unsigned num_gpu_pages, |
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index 364f5b1a04b9..bedda9caadd9 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c | |||
| @@ -45,20 +45,14 @@ static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size, | |||
| 45 | for (i = 0; i < n; i++) { | 45 | for (i = 0; i < n; i++) { |
| 46 | switch (flag) { | 46 | switch (flag) { |
| 47 | case RADEON_BENCHMARK_COPY_DMA: | 47 | case RADEON_BENCHMARK_COPY_DMA: |
| 48 | r = radeon_fence_create(rdev, &fence, radeon_copy_dma_ring_index(rdev)); | ||
| 49 | if (r) | ||
| 50 | return r; | ||
| 51 | r = radeon_copy_dma(rdev, saddr, daddr, | 48 | r = radeon_copy_dma(rdev, saddr, daddr, |
| 52 | size / RADEON_GPU_PAGE_SIZE, | 49 | size / RADEON_GPU_PAGE_SIZE, |
| 53 | fence); | 50 | &fence); |
| 54 | break; | 51 | break; |
| 55 | case RADEON_BENCHMARK_COPY_BLIT: | 52 | case RADEON_BENCHMARK_COPY_BLIT: |
| 56 | r = radeon_fence_create(rdev, &fence, radeon_copy_blit_ring_index(rdev)); | ||
| 57 | if (r) | ||
| 58 | return r; | ||
| 59 | r = radeon_copy_blit(rdev, saddr, daddr, | 53 | r = radeon_copy_blit(rdev, saddr, daddr, |
| 60 | size / RADEON_GPU_PAGE_SIZE, | 54 | size / RADEON_GPU_PAGE_SIZE, |
| 61 | fence); | 55 | &fence); |
| 62 | break; | 56 | break; |
| 63 | default: | 57 | default: |
| 64 | DRM_ERROR("Unknown copy method\n"); | 58 | DRM_ERROR("Unknown copy method\n"); |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 2914c5761cfc..895e628b60f8 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -64,14 +64,33 @@ void radeon_connector_hotplug(struct drm_connector *connector) | |||
| 64 | 64 | ||
| 65 | /* just deal with DP (not eDP) here. */ | 65 | /* just deal with DP (not eDP) here. */ |
| 66 | if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { | 66 | if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { |
| 67 | int saved_dpms = connector->dpms; | 67 | struct radeon_connector_atom_dig *dig_connector = |
| 68 | 68 | radeon_connector->con_priv; | |
| 69 | /* Only turn off the display it it's physically disconnected */ | 69 | |
| 70 | if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) | 70 | /* if existing sink type was not DP no need to retrain */ |
| 71 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); | 71 | if (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) |
| 72 | else if (radeon_dp_needs_link_train(radeon_connector)) | 72 | return; |
| 73 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); | 73 | |
| 74 | connector->dpms = saved_dpms; | 74 | /* first get sink type as it may be reset after (un)plug */ |
| 75 | dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); | ||
| 76 | /* don't do anything if sink is not display port, i.e., | ||
| 77 | * passive dp->(dvi|hdmi) adaptor | ||
| 78 | */ | ||
| 79 | if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { | ||
| 80 | int saved_dpms = connector->dpms; | ||
| 81 | /* Only turn off the display if it's physically disconnected */ | ||
| 82 | if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { | ||
| 83 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); | ||
| 84 | } else if (radeon_dp_needs_link_train(radeon_connector)) { | ||
| 85 | /* set it to OFF so that drm_helper_connector_dpms() | ||
| 86 | * won't return immediately since the current state | ||
| 87 | * is ON at this point. | ||
| 88 | */ | ||
| 89 | connector->dpms = DRM_MODE_DPMS_OFF; | ||
| 90 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); | ||
| 91 | } | ||
| 92 | connector->dpms = saved_dpms; | ||
| 93 | } | ||
| 75 | } | 94 | } |
| 76 | } | 95 | } |
| 77 | 96 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 142f89462aa4..8a4c49ef0cc4 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
| @@ -115,36 +115,20 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority | |||
| 115 | return 0; | 115 | return 0; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | static int radeon_cs_sync_rings(struct radeon_cs_parser *p) | 118 | static void radeon_cs_sync_rings(struct radeon_cs_parser *p) |
| 119 | { | 119 | { |
| 120 | bool sync_to_ring[RADEON_NUM_RINGS] = { }; | 120 | int i; |
| 121 | bool need_sync = false; | ||
| 122 | int i, r; | ||
| 123 | 121 | ||
| 124 | for (i = 0; i < p->nrelocs; i++) { | 122 | for (i = 0; i < p->nrelocs; i++) { |
| 125 | struct radeon_fence *fence; | 123 | struct radeon_fence *a, *b; |
| 126 | 124 | ||
| 127 | if (!p->relocs[i].robj || !p->relocs[i].robj->tbo.sync_obj) | 125 | if (!p->relocs[i].robj || !p->relocs[i].robj->tbo.sync_obj) |
| 128 | continue; | 126 | continue; |
| 129 | 127 | ||
| 130 | fence = p->relocs[i].robj->tbo.sync_obj; | 128 | a = p->relocs[i].robj->tbo.sync_obj; |
| 131 | if (fence->ring != p->ring && !radeon_fence_signaled(fence)) { | 129 | b = p->ib.sync_to[a->ring]; |
| 132 | sync_to_ring[fence->ring] = true; | 130 | p->ib.sync_to[a->ring] = radeon_fence_later(a, b); |
| 133 | need_sync = true; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | if (!need_sync) { | ||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | r = radeon_semaphore_create(p->rdev, &p->ib.semaphore); | ||
| 142 | if (r) { | ||
| 143 | return r; | ||
| 144 | } | 131 | } |
| 145 | |||
| 146 | return radeon_semaphore_sync_rings(p->rdev, p->ib.semaphore, | ||
| 147 | sync_to_ring, p->ring); | ||
| 148 | } | 132 | } |
| 149 | 133 | ||
| 150 | /* XXX: note that this is called from the legacy UMS CS ioctl as well */ | 134 | /* XXX: note that this is called from the legacy UMS CS ioctl as well */ |
| @@ -368,16 +352,13 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev, | |||
| 368 | DRM_ERROR("Invalid command stream !\n"); | 352 | DRM_ERROR("Invalid command stream !\n"); |
| 369 | return r; | 353 | return r; |
| 370 | } | 354 | } |
| 371 | r = radeon_cs_sync_rings(parser); | 355 | radeon_cs_sync_rings(parser); |
| 372 | if (r) { | ||
| 373 | DRM_ERROR("Failed to synchronize rings !\n"); | ||
| 374 | } | ||
| 375 | parser->ib.vm_id = 0; | 356 | parser->ib.vm_id = 0; |
| 376 | r = radeon_ib_schedule(rdev, &parser->ib); | 357 | r = radeon_ib_schedule(rdev, &parser->ib, NULL); |
| 377 | if (r) { | 358 | if (r) { |
| 378 | DRM_ERROR("Failed to schedule IB !\n"); | 359 | DRM_ERROR("Failed to schedule IB !\n"); |
| 379 | } | 360 | } |
| 380 | return 0; | 361 | return r; |
| 381 | } | 362 | } |
| 382 | 363 | ||
| 383 | static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser, | 364 | static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser, |
| @@ -459,6 +440,7 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, | |||
| 459 | return r; | 440 | return r; |
| 460 | } | 441 | } |
| 461 | 442 | ||
| 443 | mutex_lock(&rdev->vm_manager.lock); | ||
| 462 | mutex_lock(&vm->mutex); | 444 | mutex_lock(&vm->mutex); |
| 463 | r = radeon_vm_bind(rdev, vm); | 445 | r = radeon_vm_bind(rdev, vm); |
| 464 | if (r) { | 446 | if (r) { |
| @@ -468,30 +450,26 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, | |||
| 468 | if (r) { | 450 | if (r) { |
| 469 | goto out; | 451 | goto out; |
| 470 | } | 452 | } |
| 471 | r = radeon_cs_sync_rings(parser); | 453 | radeon_cs_sync_rings(parser); |
| 472 | if (r) { | 454 | |
| 473 | DRM_ERROR("Failed to synchronize rings !\n"); | 455 | parser->ib.vm_id = vm->id; |
| 474 | } | 456 | /* ib pool is bind at 0 in virtual address space, |
| 457 | * so gpu_addr is the offset inside the pool bo | ||
| 458 | */ | ||
| 459 | parser->ib.gpu_addr = parser->ib.sa_bo->soffset; | ||
| 475 | 460 | ||
| 476 | if ((rdev->family >= CHIP_TAHITI) && | 461 | if ((rdev->family >= CHIP_TAHITI) && |
| 477 | (parser->chunk_const_ib_idx != -1)) { | 462 | (parser->chunk_const_ib_idx != -1)) { |
| 478 | parser->const_ib.vm_id = vm->id; | 463 | parser->const_ib.vm_id = vm->id; |
| 479 | /* ib pool is bind at 0 in virtual address space to gpu_addr is the | 464 | /* ib pool is bind at 0 in virtual address space, |
| 480 | * offset inside the pool bo | 465 | * so gpu_addr is the offset inside the pool bo |
| 481 | */ | 466 | */ |
| 482 | parser->const_ib.gpu_addr = parser->const_ib.sa_bo->soffset; | 467 | parser->const_ib.gpu_addr = parser->const_ib.sa_bo->soffset; |
| 483 | r = radeon_ib_schedule(rdev, &parser->const_ib); | 468 | r = radeon_ib_schedule(rdev, &parser->ib, &parser->const_ib); |
| 484 | if (r) | 469 | } else { |
| 485 | goto out; | 470 | r = radeon_ib_schedule(rdev, &parser->ib, NULL); |
| 486 | } | 471 | } |
| 487 | 472 | ||
| 488 | parser->ib.vm_id = vm->id; | ||
| 489 | /* ib pool is bind at 0 in virtual address space to gpu_addr is the | ||
| 490 | * offset inside the pool bo | ||
| 491 | */ | ||
| 492 | parser->ib.gpu_addr = parser->ib.sa_bo->soffset; | ||
| 493 | parser->ib.is_const_ib = false; | ||
| 494 | r = radeon_ib_schedule(rdev, &parser->ib); | ||
| 495 | out: | 473 | out: |
| 496 | if (!r) { | 474 | if (!r) { |
| 497 | if (vm->fence) { | 475 | if (vm->fence) { |
| @@ -499,7 +477,8 @@ out: | |||
| 499 | } | 477 | } |
| 500 | vm->fence = radeon_fence_ref(parser->ib.fence); | 478 | vm->fence = radeon_fence_ref(parser->ib.fence); |
| 501 | } | 479 | } |
| 502 | mutex_unlock(&fpriv->vm.mutex); | 480 | mutex_unlock(&vm->mutex); |
| 481 | mutex_unlock(&rdev->vm_manager.lock); | ||
| 503 | return r; | 482 | return r; |
| 504 | } | 483 | } |
| 505 | 484 | ||
| @@ -519,9 +498,9 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 519 | struct radeon_cs_parser parser; | 498 | struct radeon_cs_parser parser; |
| 520 | int r; | 499 | int r; |
| 521 | 500 | ||
| 522 | radeon_mutex_lock(&rdev->cs_mutex); | 501 | down_read(&rdev->exclusive_lock); |
| 523 | if (!rdev->accel_working) { | 502 | if (!rdev->accel_working) { |
| 524 | radeon_mutex_unlock(&rdev->cs_mutex); | 503 | up_read(&rdev->exclusive_lock); |
| 525 | return -EBUSY; | 504 | return -EBUSY; |
| 526 | } | 505 | } |
| 527 | /* initialize parser */ | 506 | /* initialize parser */ |
| @@ -534,8 +513,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 534 | if (r) { | 513 | if (r) { |
| 535 | DRM_ERROR("Failed to initialize parser !\n"); | 514 | DRM_ERROR("Failed to initialize parser !\n"); |
| 536 | radeon_cs_parser_fini(&parser, r); | 515 | radeon_cs_parser_fini(&parser, r); |
| 516 | up_read(&rdev->exclusive_lock); | ||
| 537 | r = radeon_cs_handle_lockup(rdev, r); | 517 | r = radeon_cs_handle_lockup(rdev, r); |
| 538 | radeon_mutex_unlock(&rdev->cs_mutex); | ||
| 539 | return r; | 518 | return r; |
| 540 | } | 519 | } |
| 541 | r = radeon_cs_parser_relocs(&parser); | 520 | r = radeon_cs_parser_relocs(&parser); |
| @@ -543,8 +522,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 543 | if (r != -ERESTARTSYS) | 522 | if (r != -ERESTARTSYS) |
| 544 | DRM_ERROR("Failed to parse relocation %d!\n", r); | 523 | DRM_ERROR("Failed to parse relocation %d!\n", r); |
| 545 | radeon_cs_parser_fini(&parser, r); | 524 | radeon_cs_parser_fini(&parser, r); |
| 525 | up_read(&rdev->exclusive_lock); | ||
| 546 | r = radeon_cs_handle_lockup(rdev, r); | 526 | r = radeon_cs_handle_lockup(rdev, r); |
| 547 | radeon_mutex_unlock(&rdev->cs_mutex); | ||
| 548 | return r; | 527 | return r; |
| 549 | } | 528 | } |
| 550 | r = radeon_cs_ib_chunk(rdev, &parser); | 529 | r = radeon_cs_ib_chunk(rdev, &parser); |
| @@ -557,8 +536,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 557 | } | 536 | } |
| 558 | out: | 537 | out: |
| 559 | radeon_cs_parser_fini(&parser, r); | 538 | radeon_cs_parser_fini(&parser, r); |
| 539 | up_read(&rdev->exclusive_lock); | ||
| 560 | r = radeon_cs_handle_lockup(rdev, r); | 540 | r = radeon_cs_handle_lockup(rdev, r); |
| 561 | radeon_mutex_unlock(&rdev->cs_mutex); | ||
| 562 | return r; | 541 | return r; |
| 563 | } | 542 | } |
| 564 | 543 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 42acc6449dd6..711e95ad39bf 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c | |||
| @@ -262,8 +262,14 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, | |||
| 262 | if (!(cursor_end & 0x7f)) | 262 | if (!(cursor_end & 0x7f)) |
| 263 | w--; | 263 | w--; |
| 264 | } | 264 | } |
| 265 | if (w <= 0) | 265 | if (w <= 0) { |
| 266 | w = 1; | 266 | w = 1; |
| 267 | cursor_end = x - xorigin + w; | ||
| 268 | if (!(cursor_end & 0x7f)) { | ||
| 269 | x--; | ||
| 270 | WARN_ON_ONCE(x < 0); | ||
| 271 | } | ||
| 272 | } | ||
| 267 | } | 273 | } |
| 268 | } | 274 | } |
| 269 | 275 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 066c98b888a5..742af8244e89 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -96,8 +96,12 @@ static const char radeon_family_name[][16] = { | |||
| 96 | "LAST", | 96 | "LAST", |
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | /* | 99 | /** |
| 100 | * Clear GPU surface registers. | 100 | * radeon_surface_init - Clear GPU surface registers. |
| 101 | * | ||
| 102 | * @rdev: radeon_device pointer | ||
| 103 | * | ||
| 104 | * Clear GPU surface registers (r1xx-r5xx). | ||
| 101 | */ | 105 | */ |
| 102 | void radeon_surface_init(struct radeon_device *rdev) | 106 | void radeon_surface_init(struct radeon_device *rdev) |
| 103 | { | 107 | { |
| @@ -119,6 +123,13 @@ void radeon_surface_init(struct radeon_device *rdev) | |||
| 119 | /* | 123 | /* |
| 120 | * GPU scratch registers helpers function. | 124 | * GPU scratch registers helpers function. |
| 121 | */ | 125 | */ |
| 126 | /** | ||
| 127 | * radeon_scratch_init - Init scratch register driver information. | ||
| 128 | * | ||
| 129 | * @rdev: radeon_device pointer | ||
| 130 | * | ||
| 131 | * Init CP scratch register driver information (r1xx-r5xx) | ||
| 132 | */ | ||
| 122 | void radeon_scratch_init(struct radeon_device *rdev) | 133 | void radeon_scratch_init(struct radeon_device *rdev) |
| 123 | { | 134 | { |
| 124 | int i; | 135 | int i; |
| @@ -136,6 +147,15 @@ void radeon_scratch_init(struct radeon_device *rdev) | |||
| 136 | } | 147 | } |
| 137 | } | 148 | } |
| 138 | 149 | ||
| 150 | /** | ||
| 151 | * radeon_scratch_get - Allocate a scratch register | ||
| 152 | * | ||
| 153 | * @rdev: radeon_device pointer | ||
| 154 | * @reg: scratch register mmio offset | ||
| 155 | * | ||
| 156 | * Allocate a CP scratch register for use by the driver (all asics). | ||
| 157 | * Returns 0 on success or -EINVAL on failure. | ||
| 158 | */ | ||
| 139 | int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) | 159 | int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) |
| 140 | { | 160 | { |
| 141 | int i; | 161 | int i; |
| @@ -150,6 +170,14 @@ int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) | |||
| 150 | return -EINVAL; | 170 | return -EINVAL; |
| 151 | } | 171 | } |
| 152 | 172 | ||
| 173 | /** | ||
| 174 | * radeon_scratch_free - Free a scratch register | ||
| 175 | * | ||
| 176 | * @rdev: radeon_device pointer | ||
| 177 | * @reg: scratch register mmio offset | ||
| 178 | * | ||
| 179 | * Free a CP scratch register allocated for use by the driver (all asics) | ||
| 180 | */ | ||
| 153 | void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) | 181 | void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) |
| 154 | { | 182 | { |
| 155 | int i; | 183 | int i; |
| @@ -162,6 +190,20 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) | |||
| 162 | } | 190 | } |
| 163 | } | 191 | } |
| 164 | 192 | ||
| 193 | /* | ||
| 194 | * radeon_wb_*() | ||
| 195 | * Writeback is the the method by which the the GPU updates special pages | ||
| 196 | * in memory with the status of certain GPU events (fences, ring pointers, | ||
| 197 | * etc.). | ||
| 198 | */ | ||
| 199 | |||
| 200 | /** | ||
| 201 | * radeon_wb_disable - Disable Writeback | ||
| 202 | * | ||
| 203 | * @rdev: radeon_device pointer | ||
| 204 | * | ||
| 205 | * Disables Writeback (all asics). Used for suspend. | ||
| 206 | */ | ||
| 165 | void radeon_wb_disable(struct radeon_device *rdev) | 207 | void radeon_wb_disable(struct radeon_device *rdev) |
| 166 | { | 208 | { |
| 167 | int r; | 209 | int r; |
| @@ -177,6 +219,14 @@ void radeon_wb_disable(struct radeon_device *rdev) | |||
| 177 | rdev->wb.enabled = false; | 219 | rdev->wb.enabled = false; |
| 178 | } | 220 | } |
| 179 | 221 | ||
| 222 | /** | ||
| 223 | * radeon_wb_fini - Disable Writeback and free memory | ||
| 224 | * | ||
| 225 | * @rdev: radeon_device pointer | ||
| 226 | * | ||
| 227 | * Disables Writeback and frees the Writeback memory (all asics). | ||
| 228 | * Used at driver shutdown. | ||
| 229 | */ | ||
| 180 | void radeon_wb_fini(struct radeon_device *rdev) | 230 | void radeon_wb_fini(struct radeon_device *rdev) |
| 181 | { | 231 | { |
| 182 | radeon_wb_disable(rdev); | 232 | radeon_wb_disable(rdev); |
| @@ -187,6 +237,15 @@ void radeon_wb_fini(struct radeon_device *rdev) | |||
| 187 | } | 237 | } |
| 188 | } | 238 | } |
| 189 | 239 | ||
| 240 | /** | ||
| 241 | * radeon_wb_init- Init Writeback driver info and allocate memory | ||
| 242 | * | ||
| 243 | * @rdev: radeon_device pointer | ||
| 244 | * | ||
| 245 | * Disables Writeback and frees the Writeback memory (all asics). | ||
| 246 | * Used at driver startup. | ||
| 247 | * Returns 0 on success or an -error on failure. | ||
| 248 | */ | ||
| 190 | int radeon_wb_init(struct radeon_device *rdev) | 249 | int radeon_wb_init(struct radeon_device *rdev) |
| 191 | { | 250 | { |
| 192 | int r; | 251 | int r; |
| @@ -355,6 +414,15 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) | |||
| 355 | /* | 414 | /* |
| 356 | * GPU helpers function. | 415 | * GPU helpers function. |
| 357 | */ | 416 | */ |
| 417 | /** | ||
| 418 | * radeon_card_posted - check if the hw has already been initialized | ||
| 419 | * | ||
| 420 | * @rdev: radeon_device pointer | ||
| 421 | * | ||
| 422 | * Check if the asic has been initialized (all asics). | ||
| 423 | * Used at driver startup. | ||
| 424 | * Returns true if initialized or false if not. | ||
| 425 | */ | ||
| 358 | bool radeon_card_posted(struct radeon_device *rdev) | 426 | bool radeon_card_posted(struct radeon_device *rdev) |
| 359 | { | 427 | { |
| 360 | uint32_t reg; | 428 | uint32_t reg; |
| @@ -404,6 +472,14 @@ bool radeon_card_posted(struct radeon_device *rdev) | |||
| 404 | 472 | ||
| 405 | } | 473 | } |
| 406 | 474 | ||
| 475 | /** | ||
| 476 | * radeon_update_bandwidth_info - update display bandwidth params | ||
| 477 | * | ||
| 478 | * @rdev: radeon_device pointer | ||
| 479 | * | ||
| 480 | * Used when sclk/mclk are switched or display modes are set. | ||
| 481 | * params are used to calculate display watermarks (all asics) | ||
| 482 | */ | ||
| 407 | void radeon_update_bandwidth_info(struct radeon_device *rdev) | 483 | void radeon_update_bandwidth_info(struct radeon_device *rdev) |
| 408 | { | 484 | { |
| 409 | fixed20_12 a; | 485 | fixed20_12 a; |
| @@ -424,6 +500,15 @@ void radeon_update_bandwidth_info(struct radeon_device *rdev) | |||
| 424 | } | 500 | } |
| 425 | } | 501 | } |
| 426 | 502 | ||
| 503 | /** | ||
| 504 | * radeon_boot_test_post_card - check and possibly initialize the hw | ||
| 505 | * | ||
| 506 | * @rdev: radeon_device pointer | ||
| 507 | * | ||
| 508 | * Check if the asic is initialized and if not, attempt to initialize | ||
| 509 | * it (all asics). | ||
| 510 | * Returns true if initialized or false if not. | ||
| 511 | */ | ||
| 427 | bool radeon_boot_test_post_card(struct radeon_device *rdev) | 512 | bool radeon_boot_test_post_card(struct radeon_device *rdev) |
| 428 | { | 513 | { |
| 429 | if (radeon_card_posted(rdev)) | 514 | if (radeon_card_posted(rdev)) |
| @@ -442,6 +527,16 @@ bool radeon_boot_test_post_card(struct radeon_device *rdev) | |||
| 442 | } | 527 | } |
| 443 | } | 528 | } |
| 444 | 529 | ||
| 530 | /** | ||
| 531 | * radeon_dummy_page_init - init dummy page used by the driver | ||
| 532 | * | ||
| 533 | * @rdev: radeon_device pointer | ||
| 534 | * | ||
| 535 | * Allocate the dummy page used by the driver (all asics). | ||
| 536 | * This dummy page is used by the driver as a filler for gart entries | ||
| 537 | * when pages are taken out of the GART | ||
| 538 | * Returns 0 on sucess, -ENOMEM on failure. | ||
| 539 | */ | ||
| 445 | int radeon_dummy_page_init(struct radeon_device *rdev) | 540 | int radeon_dummy_page_init(struct radeon_device *rdev) |
| 446 | { | 541 | { |
| 447 | if (rdev->dummy_page.page) | 542 | if (rdev->dummy_page.page) |
| @@ -460,6 +555,13 @@ int radeon_dummy_page_init(struct radeon_device *rdev) | |||
| 460 | return 0; | 555 | return 0; |
| 461 | } | 556 | } |
| 462 | 557 | ||
| 558 | /** | ||
| 559 | * radeon_dummy_page_fini - free dummy page used by the driver | ||
| 560 | * | ||
| 561 | * @rdev: radeon_device pointer | ||
| 562 | * | ||
| 563 | * Frees the dummy page used by the driver (all asics). | ||
| 564 | */ | ||
| 463 | void radeon_dummy_page_fini(struct radeon_device *rdev) | 565 | void radeon_dummy_page_fini(struct radeon_device *rdev) |
| 464 | { | 566 | { |
| 465 | if (rdev->dummy_page.page == NULL) | 567 | if (rdev->dummy_page.page == NULL) |
| @@ -472,6 +574,23 @@ void radeon_dummy_page_fini(struct radeon_device *rdev) | |||
| 472 | 574 | ||
| 473 | 575 | ||
| 474 | /* ATOM accessor methods */ | 576 | /* ATOM accessor methods */ |
| 577 | /* | ||
| 578 | * ATOM is an interpreted byte code stored in tables in the vbios. The | ||
| 579 | * driver registers callbacks to access registers and the interpreter | ||
| 580 | * in the driver parses the tables and executes then to program specific | ||
| 581 | * actions (set display modes, asic init, etc.). See radeon_atombios.c, | ||
| 582 | * atombios.h, and atom.c | ||
| 583 | */ | ||
| 584 | |||
| 585 | /** | ||
| 586 | * cail_pll_read - read PLL register | ||
| 587 | * | ||
| 588 | * @info: atom card_info pointer | ||
| 589 | * @reg: PLL register offset | ||
| 590 | * | ||
| 591 | * Provides a PLL register accessor for the atom interpreter (r4xx+). | ||
| 592 | * Returns the value of the PLL register. | ||
| 593 | */ | ||
| 475 | static uint32_t cail_pll_read(struct card_info *info, uint32_t reg) | 594 | static uint32_t cail_pll_read(struct card_info *info, uint32_t reg) |
| 476 | { | 595 | { |
| 477 | struct radeon_device *rdev = info->dev->dev_private; | 596 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -481,6 +600,15 @@ static uint32_t cail_pll_read(struct card_info *info, uint32_t reg) | |||
| 481 | return r; | 600 | return r; |
| 482 | } | 601 | } |
| 483 | 602 | ||
| 603 | /** | ||
| 604 | * cail_pll_write - write PLL register | ||
| 605 | * | ||
| 606 | * @info: atom card_info pointer | ||
| 607 | * @reg: PLL register offset | ||
| 608 | * @val: value to write to the pll register | ||
| 609 | * | ||
| 610 | * Provides a PLL register accessor for the atom interpreter (r4xx+). | ||
| 611 | */ | ||
| 484 | static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) | 612 | static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) |
| 485 | { | 613 | { |
| 486 | struct radeon_device *rdev = info->dev->dev_private; | 614 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -488,6 +616,15 @@ static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) | |||
| 488 | rdev->pll_wreg(rdev, reg, val); | 616 | rdev->pll_wreg(rdev, reg, val); |
| 489 | } | 617 | } |
| 490 | 618 | ||
| 619 | /** | ||
| 620 | * cail_mc_read - read MC (Memory Controller) register | ||
| 621 | * | ||
| 622 | * @info: atom card_info pointer | ||
| 623 | * @reg: MC register offset | ||
| 624 | * | ||
| 625 | * Provides an MC register accessor for the atom interpreter (r4xx+). | ||
| 626 | * Returns the value of the MC register. | ||
| 627 | */ | ||
| 491 | static uint32_t cail_mc_read(struct card_info *info, uint32_t reg) | 628 | static uint32_t cail_mc_read(struct card_info *info, uint32_t reg) |
| 492 | { | 629 | { |
| 493 | struct radeon_device *rdev = info->dev->dev_private; | 630 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -497,6 +634,15 @@ static uint32_t cail_mc_read(struct card_info *info, uint32_t reg) | |||
| 497 | return r; | 634 | return r; |
| 498 | } | 635 | } |
| 499 | 636 | ||
| 637 | /** | ||
| 638 | * cail_mc_write - write MC (Memory Controller) register | ||
| 639 | * | ||
| 640 | * @info: atom card_info pointer | ||
| 641 | * @reg: MC register offset | ||
| 642 | * @val: value to write to the pll register | ||
| 643 | * | ||
| 644 | * Provides a MC register accessor for the atom interpreter (r4xx+). | ||
| 645 | */ | ||
| 500 | static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) | 646 | static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) |
| 501 | { | 647 | { |
| 502 | struct radeon_device *rdev = info->dev->dev_private; | 648 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -504,6 +650,15 @@ static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) | |||
| 504 | rdev->mc_wreg(rdev, reg, val); | 650 | rdev->mc_wreg(rdev, reg, val); |
| 505 | } | 651 | } |
| 506 | 652 | ||
| 653 | /** | ||
| 654 | * cail_reg_write - write MMIO register | ||
| 655 | * | ||
| 656 | * @info: atom card_info pointer | ||
| 657 | * @reg: MMIO register offset | ||
| 658 | * @val: value to write to the pll register | ||
| 659 | * | ||
| 660 | * Provides a MMIO register accessor for the atom interpreter (r4xx+). | ||
| 661 | */ | ||
| 507 | static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) | 662 | static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) |
| 508 | { | 663 | { |
| 509 | struct radeon_device *rdev = info->dev->dev_private; | 664 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -511,6 +666,15 @@ static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) | |||
| 511 | WREG32(reg*4, val); | 666 | WREG32(reg*4, val); |
| 512 | } | 667 | } |
| 513 | 668 | ||
| 669 | /** | ||
| 670 | * cail_reg_read - read MMIO register | ||
| 671 | * | ||
| 672 | * @info: atom card_info pointer | ||
| 673 | * @reg: MMIO register offset | ||
| 674 | * | ||
| 675 | * Provides an MMIO register accessor for the atom interpreter (r4xx+). | ||
| 676 | * Returns the value of the MMIO register. | ||
| 677 | */ | ||
| 514 | static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) | 678 | static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) |
| 515 | { | 679 | { |
| 516 | struct radeon_device *rdev = info->dev->dev_private; | 680 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -520,6 +684,15 @@ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) | |||
| 520 | return r; | 684 | return r; |
| 521 | } | 685 | } |
| 522 | 686 | ||
| 687 | /** | ||
| 688 | * cail_ioreg_write - write IO register | ||
| 689 | * | ||
| 690 | * @info: atom card_info pointer | ||
| 691 | * @reg: IO register offset | ||
| 692 | * @val: value to write to the pll register | ||
| 693 | * | ||
| 694 | * Provides a IO register accessor for the atom interpreter (r4xx+). | ||
| 695 | */ | ||
| 523 | static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) | 696 | static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) |
| 524 | { | 697 | { |
| 525 | struct radeon_device *rdev = info->dev->dev_private; | 698 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -527,6 +700,15 @@ static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) | |||
| 527 | WREG32_IO(reg*4, val); | 700 | WREG32_IO(reg*4, val); |
| 528 | } | 701 | } |
| 529 | 702 | ||
| 703 | /** | ||
| 704 | * cail_ioreg_read - read IO register | ||
| 705 | * | ||
| 706 | * @info: atom card_info pointer | ||
| 707 | * @reg: IO register offset | ||
| 708 | * | ||
| 709 | * Provides an IO register accessor for the atom interpreter (r4xx+). | ||
| 710 | * Returns the value of the IO register. | ||
| 711 | */ | ||
| 530 | static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) | 712 | static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) |
| 531 | { | 713 | { |
| 532 | struct radeon_device *rdev = info->dev->dev_private; | 714 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -536,6 +718,16 @@ static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) | |||
| 536 | return r; | 718 | return r; |
| 537 | } | 719 | } |
| 538 | 720 | ||
| 721 | /** | ||
| 722 | * radeon_atombios_init - init the driver info and callbacks for atombios | ||
| 723 | * | ||
| 724 | * @rdev: radeon_device pointer | ||
| 725 | * | ||
| 726 | * Initializes the driver info and register access callbacks for the | ||
| 727 | * ATOM interpreter (r4xx+). | ||
| 728 | * Returns 0 on sucess, -ENOMEM on failure. | ||
| 729 | * Called at driver startup. | ||
| 730 | */ | ||
| 539 | int radeon_atombios_init(struct radeon_device *rdev) | 731 | int radeon_atombios_init(struct radeon_device *rdev) |
| 540 | { | 732 | { |
| 541 | struct card_info *atom_card_info = | 733 | struct card_info *atom_card_info = |
| @@ -569,6 +761,15 @@ int radeon_atombios_init(struct radeon_device *rdev) | |||
| 569 | return 0; | 761 | return 0; |
| 570 | } | 762 | } |
| 571 | 763 | ||
| 764 | /** | ||
| 765 | * radeon_atombios_fini - free the driver info and callbacks for atombios | ||
| 766 | * | ||
| 767 | * @rdev: radeon_device pointer | ||
| 768 | * | ||
| 769 | * Frees the driver info and register access callbacks for the ATOM | ||
| 770 | * interpreter (r4xx+). | ||
| 771 | * Called at driver shutdown. | ||
| 772 | */ | ||
| 572 | void radeon_atombios_fini(struct radeon_device *rdev) | 773 | void radeon_atombios_fini(struct radeon_device *rdev) |
| 573 | { | 774 | { |
| 574 | if (rdev->mode_info.atom_context) { | 775 | if (rdev->mode_info.atom_context) { |
| @@ -578,17 +779,50 @@ void radeon_atombios_fini(struct radeon_device *rdev) | |||
| 578 | kfree(rdev->mode_info.atom_card_info); | 779 | kfree(rdev->mode_info.atom_card_info); |
| 579 | } | 780 | } |
| 580 | 781 | ||
| 782 | /* COMBIOS */ | ||
| 783 | /* | ||
| 784 | * COMBIOS is the bios format prior to ATOM. It provides | ||
| 785 | * command tables similar to ATOM, but doesn't have a unified | ||
| 786 | * parser. See radeon_combios.c | ||
| 787 | */ | ||
| 788 | |||
| 789 | /** | ||
| 790 | * radeon_combios_init - init the driver info for combios | ||
| 791 | * | ||
| 792 | * @rdev: radeon_device pointer | ||
| 793 | * | ||
| 794 | * Initializes the driver info for combios (r1xx-r3xx). | ||
| 795 | * Returns 0 on sucess. | ||
| 796 | * Called at driver startup. | ||
| 797 | */ | ||
| 581 | int radeon_combios_init(struct radeon_device *rdev) | 798 | int radeon_combios_init(struct radeon_device *rdev) |
| 582 | { | 799 | { |
| 583 | radeon_combios_initialize_bios_scratch_regs(rdev->ddev); | 800 | radeon_combios_initialize_bios_scratch_regs(rdev->ddev); |
| 584 | return 0; | 801 | return 0; |
| 585 | } | 802 | } |
| 586 | 803 | ||
| 804 | /** | ||
| 805 | * radeon_combios_fini - free the driver info for combios | ||
| 806 | * | ||
| 807 | * @rdev: radeon_device pointer | ||
| 808 | * | ||
| 809 | * Frees the driver info for combios (r1xx-r3xx). | ||
| 810 | * Called at driver shutdown. | ||
| 811 | */ | ||
| 587 | void radeon_combios_fini(struct radeon_device *rdev) | 812 | void radeon_combios_fini(struct radeon_device *rdev) |
| 588 | { | 813 | { |
| 589 | } | 814 | } |
| 590 | 815 | ||
| 591 | /* if we get transitioned to only one device, tak VGA back */ | 816 | /* if we get transitioned to only one device, take VGA back */ |
| 817 | /** | ||
| 818 | * radeon_vga_set_decode - enable/disable vga decode | ||
| 819 | * | ||
| 820 | * @cookie: radeon_device pointer | ||
| 821 | * @state: enable/disable vga decode | ||
| 822 | * | ||
| 823 | * Enable/disable vga decode (all asics). | ||
| 824 | * Returns VGA resource flags. | ||
| 825 | */ | ||
| 592 | static unsigned int radeon_vga_set_decode(void *cookie, bool state) | 826 | static unsigned int radeon_vga_set_decode(void *cookie, bool state) |
| 593 | { | 827 | { |
| 594 | struct radeon_device *rdev = cookie; | 828 | struct radeon_device *rdev = cookie; |
| @@ -600,6 +834,14 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state) | |||
| 600 | return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | 834 | return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; |
| 601 | } | 835 | } |
| 602 | 836 | ||
| 837 | /** | ||
| 838 | * radeon_check_arguments - validate module params | ||
| 839 | * | ||
| 840 | * @rdev: radeon_device pointer | ||
| 841 | * | ||
| 842 | * Validates certain module parameters and updates | ||
| 843 | * the associated values used by the driver (all asics). | ||
| 844 | */ | ||
| 603 | void radeon_check_arguments(struct radeon_device *rdev) | 845 | void radeon_check_arguments(struct radeon_device *rdev) |
| 604 | { | 846 | { |
| 605 | /* vramlimit must be a power of two */ | 847 | /* vramlimit must be a power of two */ |
| @@ -666,6 +908,15 @@ void radeon_check_arguments(struct radeon_device *rdev) | |||
| 666 | } | 908 | } |
| 667 | } | 909 | } |
| 668 | 910 | ||
| 911 | /** | ||
| 912 | * radeon_switcheroo_set_state - set switcheroo state | ||
| 913 | * | ||
| 914 | * @pdev: pci dev pointer | ||
| 915 | * @state: vga switcheroo state | ||
| 916 | * | ||
| 917 | * Callback for the switcheroo driver. Suspends or resumes the | ||
| 918 | * the asics before or after it is powered up using ACPI methods. | ||
| 919 | */ | ||
| 669 | static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) | 920 | static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) |
| 670 | { | 921 | { |
| 671 | struct drm_device *dev = pci_get_drvdata(pdev); | 922 | struct drm_device *dev = pci_get_drvdata(pdev); |
| @@ -686,6 +937,15 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero | |||
| 686 | } | 937 | } |
| 687 | } | 938 | } |
| 688 | 939 | ||
| 940 | /** | ||
| 941 | * radeon_switcheroo_can_switch - see if switcheroo state can change | ||
| 942 | * | ||
| 943 | * @pdev: pci dev pointer | ||
| 944 | * | ||
| 945 | * Callback for the switcheroo driver. Check of the switcheroo | ||
| 946 | * state can be changed. | ||
| 947 | * Returns true if the state can be changed, false if not. | ||
| 948 | */ | ||
| 689 | static bool radeon_switcheroo_can_switch(struct pci_dev *pdev) | 949 | static bool radeon_switcheroo_can_switch(struct pci_dev *pdev) |
| 690 | { | 950 | { |
| 691 | struct drm_device *dev = pci_get_drvdata(pdev); | 951 | struct drm_device *dev = pci_get_drvdata(pdev); |
| @@ -703,6 +963,18 @@ static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = { | |||
| 703 | .can_switch = radeon_switcheroo_can_switch, | 963 | .can_switch = radeon_switcheroo_can_switch, |
| 704 | }; | 964 | }; |
| 705 | 965 | ||
| 966 | /** | ||
| 967 | * radeon_device_init - initialize the driver | ||
| 968 | * | ||
| 969 | * @rdev: radeon_device pointer | ||
| 970 | * @pdev: drm dev pointer | ||
| 971 | * @pdev: pci dev pointer | ||
| 972 | * @flags: driver flags | ||
| 973 | * | ||
| 974 | * Initializes the driver info and hw (all asics). | ||
| 975 | * Returns 0 for success or an error on failure. | ||
| 976 | * Called at driver startup. | ||
| 977 | */ | ||
| 706 | int radeon_device_init(struct radeon_device *rdev, | 978 | int radeon_device_init(struct radeon_device *rdev, |
| 707 | struct drm_device *ddev, | 979 | struct drm_device *ddev, |
| 708 | struct pci_dev *pdev, | 980 | struct pci_dev *pdev, |
| @@ -721,6 +993,10 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 721 | rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT; | 993 | rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT; |
| 722 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | 994 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; |
| 723 | rdev->accel_working = false; | 995 | rdev->accel_working = false; |
| 996 | /* set up ring ids */ | ||
| 997 | for (i = 0; i < RADEON_NUM_RINGS; i++) { | ||
| 998 | rdev->ring[i].idx = i; | ||
| 999 | } | ||
| 724 | 1000 | ||
| 725 | DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n", | 1001 | DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n", |
| 726 | radeon_family_name[rdev->family], pdev->vendor, pdev->device, | 1002 | radeon_family_name[rdev->family], pdev->vendor, pdev->device, |
| @@ -728,20 +1004,20 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 728 | 1004 | ||
| 729 | /* mutex initialization are all done here so we | 1005 | /* mutex initialization are all done here so we |
| 730 | * can recall function without having locking issues */ | 1006 | * can recall function without having locking issues */ |
| 731 | radeon_mutex_init(&rdev->cs_mutex); | ||
| 732 | mutex_init(&rdev->ring_lock); | 1007 | mutex_init(&rdev->ring_lock); |
| 733 | mutex_init(&rdev->dc_hw_i2c_mutex); | 1008 | mutex_init(&rdev->dc_hw_i2c_mutex); |
| 734 | if (rdev->family >= CHIP_R600) | 1009 | atomic_set(&rdev->ih.lock, 0); |
| 735 | spin_lock_init(&rdev->ih.lock); | ||
| 736 | mutex_init(&rdev->gem.mutex); | 1010 | mutex_init(&rdev->gem.mutex); |
| 737 | mutex_init(&rdev->pm.mutex); | 1011 | mutex_init(&rdev->pm.mutex); |
| 738 | mutex_init(&rdev->vram_mutex); | 1012 | init_rwsem(&rdev->pm.mclk_lock); |
| 1013 | init_rwsem(&rdev->exclusive_lock); | ||
| 739 | init_waitqueue_head(&rdev->irq.vblank_queue); | 1014 | init_waitqueue_head(&rdev->irq.vblank_queue); |
| 740 | init_waitqueue_head(&rdev->irq.idle_queue); | 1015 | init_waitqueue_head(&rdev->irq.idle_queue); |
| 741 | r = radeon_gem_init(rdev); | 1016 | r = radeon_gem_init(rdev); |
| 742 | if (r) | 1017 | if (r) |
| 743 | return r; | 1018 | return r; |
| 744 | /* initialize vm here */ | 1019 | /* initialize vm here */ |
| 1020 | mutex_init(&rdev->vm_manager.lock); | ||
| 745 | rdev->vm_manager.use_bitmap = 1; | 1021 | rdev->vm_manager.use_bitmap = 1; |
| 746 | rdev->vm_manager.max_pfn = 1 << 20; | 1022 | rdev->vm_manager.max_pfn = 1 << 20; |
| 747 | INIT_LIST_HEAD(&rdev->vm_manager.lru_vm); | 1023 | INIT_LIST_HEAD(&rdev->vm_manager.lru_vm); |
| @@ -822,6 +1098,10 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 822 | if (r) | 1098 | if (r) |
| 823 | return r; | 1099 | return r; |
| 824 | 1100 | ||
| 1101 | r = radeon_ib_ring_tests(rdev); | ||
| 1102 | if (r) | ||
| 1103 | DRM_ERROR("ib ring test failed (%d).\n", r); | ||
| 1104 | |||
| 825 | if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { | 1105 | if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { |
| 826 | /* Acceleration not working on AGP card try again | 1106 | /* Acceleration not working on AGP card try again |
| 827 | * with fallback to PCI or PCIE GART | 1107 | * with fallback to PCI or PCIE GART |
| @@ -847,6 +1127,14 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 847 | 1127 | ||
| 848 | static void radeon_debugfs_remove_files(struct radeon_device *rdev); | 1128 | static void radeon_debugfs_remove_files(struct radeon_device *rdev); |
| 849 | 1129 | ||
| 1130 | /** | ||
| 1131 | * radeon_device_fini - tear down the driver | ||
| 1132 | * | ||
| 1133 | * @rdev: radeon_device pointer | ||
| 1134 | * | ||
| 1135 | * Tear down the driver info (all asics). | ||
| 1136 | * Called at driver shutdown. | ||
| 1137 | */ | ||
| 850 | void radeon_device_fini(struct radeon_device *rdev) | 1138 | void radeon_device_fini(struct radeon_device *rdev) |
| 851 | { | 1139 | { |
| 852 | DRM_INFO("radeon: finishing device.\n"); | 1140 | DRM_INFO("radeon: finishing device.\n"); |
| @@ -868,6 +1156,16 @@ void radeon_device_fini(struct radeon_device *rdev) | |||
| 868 | /* | 1156 | /* |
| 869 | * Suspend & resume. | 1157 | * Suspend & resume. |
| 870 | */ | 1158 | */ |
| 1159 | /** | ||
| 1160 | * radeon_suspend_kms - initiate device suspend | ||
| 1161 | * | ||
| 1162 | * @pdev: drm dev pointer | ||
| 1163 | * @state: suspend state | ||
| 1164 | * | ||
| 1165 | * Puts the hw in the suspend state (all asics). | ||
| 1166 | * Returns 0 for success or an error on failure. | ||
| 1167 | * Called at driver suspend. | ||
| 1168 | */ | ||
| 871 | int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | 1169 | int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) |
| 872 | { | 1170 | { |
| 873 | struct radeon_device *rdev; | 1171 | struct radeon_device *rdev; |
| @@ -942,10 +1240,20 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
| 942 | return 0; | 1240 | return 0; |
| 943 | } | 1241 | } |
| 944 | 1242 | ||
| 1243 | /** | ||
| 1244 | * radeon_resume_kms - initiate device resume | ||
| 1245 | * | ||
| 1246 | * @pdev: drm dev pointer | ||
| 1247 | * | ||
| 1248 | * Bring the hw back to operating state (all asics). | ||
| 1249 | * Returns 0 for success or an error on failure. | ||
| 1250 | * Called at driver resume. | ||
| 1251 | */ | ||
| 945 | int radeon_resume_kms(struct drm_device *dev) | 1252 | int radeon_resume_kms(struct drm_device *dev) |
| 946 | { | 1253 | { |
| 947 | struct drm_connector *connector; | 1254 | struct drm_connector *connector; |
| 948 | struct radeon_device *rdev = dev->dev_private; | 1255 | struct radeon_device *rdev = dev->dev_private; |
| 1256 | int r; | ||
| 949 | 1257 | ||
| 950 | if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) | 1258 | if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) |
| 951 | return 0; | 1259 | return 0; |
| @@ -960,6 +1268,11 @@ int radeon_resume_kms(struct drm_device *dev) | |||
| 960 | /* resume AGP if in use */ | 1268 | /* resume AGP if in use */ |
| 961 | radeon_agp_resume(rdev); | 1269 | radeon_agp_resume(rdev); |
| 962 | radeon_resume(rdev); | 1270 | radeon_resume(rdev); |
| 1271 | |||
| 1272 | r = radeon_ib_ring_tests(rdev); | ||
| 1273 | if (r) | ||
| 1274 | DRM_ERROR("ib ring test failed (%d).\n", r); | ||
| 1275 | |||
| 963 | radeon_pm_resume(rdev); | 1276 | radeon_pm_resume(rdev); |
| 964 | radeon_restore_bios_scratch_regs(rdev); | 1277 | radeon_restore_bios_scratch_regs(rdev); |
| 965 | 1278 | ||
| @@ -984,30 +1297,77 @@ int radeon_resume_kms(struct drm_device *dev) | |||
| 984 | return 0; | 1297 | return 0; |
| 985 | } | 1298 | } |
| 986 | 1299 | ||
| 1300 | /** | ||
| 1301 | * radeon_gpu_reset - reset the asic | ||
| 1302 | * | ||
| 1303 | * @rdev: radeon device pointer | ||
| 1304 | * | ||
| 1305 | * Attempt the reset the GPU if it has hung (all asics). | ||
| 1306 | * Returns 0 for success or an error on failure. | ||
| 1307 | */ | ||
| 987 | int radeon_gpu_reset(struct radeon_device *rdev) | 1308 | int radeon_gpu_reset(struct radeon_device *rdev) |
| 988 | { | 1309 | { |
| 989 | int r; | 1310 | unsigned ring_sizes[RADEON_NUM_RINGS]; |
| 1311 | uint32_t *ring_data[RADEON_NUM_RINGS]; | ||
| 1312 | |||
| 1313 | bool saved = false; | ||
| 1314 | |||
| 1315 | int i, r; | ||
| 990 | int resched; | 1316 | int resched; |
| 991 | 1317 | ||
| 1318 | down_write(&rdev->exclusive_lock); | ||
| 992 | radeon_save_bios_scratch_regs(rdev); | 1319 | radeon_save_bios_scratch_regs(rdev); |
| 993 | /* block TTM */ | 1320 | /* block TTM */ |
| 994 | resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); | 1321 | resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); |
| 995 | radeon_suspend(rdev); | 1322 | radeon_suspend(rdev); |
| 996 | 1323 | ||
| 1324 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 1325 | ring_sizes[i] = radeon_ring_backup(rdev, &rdev->ring[i], | ||
| 1326 | &ring_data[i]); | ||
| 1327 | if (ring_sizes[i]) { | ||
| 1328 | saved = true; | ||
| 1329 | dev_info(rdev->dev, "Saved %d dwords of commands " | ||
| 1330 | "on ring %d.\n", ring_sizes[i], i); | ||
| 1331 | } | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | retry: | ||
| 997 | r = radeon_asic_reset(rdev); | 1335 | r = radeon_asic_reset(rdev); |
| 998 | if (!r) { | 1336 | if (!r) { |
| 999 | dev_info(rdev->dev, "GPU reset succeed\n"); | 1337 | dev_info(rdev->dev, "GPU reset succeeded, trying to resume\n"); |
| 1000 | radeon_resume(rdev); | 1338 | radeon_resume(rdev); |
| 1001 | radeon_restore_bios_scratch_regs(rdev); | ||
| 1002 | drm_helper_resume_force_mode(rdev->ddev); | ||
| 1003 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); | ||
| 1004 | } | 1339 | } |
| 1005 | 1340 | ||
| 1341 | radeon_restore_bios_scratch_regs(rdev); | ||
| 1342 | drm_helper_resume_force_mode(rdev->ddev); | ||
| 1343 | |||
| 1344 | if (!r) { | ||
| 1345 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 1346 | radeon_ring_restore(rdev, &rdev->ring[i], | ||
| 1347 | ring_sizes[i], ring_data[i]); | ||
| 1348 | } | ||
| 1349 | |||
| 1350 | r = radeon_ib_ring_tests(rdev); | ||
| 1351 | if (r) { | ||
| 1352 | dev_err(rdev->dev, "ib ring test failed (%d).\n", r); | ||
| 1353 | if (saved) { | ||
| 1354 | radeon_suspend(rdev); | ||
| 1355 | goto retry; | ||
| 1356 | } | ||
| 1357 | } | ||
| 1358 | } else { | ||
| 1359 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 1360 | kfree(ring_data[i]); | ||
| 1361 | } | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); | ||
| 1006 | if (r) { | 1365 | if (r) { |
| 1007 | /* bad news, how to tell it to userspace ? */ | 1366 | /* bad news, how to tell it to userspace ? */ |
| 1008 | dev_info(rdev->dev, "GPU reset failed\n"); | 1367 | dev_info(rdev->dev, "GPU reset failed\n"); |
| 1009 | } | 1368 | } |
| 1010 | 1369 | ||
| 1370 | up_write(&rdev->exclusive_lock); | ||
| 1011 | return r; | 1371 | return r; |
| 1012 | } | 1372 | } |
| 1013 | 1373 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 64a008d14493..7ddef8f30d0e 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -1401,7 +1401,7 @@ void radeon_modeset_fini(struct radeon_device *rdev) | |||
| 1401 | radeon_i2c_fini(rdev); | 1401 | radeon_i2c_fini(rdev); |
| 1402 | } | 1402 | } |
| 1403 | 1403 | ||
| 1404 | static bool is_hdtv_mode(struct drm_display_mode *mode) | 1404 | static bool is_hdtv_mode(const struct drm_display_mode *mode) |
| 1405 | { | 1405 | { |
| 1406 | /* try and guess if this is a tv or a monitor */ | 1406 | /* try and guess if this is a tv or a monitor */ |
| 1407 | if ((mode->vdisplay == 480 && mode->hdisplay == 720) || /* 480p */ | 1407 | if ((mode->vdisplay == 480 && mode->hdisplay == 720) || /* 480p */ |
| @@ -1414,7 +1414,7 @@ static bool is_hdtv_mode(struct drm_display_mode *mode) | |||
| 1414 | } | 1414 | } |
| 1415 | 1415 | ||
| 1416 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | 1416 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, |
| 1417 | struct drm_display_mode *mode, | 1417 | const struct drm_display_mode *mode, |
| 1418 | struct drm_display_mode *adjusted_mode) | 1418 | struct drm_display_mode *adjusted_mode) |
| 1419 | { | 1419 | { |
| 1420 | struct drm_device *dev = crtc->dev; | 1420 | struct drm_device *dev = crtc->dev; |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 2c4d53fd20c5..dcea6f01ae4e 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -133,7 +133,7 @@ int radeon_tv = 1; | |||
| 133 | int radeon_audio = 0; | 133 | int radeon_audio = 0; |
| 134 | int radeon_disp_priority = 0; | 134 | int radeon_disp_priority = 0; |
| 135 | int radeon_hw_i2c = 0; | 135 | int radeon_hw_i2c = 0; |
| 136 | int radeon_pcie_gen2 = 0; | 136 | int radeon_pcie_gen2 = -1; |
| 137 | int radeon_msi = -1; | 137 | int radeon_msi = -1; |
| 138 | int radeon_lockup_timeout = 10000; | 138 | int radeon_lockup_timeout = 10000; |
| 139 | 139 | ||
| @@ -179,7 +179,7 @@ module_param_named(disp_priority, radeon_disp_priority, int, 0444); | |||
| 179 | MODULE_PARM_DESC(hw_i2c, "hw i2c engine enable (0 = disable)"); | 179 | MODULE_PARM_DESC(hw_i2c, "hw i2c engine enable (0 = disable)"); |
| 180 | module_param_named(hw_i2c, radeon_hw_i2c, int, 0444); | 180 | module_param_named(hw_i2c, radeon_hw_i2c, int, 0444); |
| 181 | 181 | ||
| 182 | MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (1 = enable)"); | 182 | MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (-1 = auto, 0 = disable, 1 = enable)"); |
| 183 | module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444); | 183 | module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444); |
| 184 | 184 | ||
| 185 | MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)"); | 185 | MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)"); |
| @@ -262,7 +262,6 @@ static struct drm_driver driver_old = { | |||
| 262 | .irq_postinstall = radeon_driver_irq_postinstall, | 262 | .irq_postinstall = radeon_driver_irq_postinstall, |
| 263 | .irq_uninstall = radeon_driver_irq_uninstall, | 263 | .irq_uninstall = radeon_driver_irq_uninstall, |
| 264 | .irq_handler = radeon_driver_irq_handler, | 264 | .irq_handler = radeon_driver_irq_handler, |
| 265 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 266 | .ioctls = radeon_ioctls, | 265 | .ioctls = radeon_ioctls, |
| 267 | .dma_ioctl = radeon_cp_buffers, | 266 | .dma_ioctl = radeon_cp_buffers, |
| 268 | .fops = &radeon_driver_old_fops, | 267 | .fops = &radeon_driver_old_fops, |
| @@ -365,7 +364,6 @@ static struct drm_driver kms_driver = { | |||
| 365 | .irq_postinstall = radeon_driver_irq_postinstall_kms, | 364 | .irq_postinstall = radeon_driver_irq_postinstall_kms, |
| 366 | .irq_uninstall = radeon_driver_irq_uninstall_kms, | 365 | .irq_uninstall = radeon_driver_irq_uninstall_kms, |
| 367 | .irq_handler = radeon_driver_irq_handler_kms, | 366 | .irq_handler = radeon_driver_irq_handler_kms, |
| 368 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 369 | .ioctls = radeon_ioctls_kms, | 367 | .ioctls = radeon_ioctls_kms, |
| 370 | .gem_init_object = radeon_gem_object_init, | 368 | .gem_init_object = radeon_gem_object_init, |
| 371 | .gem_free_object = radeon_gem_object_free, | 369 | .gem_free_object = radeon_gem_object_free, |
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 11f5f402d22c..7b737b9339ad 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
| @@ -40,39 +40,95 @@ | |||
| 40 | #include "radeon.h" | 40 | #include "radeon.h" |
| 41 | #include "radeon_trace.h" | 41 | #include "radeon_trace.h" |
| 42 | 42 | ||
| 43 | /* | ||
| 44 | * Fences | ||
| 45 | * Fences mark an event in the GPUs pipeline and are used | ||
| 46 | * for GPU/CPU synchronization. When the fence is written, | ||
| 47 | * it is expected that all buffers associated with that fence | ||
| 48 | * are no longer in use by the associated ring on the GPU and | ||
| 49 | * that the the relevant GPU caches have been flushed. Whether | ||
| 50 | * we use a scratch register or memory location depends on the asic | ||
| 51 | * and whether writeback is enabled. | ||
| 52 | */ | ||
| 53 | |||
| 54 | /** | ||
| 55 | * radeon_fence_write - write a fence value | ||
| 56 | * | ||
| 57 | * @rdev: radeon_device pointer | ||
| 58 | * @seq: sequence number to write | ||
| 59 | * @ring: ring index the fence is associated with | ||
| 60 | * | ||
| 61 | * Writes a fence value to memory or a scratch register (all asics). | ||
| 62 | */ | ||
| 43 | static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring) | 63 | static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring) |
| 44 | { | 64 | { |
| 45 | if (rdev->wb.enabled) { | 65 | struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; |
| 46 | *rdev->fence_drv[ring].cpu_addr = cpu_to_le32(seq); | 66 | if (likely(rdev->wb.enabled || !drv->scratch_reg)) { |
| 67 | *drv->cpu_addr = cpu_to_le32(seq); | ||
| 47 | } else { | 68 | } else { |
| 48 | WREG32(rdev->fence_drv[ring].scratch_reg, seq); | 69 | WREG32(drv->scratch_reg, seq); |
| 49 | } | 70 | } |
| 50 | } | 71 | } |
| 51 | 72 | ||
| 73 | /** | ||
| 74 | * radeon_fence_read - read a fence value | ||
| 75 | * | ||
| 76 | * @rdev: radeon_device pointer | ||
| 77 | * @ring: ring index the fence is associated with | ||
| 78 | * | ||
| 79 | * Reads a fence value from memory or a scratch register (all asics). | ||
| 80 | * Returns the value of the fence read from memory or register. | ||
| 81 | */ | ||
| 52 | static u32 radeon_fence_read(struct radeon_device *rdev, int ring) | 82 | static u32 radeon_fence_read(struct radeon_device *rdev, int ring) |
| 53 | { | 83 | { |
| 84 | struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; | ||
| 54 | u32 seq = 0; | 85 | u32 seq = 0; |
| 55 | 86 | ||
| 56 | if (rdev->wb.enabled) { | 87 | if (likely(rdev->wb.enabled || !drv->scratch_reg)) { |
| 57 | seq = le32_to_cpu(*rdev->fence_drv[ring].cpu_addr); | 88 | seq = le32_to_cpu(*drv->cpu_addr); |
| 58 | } else { | 89 | } else { |
| 59 | seq = RREG32(rdev->fence_drv[ring].scratch_reg); | 90 | seq = RREG32(drv->scratch_reg); |
| 60 | } | 91 | } |
| 61 | return seq; | 92 | return seq; |
| 62 | } | 93 | } |
| 63 | 94 | ||
| 64 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) | 95 | /** |
| 96 | * radeon_fence_emit - emit a fence on the requested ring | ||
| 97 | * | ||
| 98 | * @rdev: radeon_device pointer | ||
| 99 | * @fence: radeon fence object | ||
| 100 | * @ring: ring index the fence is associated with | ||
| 101 | * | ||
| 102 | * Emits a fence command on the requested ring (all asics). | ||
| 103 | * Returns 0 on success, -ENOMEM on failure. | ||
| 104 | */ | ||
| 105 | int radeon_fence_emit(struct radeon_device *rdev, | ||
| 106 | struct radeon_fence **fence, | ||
| 107 | int ring) | ||
| 65 | { | 108 | { |
| 66 | /* we are protected by the ring emission mutex */ | 109 | /* we are protected by the ring emission mutex */ |
| 67 | if (fence->seq && fence->seq < RADEON_FENCE_NOTEMITED_SEQ) { | 110 | *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); |
| 68 | return 0; | 111 | if ((*fence) == NULL) { |
| 112 | return -ENOMEM; | ||
| 69 | } | 113 | } |
| 70 | fence->seq = ++rdev->fence_drv[fence->ring].seq; | 114 | kref_init(&((*fence)->kref)); |
| 71 | radeon_fence_ring_emit(rdev, fence->ring, fence); | 115 | (*fence)->rdev = rdev; |
| 72 | trace_radeon_fence_emit(rdev->ddev, fence->seq); | 116 | (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring]; |
| 117 | (*fence)->ring = ring; | ||
| 118 | radeon_fence_ring_emit(rdev, ring, *fence); | ||
| 119 | trace_radeon_fence_emit(rdev->ddev, (*fence)->seq); | ||
| 73 | return 0; | 120 | return 0; |
| 74 | } | 121 | } |
| 75 | 122 | ||
| 123 | /** | ||
| 124 | * radeon_fence_process - process a fence | ||
| 125 | * | ||
| 126 | * @rdev: radeon_device pointer | ||
| 127 | * @ring: ring index the fence is associated with | ||
| 128 | * | ||
| 129 | * Checks the current fence value and wakes the fence queue | ||
| 130 | * if the sequence number has increased (all asics). | ||
| 131 | */ | ||
| 76 | void radeon_fence_process(struct radeon_device *rdev, int ring) | 132 | void radeon_fence_process(struct radeon_device *rdev, int ring) |
| 77 | { | 133 | { |
| 78 | uint64_t seq, last_seq; | 134 | uint64_t seq, last_seq; |
| @@ -133,30 +189,35 @@ void radeon_fence_process(struct radeon_device *rdev, int ring) | |||
| 133 | } | 189 | } |
| 134 | } | 190 | } |
| 135 | 191 | ||
| 192 | /** | ||
| 193 | * radeon_fence_destroy - destroy a fence | ||
| 194 | * | ||
| 195 | * @kref: fence kref | ||
| 196 | * | ||
| 197 | * Frees the fence object (all asics). | ||
| 198 | */ | ||
| 136 | static void radeon_fence_destroy(struct kref *kref) | 199 | static void radeon_fence_destroy(struct kref *kref) |
| 137 | { | 200 | { |
| 138 | struct radeon_fence *fence; | 201 | struct radeon_fence *fence; |
| 139 | 202 | ||
| 140 | fence = container_of(kref, struct radeon_fence, kref); | 203 | fence = container_of(kref, struct radeon_fence, kref); |
| 141 | fence->seq = RADEON_FENCE_NOTEMITED_SEQ; | ||
| 142 | kfree(fence); | 204 | kfree(fence); |
| 143 | } | 205 | } |
| 144 | 206 | ||
| 145 | int radeon_fence_create(struct radeon_device *rdev, | 207 | /** |
| 146 | struct radeon_fence **fence, | 208 | * radeon_fence_seq_signaled - check if a fence sequeuce number has signaled |
| 147 | int ring) | 209 | * |
| 148 | { | 210 | * @rdev: radeon device pointer |
| 149 | *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); | 211 | * @seq: sequence number |
| 150 | if ((*fence) == NULL) { | 212 | * @ring: ring index the fence is associated with |
| 151 | return -ENOMEM; | 213 | * |
| 152 | } | 214 | * Check if the last singled fence sequnce number is >= the requested |
| 153 | kref_init(&((*fence)->kref)); | 215 | * sequence number (all asics). |
| 154 | (*fence)->rdev = rdev; | 216 | * Returns true if the fence has signaled (current fence value |
| 155 | (*fence)->seq = RADEON_FENCE_NOTEMITED_SEQ; | 217 | * is >= requested value) or false if it has not (current fence |
| 156 | (*fence)->ring = ring; | 218 | * value is < the requested value. Helper function for |
| 157 | return 0; | 219 | * radeon_fence_signaled(). |
| 158 | } | 220 | */ |
| 159 | |||
| 160 | static bool radeon_fence_seq_signaled(struct radeon_device *rdev, | 221 | static bool radeon_fence_seq_signaled(struct radeon_device *rdev, |
| 161 | u64 seq, unsigned ring) | 222 | u64 seq, unsigned ring) |
| 162 | { | 223 | { |
| @@ -171,15 +232,19 @@ static bool radeon_fence_seq_signaled(struct radeon_device *rdev, | |||
| 171 | return false; | 232 | return false; |
| 172 | } | 233 | } |
| 173 | 234 | ||
| 235 | /** | ||
| 236 | * radeon_fence_signaled - check if a fence has signaled | ||
| 237 | * | ||
| 238 | * @fence: radeon fence object | ||
| 239 | * | ||
| 240 | * Check if the requested fence has signaled (all asics). | ||
| 241 | * Returns true if the fence has signaled or false if it has not. | ||
| 242 | */ | ||
| 174 | bool radeon_fence_signaled(struct radeon_fence *fence) | 243 | bool radeon_fence_signaled(struct radeon_fence *fence) |
| 175 | { | 244 | { |
| 176 | if (!fence) { | 245 | if (!fence) { |
| 177 | return true; | 246 | return true; |
| 178 | } | 247 | } |
| 179 | if (fence->seq == RADEON_FENCE_NOTEMITED_SEQ) { | ||
| 180 | WARN(1, "Querying an unemitted fence : %p !\n", fence); | ||
| 181 | return true; | ||
| 182 | } | ||
| 183 | if (fence->seq == RADEON_FENCE_SIGNALED_SEQ) { | 248 | if (fence->seq == RADEON_FENCE_SIGNALED_SEQ) { |
| 184 | return true; | 249 | return true; |
| 185 | } | 250 | } |
| @@ -190,6 +255,24 @@ bool radeon_fence_signaled(struct radeon_fence *fence) | |||
| 190 | return false; | 255 | return false; |
| 191 | } | 256 | } |
| 192 | 257 | ||
| 258 | /** | ||
| 259 | * radeon_fence_wait_seq - wait for a specific sequence number | ||
| 260 | * | ||
| 261 | * @rdev: radeon device pointer | ||
| 262 | * @target_seq: sequence number we want to wait for | ||
| 263 | * @ring: ring index the fence is associated with | ||
| 264 | * @intr: use interruptable sleep | ||
| 265 | * @lock_ring: whether the ring should be locked or not | ||
| 266 | * | ||
| 267 | * Wait for the requested sequence number to be written (all asics). | ||
| 268 | * @intr selects whether to use interruptable (true) or non-interruptable | ||
| 269 | * (false) sleep when waiting for the sequence number. Helper function | ||
| 270 | * for radeon_fence_wait(), et al. | ||
| 271 | * Returns 0 if the sequence number has passed, error for all other cases. | ||
| 272 | * -EDEADLK is returned when a GPU lockup has been detected and the ring is | ||
| 273 | * marked as not ready so no further jobs get scheduled until a successful | ||
| 274 | * reset. | ||
| 275 | */ | ||
| 193 | static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, | 276 | static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, |
| 194 | unsigned ring, bool intr, bool lock_ring) | 277 | unsigned ring, bool intr, bool lock_ring) |
| 195 | { | 278 | { |
| @@ -285,6 +368,17 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, | |||
| 285 | return 0; | 368 | return 0; |
| 286 | } | 369 | } |
| 287 | 370 | ||
| 371 | /** | ||
| 372 | * radeon_fence_wait - wait for a fence to signal | ||
| 373 | * | ||
| 374 | * @fence: radeon fence object | ||
| 375 | * @intr: use interruptable sleep | ||
| 376 | * | ||
| 377 | * Wait for the requested fence to signal (all asics). | ||
| 378 | * @intr selects whether to use interruptable (true) or non-interruptable | ||
| 379 | * (false) sleep when waiting for the fence. | ||
| 380 | * Returns 0 if the fence has passed, error for all other cases. | ||
| 381 | */ | ||
| 288 | int radeon_fence_wait(struct radeon_fence *fence, bool intr) | 382 | int radeon_fence_wait(struct radeon_fence *fence, bool intr) |
| 289 | { | 383 | { |
| 290 | int r; | 384 | int r; |
| @@ -315,6 +409,20 @@ bool radeon_fence_any_seq_signaled(struct radeon_device *rdev, u64 *seq) | |||
| 315 | return false; | 409 | return false; |
| 316 | } | 410 | } |
| 317 | 411 | ||
| 412 | /** | ||
| 413 | * radeon_fence_wait_any_seq - wait for a sequence number on any ring | ||
| 414 | * | ||
| 415 | * @rdev: radeon device pointer | ||
| 416 | * @target_seq: sequence number(s) we want to wait for | ||
| 417 | * @intr: use interruptable sleep | ||
| 418 | * | ||
| 419 | * Wait for the requested sequence number(s) to be written by any ring | ||
| 420 | * (all asics). Sequnce number array is indexed by ring id. | ||
| 421 | * @intr selects whether to use interruptable (true) or non-interruptable | ||
| 422 | * (false) sleep when waiting for the sequence number. Helper function | ||
| 423 | * for radeon_fence_wait_any(), et al. | ||
| 424 | * Returns 0 if the sequence number has passed, error for all other cases. | ||
| 425 | */ | ||
| 318 | static int radeon_fence_wait_any_seq(struct radeon_device *rdev, | 426 | static int radeon_fence_wait_any_seq(struct radeon_device *rdev, |
| 319 | u64 *target_seq, bool intr) | 427 | u64 *target_seq, bool intr) |
| 320 | { | 428 | { |
| @@ -343,7 +451,7 @@ static int radeon_fence_wait_any_seq(struct radeon_device *rdev, | |||
| 343 | 451 | ||
| 344 | /* nothing to wait for ? */ | 452 | /* nothing to wait for ? */ |
| 345 | if (ring == RADEON_NUM_RINGS) { | 453 | if (ring == RADEON_NUM_RINGS) { |
| 346 | return 0; | 454 | return -ENOENT; |
| 347 | } | 455 | } |
| 348 | 456 | ||
| 349 | while (!radeon_fence_any_seq_signaled(rdev, target_seq)) { | 457 | while (!radeon_fence_any_seq_signaled(rdev, target_seq)) { |
| @@ -424,6 +532,19 @@ static int radeon_fence_wait_any_seq(struct radeon_device *rdev, | |||
| 424 | return 0; | 532 | return 0; |
| 425 | } | 533 | } |
| 426 | 534 | ||
| 535 | /** | ||
| 536 | * radeon_fence_wait_any - wait for a fence to signal on any ring | ||
| 537 | * | ||
| 538 | * @rdev: radeon device pointer | ||
| 539 | * @fences: radeon fence object(s) | ||
| 540 | * @intr: use interruptable sleep | ||
| 541 | * | ||
| 542 | * Wait for any requested fence to signal (all asics). Fence | ||
| 543 | * array is indexed by ring id. @intr selects whether to use | ||
| 544 | * interruptable (true) or non-interruptable (false) sleep when | ||
| 545 | * waiting for the fences. Used by the suballocator. | ||
| 546 | * Returns 0 if any fence has passed, error for all other cases. | ||
| 547 | */ | ||
| 427 | int radeon_fence_wait_any(struct radeon_device *rdev, | 548 | int radeon_fence_wait_any(struct radeon_device *rdev, |
| 428 | struct radeon_fence **fences, | 549 | struct radeon_fence **fences, |
| 429 | bool intr) | 550 | bool intr) |
| @@ -444,9 +565,7 @@ int radeon_fence_wait_any(struct radeon_device *rdev, | |||
| 444 | return 0; | 565 | return 0; |
| 445 | } | 566 | } |
| 446 | 567 | ||
| 447 | if (fences[i]->seq < RADEON_FENCE_NOTEMITED_SEQ) { | 568 | seq[i] = fences[i]->seq; |
| 448 | seq[i] = fences[i]->seq; | ||
| 449 | } | ||
| 450 | } | 569 | } |
| 451 | 570 | ||
| 452 | r = radeon_fence_wait_any_seq(rdev, seq, intr); | 571 | r = radeon_fence_wait_any_seq(rdev, seq, intr); |
| @@ -456,16 +575,22 @@ int radeon_fence_wait_any(struct radeon_device *rdev, | |||
| 456 | return 0; | 575 | return 0; |
| 457 | } | 576 | } |
| 458 | 577 | ||
| 578 | /** | ||
| 579 | * radeon_fence_wait_next_locked - wait for the next fence to signal | ||
| 580 | * | ||
| 581 | * @rdev: radeon device pointer | ||
| 582 | * @ring: ring index the fence is associated with | ||
| 583 | * | ||
| 584 | * Wait for the next fence on the requested ring to signal (all asics). | ||
| 585 | * Returns 0 if the next fence has passed, error for all other cases. | ||
| 586 | * Caller must hold ring lock. | ||
| 587 | */ | ||
| 459 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) | 588 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) |
| 460 | { | 589 | { |
| 461 | uint64_t seq; | 590 | uint64_t seq; |
| 462 | 591 | ||
| 463 | /* We are not protected by ring lock when reading current seq but | ||
| 464 | * it's ok as worst case is we return to early while we could have | ||
| 465 | * wait. | ||
| 466 | */ | ||
| 467 | seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL; | 592 | seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL; |
| 468 | if (seq >= rdev->fence_drv[ring].seq) { | 593 | if (seq >= rdev->fence_drv[ring].sync_seq[ring]) { |
| 469 | /* nothing to wait for, last_seq is | 594 | /* nothing to wait for, last_seq is |
| 470 | already the last emited fence */ | 595 | already the last emited fence */ |
| 471 | return -ENOENT; | 596 | return -ENOENT; |
| @@ -473,23 +598,59 @@ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) | |||
| 473 | return radeon_fence_wait_seq(rdev, seq, ring, false, false); | 598 | return radeon_fence_wait_seq(rdev, seq, ring, false, false); |
| 474 | } | 599 | } |
| 475 | 600 | ||
| 476 | int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) | 601 | /** |
| 602 | * radeon_fence_wait_empty_locked - wait for all fences to signal | ||
| 603 | * | ||
| 604 | * @rdev: radeon device pointer | ||
| 605 | * @ring: ring index the fence is associated with | ||
| 606 | * | ||
| 607 | * Wait for all fences on the requested ring to signal (all asics). | ||
| 608 | * Returns 0 if the fences have passed, error for all other cases. | ||
| 609 | * Caller must hold ring lock. | ||
| 610 | */ | ||
| 611 | void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) | ||
| 477 | { | 612 | { |
| 478 | /* We are not protected by ring lock when reading current seq | 613 | uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; |
| 479 | * but it's ok as wait empty is call from place where no more | 614 | |
| 480 | * activity can be scheduled so there won't be concurrent access | 615 | while(1) { |
| 481 | * to seq value. | 616 | int r; |
| 482 | */ | 617 | r = radeon_fence_wait_seq(rdev, seq, ring, false, false); |
| 483 | return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].seq, | 618 | if (r == -EDEADLK) { |
| 484 | ring, false, false); | 619 | mutex_unlock(&rdev->ring_lock); |
| 620 | r = radeon_gpu_reset(rdev); | ||
| 621 | mutex_lock(&rdev->ring_lock); | ||
| 622 | if (!r) | ||
| 623 | continue; | ||
| 624 | } | ||
| 625 | if (r) { | ||
| 626 | dev_err(rdev->dev, "error waiting for ring to become" | ||
| 627 | " idle (%d)\n", r); | ||
| 628 | } | ||
| 629 | return; | ||
| 630 | } | ||
| 485 | } | 631 | } |
| 486 | 632 | ||
| 633 | /** | ||
| 634 | * radeon_fence_ref - take a ref on a fence | ||
| 635 | * | ||
| 636 | * @fence: radeon fence object | ||
| 637 | * | ||
| 638 | * Take a reference on a fence (all asics). | ||
| 639 | * Returns the fence. | ||
| 640 | */ | ||
| 487 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) | 641 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) |
| 488 | { | 642 | { |
| 489 | kref_get(&fence->kref); | 643 | kref_get(&fence->kref); |
| 490 | return fence; | 644 | return fence; |
| 491 | } | 645 | } |
| 492 | 646 | ||
| 647 | /** | ||
| 648 | * radeon_fence_unref - remove a ref on a fence | ||
| 649 | * | ||
| 650 | * @fence: radeon fence object | ||
| 651 | * | ||
| 652 | * Remove a reference on a fence (all asics). | ||
| 653 | */ | ||
| 493 | void radeon_fence_unref(struct radeon_fence **fence) | 654 | void radeon_fence_unref(struct radeon_fence **fence) |
| 494 | { | 655 | { |
| 495 | struct radeon_fence *tmp = *fence; | 656 | struct radeon_fence *tmp = *fence; |
| @@ -500,6 +661,16 @@ void radeon_fence_unref(struct radeon_fence **fence) | |||
| 500 | } | 661 | } |
| 501 | } | 662 | } |
| 502 | 663 | ||
| 664 | /** | ||
| 665 | * radeon_fence_count_emitted - get the count of emitted fences | ||
| 666 | * | ||
| 667 | * @rdev: radeon device pointer | ||
| 668 | * @ring: ring index the fence is associated with | ||
| 669 | * | ||
| 670 | * Get the number of fences emitted on the requested ring (all asics). | ||
| 671 | * Returns the number of emitted fences on the ring. Used by the | ||
| 672 | * dynpm code to ring track activity. | ||
| 673 | */ | ||
| 503 | unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) | 674 | unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) |
| 504 | { | 675 | { |
| 505 | uint64_t emitted; | 676 | uint64_t emitted; |
| @@ -508,7 +679,8 @@ unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) | |||
| 508 | * but it's ok to report slightly wrong fence count here. | 679 | * but it's ok to report slightly wrong fence count here. |
| 509 | */ | 680 | */ |
| 510 | radeon_fence_process(rdev, ring); | 681 | radeon_fence_process(rdev, ring); |
| 511 | emitted = rdev->fence_drv[ring].seq - atomic64_read(&rdev->fence_drv[ring].last_seq); | 682 | emitted = rdev->fence_drv[ring].sync_seq[ring] |
| 683 | - atomic64_read(&rdev->fence_drv[ring].last_seq); | ||
| 512 | /* to avoid 32bits warp around */ | 684 | /* to avoid 32bits warp around */ |
| 513 | if (emitted > 0x10000000) { | 685 | if (emitted > 0x10000000) { |
| 514 | emitted = 0x10000000; | 686 | emitted = 0x10000000; |
| @@ -516,6 +688,83 @@ unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) | |||
| 516 | return (unsigned)emitted; | 688 | return (unsigned)emitted; |
| 517 | } | 689 | } |
| 518 | 690 | ||
| 691 | /** | ||
| 692 | * radeon_fence_need_sync - do we need a semaphore | ||
| 693 | * | ||
| 694 | * @fence: radeon fence object | ||
| 695 | * @dst_ring: which ring to check against | ||
| 696 | * | ||
| 697 | * Check if the fence needs to be synced against another ring | ||
| 698 | * (all asics). If so, we need to emit a semaphore. | ||
| 699 | * Returns true if we need to sync with another ring, false if | ||
| 700 | * not. | ||
| 701 | */ | ||
| 702 | bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring) | ||
| 703 | { | ||
| 704 | struct radeon_fence_driver *fdrv; | ||
| 705 | |||
| 706 | if (!fence) { | ||
| 707 | return false; | ||
| 708 | } | ||
| 709 | |||
| 710 | if (fence->ring == dst_ring) { | ||
| 711 | return false; | ||
| 712 | } | ||
| 713 | |||
| 714 | /* we are protected by the ring mutex */ | ||
| 715 | fdrv = &fence->rdev->fence_drv[dst_ring]; | ||
| 716 | if (fence->seq <= fdrv->sync_seq[fence->ring]) { | ||
| 717 | return false; | ||
| 718 | } | ||
| 719 | |||
| 720 | return true; | ||
| 721 | } | ||
| 722 | |||
| 723 | /** | ||
| 724 | * radeon_fence_note_sync - record the sync point | ||
| 725 | * | ||
| 726 | * @fence: radeon fence object | ||
| 727 | * @dst_ring: which ring to check against | ||
| 728 | * | ||
| 729 | * Note the sequence number at which point the fence will | ||
| 730 | * be synced with the requested ring (all asics). | ||
| 731 | */ | ||
| 732 | void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring) | ||
| 733 | { | ||
| 734 | struct radeon_fence_driver *dst, *src; | ||
| 735 | unsigned i; | ||
| 736 | |||
| 737 | if (!fence) { | ||
| 738 | return; | ||
| 739 | } | ||
| 740 | |||
| 741 | if (fence->ring == dst_ring) { | ||
| 742 | return; | ||
| 743 | } | ||
| 744 | |||
| 745 | /* we are protected by the ring mutex */ | ||
| 746 | src = &fence->rdev->fence_drv[fence->ring]; | ||
| 747 | dst = &fence->rdev->fence_drv[dst_ring]; | ||
| 748 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 749 | if (i == dst_ring) { | ||
| 750 | continue; | ||
| 751 | } | ||
| 752 | dst->sync_seq[i] = max(dst->sync_seq[i], src->sync_seq[i]); | ||
| 753 | } | ||
| 754 | } | ||
| 755 | |||
| 756 | /** | ||
| 757 | * radeon_fence_driver_start_ring - make the fence driver | ||
| 758 | * ready for use on the requested ring. | ||
| 759 | * | ||
| 760 | * @rdev: radeon device pointer | ||
| 761 | * @ring: ring index to start the fence driver on | ||
| 762 | * | ||
| 763 | * Make the fence driver ready for processing (all asics). | ||
| 764 | * Not all asics have all rings, so each asic will only | ||
| 765 | * start the fence driver on the rings it has. | ||
| 766 | * Returns 0 for success, errors for failure. | ||
| 767 | */ | ||
| 519 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) | 768 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) |
| 520 | { | 769 | { |
| 521 | uint64_t index; | 770 | uint64_t index; |
| @@ -537,24 +786,49 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) | |||
| 537 | } | 786 | } |
| 538 | rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4]; | 787 | rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4]; |
| 539 | rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index; | 788 | rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index; |
| 540 | radeon_fence_write(rdev, rdev->fence_drv[ring].seq, ring); | 789 | radeon_fence_write(rdev, atomic64_read(&rdev->fence_drv[ring].last_seq), ring); |
| 541 | rdev->fence_drv[ring].initialized = true; | 790 | rdev->fence_drv[ring].initialized = true; |
| 542 | dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016llx and cpu addr 0x%p\n", | 791 | dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016llx and cpu addr 0x%p\n", |
| 543 | ring, rdev->fence_drv[ring].gpu_addr, rdev->fence_drv[ring].cpu_addr); | 792 | ring, rdev->fence_drv[ring].gpu_addr, rdev->fence_drv[ring].cpu_addr); |
| 544 | return 0; | 793 | return 0; |
| 545 | } | 794 | } |
| 546 | 795 | ||
| 796 | /** | ||
| 797 | * radeon_fence_driver_init_ring - init the fence driver | ||
| 798 | * for the requested ring. | ||
| 799 | * | ||
| 800 | * @rdev: radeon device pointer | ||
| 801 | * @ring: ring index to start the fence driver on | ||
| 802 | * | ||
| 803 | * Init the fence driver for the requested ring (all asics). | ||
| 804 | * Helper function for radeon_fence_driver_init(). | ||
| 805 | */ | ||
| 547 | static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) | 806 | static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) |
| 548 | { | 807 | { |
| 808 | int i; | ||
| 809 | |||
| 549 | rdev->fence_drv[ring].scratch_reg = -1; | 810 | rdev->fence_drv[ring].scratch_reg = -1; |
| 550 | rdev->fence_drv[ring].cpu_addr = NULL; | 811 | rdev->fence_drv[ring].cpu_addr = NULL; |
| 551 | rdev->fence_drv[ring].gpu_addr = 0; | 812 | rdev->fence_drv[ring].gpu_addr = 0; |
| 552 | rdev->fence_drv[ring].seq = 0; | 813 | for (i = 0; i < RADEON_NUM_RINGS; ++i) |
| 814 | rdev->fence_drv[ring].sync_seq[i] = 0; | ||
| 553 | atomic64_set(&rdev->fence_drv[ring].last_seq, 0); | 815 | atomic64_set(&rdev->fence_drv[ring].last_seq, 0); |
| 554 | rdev->fence_drv[ring].last_activity = jiffies; | 816 | rdev->fence_drv[ring].last_activity = jiffies; |
| 555 | rdev->fence_drv[ring].initialized = false; | 817 | rdev->fence_drv[ring].initialized = false; |
| 556 | } | 818 | } |
| 557 | 819 | ||
| 820 | /** | ||
| 821 | * radeon_fence_driver_init - init the fence driver | ||
| 822 | * for all possible rings. | ||
| 823 | * | ||
| 824 | * @rdev: radeon device pointer | ||
| 825 | * | ||
| 826 | * Init the fence driver for all possible rings (all asics). | ||
| 827 | * Not all asics have all rings, so each asic will only | ||
| 828 | * start the fence driver on the rings it has using | ||
| 829 | * radeon_fence_driver_start_ring(). | ||
| 830 | * Returns 0 for success. | ||
| 831 | */ | ||
| 558 | int radeon_fence_driver_init(struct radeon_device *rdev) | 832 | int radeon_fence_driver_init(struct radeon_device *rdev) |
| 559 | { | 833 | { |
| 560 | int ring; | 834 | int ring; |
| @@ -569,6 +843,14 @@ int radeon_fence_driver_init(struct radeon_device *rdev) | |||
| 569 | return 0; | 843 | return 0; |
| 570 | } | 844 | } |
| 571 | 845 | ||
| 846 | /** | ||
| 847 | * radeon_fence_driver_fini - tear down the fence driver | ||
| 848 | * for all possible rings. | ||
| 849 | * | ||
| 850 | * @rdev: radeon device pointer | ||
| 851 | * | ||
| 852 | * Tear down the fence driver for all possible rings (all asics). | ||
| 853 | */ | ||
| 572 | void radeon_fence_driver_fini(struct radeon_device *rdev) | 854 | void radeon_fence_driver_fini(struct radeon_device *rdev) |
| 573 | { | 855 | { |
| 574 | int ring; | 856 | int ring; |
| @@ -595,7 +877,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) | |||
| 595 | struct drm_info_node *node = (struct drm_info_node *)m->private; | 877 | struct drm_info_node *node = (struct drm_info_node *)m->private; |
| 596 | struct drm_device *dev = node->minor->dev; | 878 | struct drm_device *dev = node->minor->dev; |
| 597 | struct radeon_device *rdev = dev->dev_private; | 879 | struct radeon_device *rdev = dev->dev_private; |
| 598 | int i; | 880 | int i, j; |
| 599 | 881 | ||
| 600 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 882 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
| 601 | if (!rdev->fence_drv[i].initialized) | 883 | if (!rdev->fence_drv[i].initialized) |
| @@ -604,8 +886,14 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) | |||
| 604 | seq_printf(m, "--- ring %d ---\n", i); | 886 | seq_printf(m, "--- ring %d ---\n", i); |
| 605 | seq_printf(m, "Last signaled fence 0x%016llx\n", | 887 | seq_printf(m, "Last signaled fence 0x%016llx\n", |
| 606 | (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq)); | 888 | (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq)); |
| 607 | seq_printf(m, "Last emitted 0x%016llx\n", | 889 | seq_printf(m, "Last emitted 0x%016llx\n", |
| 608 | rdev->fence_drv[i].seq); | 890 | rdev->fence_drv[i].sync_seq[i]); |
| 891 | |||
| 892 | for (j = 0; j < RADEON_NUM_RINGS; ++j) { | ||
| 893 | if (i != j && rdev->fence_drv[j].initialized) | ||
| 894 | seq_printf(m, "Last sync to ring %d 0x%016llx\n", | ||
| 895 | j, rdev->fence_drv[i].sync_seq[j]); | ||
| 896 | } | ||
| 609 | } | 897 | } |
| 610 | return 0; | 898 | return 0; |
| 611 | } | 899 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 84b648a7ddd8..b3720054614d 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c | |||
| @@ -31,8 +31,38 @@ | |||
| 31 | #include "radeon_reg.h" | 31 | #include "radeon_reg.h" |
| 32 | 32 | ||
| 33 | /* | 33 | /* |
| 34 | * GART | ||
| 35 | * The GART (Graphics Aperture Remapping Table) is an aperture | ||
| 36 | * in the GPU's address space. System pages can be mapped into | ||
| 37 | * the aperture and look like contiguous pages from the GPU's | ||
| 38 | * perspective. A page table maps the pages in the aperture | ||
| 39 | * to the actual backing pages in system memory. | ||
| 40 | * | ||
| 41 | * Radeon GPUs support both an internal GART, as described above, | ||
| 42 | * and AGP. AGP works similarly, but the GART table is configured | ||
| 43 | * and maintained by the northbridge rather than the driver. | ||
| 44 | * Radeon hw has a separate AGP aperture that is programmed to | ||
| 45 | * point to the AGP aperture provided by the northbridge and the | ||
| 46 | * requests are passed through to the northbridge aperture. | ||
| 47 | * Both AGP and internal GART can be used at the same time, however | ||
| 48 | * that is not currently supported by the driver. | ||
| 49 | * | ||
| 50 | * This file handles the common internal GART management. | ||
| 51 | */ | ||
| 52 | |||
| 53 | /* | ||
| 34 | * Common GART table functions. | 54 | * Common GART table functions. |
| 35 | */ | 55 | */ |
| 56 | /** | ||
| 57 | * radeon_gart_table_ram_alloc - allocate system ram for gart page table | ||
| 58 | * | ||
| 59 | * @rdev: radeon_device pointer | ||
| 60 | * | ||
| 61 | * Allocate system memory for GART page table | ||
| 62 | * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the | ||
| 63 | * gart table to be in system memory. | ||
| 64 | * Returns 0 for success, -ENOMEM for failure. | ||
| 65 | */ | ||
| 36 | int radeon_gart_table_ram_alloc(struct radeon_device *rdev) | 66 | int radeon_gart_table_ram_alloc(struct radeon_device *rdev) |
| 37 | { | 67 | { |
| 38 | void *ptr; | 68 | void *ptr; |
| @@ -54,6 +84,15 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev) | |||
| 54 | return 0; | 84 | return 0; |
| 55 | } | 85 | } |
| 56 | 86 | ||
| 87 | /** | ||
| 88 | * radeon_gart_table_ram_free - free system ram for gart page table | ||
| 89 | * | ||
| 90 | * @rdev: radeon_device pointer | ||
| 91 | * | ||
| 92 | * Free system memory for GART page table | ||
| 93 | * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the | ||
| 94 | * gart table to be in system memory. | ||
| 95 | */ | ||
| 57 | void radeon_gart_table_ram_free(struct radeon_device *rdev) | 96 | void radeon_gart_table_ram_free(struct radeon_device *rdev) |
| 58 | { | 97 | { |
| 59 | if (rdev->gart.ptr == NULL) { | 98 | if (rdev->gart.ptr == NULL) { |
| @@ -73,6 +112,16 @@ void radeon_gart_table_ram_free(struct radeon_device *rdev) | |||
| 73 | rdev->gart.table_addr = 0; | 112 | rdev->gart.table_addr = 0; |
| 74 | } | 113 | } |
| 75 | 114 | ||
| 115 | /** | ||
| 116 | * radeon_gart_table_vram_alloc - allocate vram for gart page table | ||
| 117 | * | ||
| 118 | * @rdev: radeon_device pointer | ||
| 119 | * | ||
| 120 | * Allocate video memory for GART page table | ||
| 121 | * (pcie r4xx, r5xx+). These asics require the | ||
| 122 | * gart table to be in video memory. | ||
| 123 | * Returns 0 for success, error for failure. | ||
| 124 | */ | ||
| 76 | int radeon_gart_table_vram_alloc(struct radeon_device *rdev) | 125 | int radeon_gart_table_vram_alloc(struct radeon_device *rdev) |
| 77 | { | 126 | { |
| 78 | int r; | 127 | int r; |
| @@ -88,6 +137,16 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev) | |||
| 88 | return 0; | 137 | return 0; |
| 89 | } | 138 | } |
| 90 | 139 | ||
| 140 | /** | ||
| 141 | * radeon_gart_table_vram_pin - pin gart page table in vram | ||
| 142 | * | ||
| 143 | * @rdev: radeon_device pointer | ||
| 144 | * | ||
| 145 | * Pin the GART page table in vram so it will not be moved | ||
| 146 | * by the memory manager (pcie r4xx, r5xx+). These asics require the | ||
| 147 | * gart table to be in video memory. | ||
| 148 | * Returns 0 for success, error for failure. | ||
| 149 | */ | ||
| 91 | int radeon_gart_table_vram_pin(struct radeon_device *rdev) | 150 | int radeon_gart_table_vram_pin(struct radeon_device *rdev) |
| 92 | { | 151 | { |
| 93 | uint64_t gpu_addr; | 152 | uint64_t gpu_addr; |
| @@ -110,6 +169,14 @@ int radeon_gart_table_vram_pin(struct radeon_device *rdev) | |||
| 110 | return r; | 169 | return r; |
| 111 | } | 170 | } |
| 112 | 171 | ||
| 172 | /** | ||
| 173 | * radeon_gart_table_vram_unpin - unpin gart page table in vram | ||
| 174 | * | ||
| 175 | * @rdev: radeon_device pointer | ||
| 176 | * | ||
| 177 | * Unpin the GART page table in vram (pcie r4xx, r5xx+). | ||
| 178 | * These asics require the gart table to be in video memory. | ||
| 179 | */ | ||
| 113 | void radeon_gart_table_vram_unpin(struct radeon_device *rdev) | 180 | void radeon_gart_table_vram_unpin(struct radeon_device *rdev) |
| 114 | { | 181 | { |
| 115 | int r; | 182 | int r; |
| @@ -126,6 +193,15 @@ void radeon_gart_table_vram_unpin(struct radeon_device *rdev) | |||
| 126 | } | 193 | } |
| 127 | } | 194 | } |
| 128 | 195 | ||
| 196 | /** | ||
| 197 | * radeon_gart_table_vram_free - free gart page table vram | ||
| 198 | * | ||
| 199 | * @rdev: radeon_device pointer | ||
| 200 | * | ||
| 201 | * Free the video memory used for the GART page table | ||
| 202 | * (pcie r4xx, r5xx+). These asics require the gart table to | ||
| 203 | * be in video memory. | ||
| 204 | */ | ||
| 129 | void radeon_gart_table_vram_free(struct radeon_device *rdev) | 205 | void radeon_gart_table_vram_free(struct radeon_device *rdev) |
| 130 | { | 206 | { |
| 131 | if (rdev->gart.robj == NULL) { | 207 | if (rdev->gart.robj == NULL) { |
| @@ -135,12 +211,19 @@ void radeon_gart_table_vram_free(struct radeon_device *rdev) | |||
| 135 | radeon_bo_unref(&rdev->gart.robj); | 211 | radeon_bo_unref(&rdev->gart.robj); |
| 136 | } | 212 | } |
| 137 | 213 | ||
| 138 | |||
| 139 | |||
| 140 | |||
| 141 | /* | 214 | /* |
| 142 | * Common gart functions. | 215 | * Common gart functions. |
| 143 | */ | 216 | */ |
| 217 | /** | ||
| 218 | * radeon_gart_unbind - unbind pages from the gart page table | ||
| 219 | * | ||
| 220 | * @rdev: radeon_device pointer | ||
| 221 | * @offset: offset into the GPU's gart aperture | ||
| 222 | * @pages: number of pages to unbind | ||
| 223 | * | ||
| 224 | * Unbinds the requested pages from the gart page table and | ||
| 225 | * replaces them with the dummy page (all asics). | ||
| 226 | */ | ||
| 144 | void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | 227 | void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, |
| 145 | int pages) | 228 | int pages) |
| 146 | { | 229 | { |
| @@ -172,6 +255,19 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | |||
| 172 | radeon_gart_tlb_flush(rdev); | 255 | radeon_gart_tlb_flush(rdev); |
| 173 | } | 256 | } |
| 174 | 257 | ||
| 258 | /** | ||
| 259 | * radeon_gart_bind - bind pages into the gart page table | ||
| 260 | * | ||
| 261 | * @rdev: radeon_device pointer | ||
| 262 | * @offset: offset into the GPU's gart aperture | ||
| 263 | * @pages: number of pages to bind | ||
| 264 | * @pagelist: pages to bind | ||
| 265 | * @dma_addr: DMA addresses of pages | ||
| 266 | * | ||
| 267 | * Binds the requested pages to the gart page table | ||
| 268 | * (all asics). | ||
| 269 | * Returns 0 for success, -EINVAL for failure. | ||
| 270 | */ | ||
| 175 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | 271 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, |
| 176 | int pages, struct page **pagelist, dma_addr_t *dma_addr) | 272 | int pages, struct page **pagelist, dma_addr_t *dma_addr) |
| 177 | { | 273 | { |
| @@ -203,6 +299,14 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | |||
| 203 | return 0; | 299 | return 0; |
| 204 | } | 300 | } |
| 205 | 301 | ||
| 302 | /** | ||
| 303 | * radeon_gart_restore - bind all pages in the gart page table | ||
| 304 | * | ||
| 305 | * @rdev: radeon_device pointer | ||
| 306 | * | ||
| 307 | * Binds all pages in the gart page table (all asics). | ||
| 308 | * Used to rebuild the gart table on device startup or resume. | ||
| 309 | */ | ||
| 206 | void radeon_gart_restore(struct radeon_device *rdev) | 310 | void radeon_gart_restore(struct radeon_device *rdev) |
| 207 | { | 311 | { |
| 208 | int i, j, t; | 312 | int i, j, t; |
| @@ -222,6 +326,14 @@ void radeon_gart_restore(struct radeon_device *rdev) | |||
| 222 | radeon_gart_tlb_flush(rdev); | 326 | radeon_gart_tlb_flush(rdev); |
| 223 | } | 327 | } |
| 224 | 328 | ||
| 329 | /** | ||
| 330 | * radeon_gart_init - init the driver info for managing the gart | ||
| 331 | * | ||
| 332 | * @rdev: radeon_device pointer | ||
| 333 | * | ||
| 334 | * Allocate the dummy page and init the gart driver info (all asics). | ||
| 335 | * Returns 0 for success, error for failure. | ||
| 336 | */ | ||
| 225 | int radeon_gart_init(struct radeon_device *rdev) | 337 | int radeon_gart_init(struct radeon_device *rdev) |
| 226 | { | 338 | { |
| 227 | int r, i; | 339 | int r, i; |
| @@ -262,6 +374,13 @@ int radeon_gart_init(struct radeon_device *rdev) | |||
| 262 | return 0; | 374 | return 0; |
| 263 | } | 375 | } |
| 264 | 376 | ||
| 377 | /** | ||
| 378 | * radeon_gart_fini - tear down the driver info for managing the gart | ||
| 379 | * | ||
| 380 | * @rdev: radeon_device pointer | ||
| 381 | * | ||
| 382 | * Tear down the gart driver info and free the dummy page (all asics). | ||
| 383 | */ | ||
| 265 | void radeon_gart_fini(struct radeon_device *rdev) | 384 | void radeon_gart_fini(struct radeon_device *rdev) |
| 266 | { | 385 | { |
| 267 | if (rdev->gart.pages && rdev->gart.pages_addr && rdev->gart.ready) { | 386 | if (rdev->gart.pages && rdev->gart.pages_addr && rdev->gart.ready) { |
| @@ -278,35 +397,104 @@ void radeon_gart_fini(struct radeon_device *rdev) | |||
| 278 | } | 397 | } |
| 279 | 398 | ||
| 280 | /* | 399 | /* |
| 400 | * GPUVM | ||
| 401 | * GPUVM is similar to the legacy gart on older asics, however | ||
| 402 | * rather than there being a single global gart table | ||
| 403 | * for the entire GPU, there are multiple VM page tables active | ||
| 404 | * at any given time. The VM page tables can contain a mix | ||
| 405 | * vram pages and system memory pages and system memory pages | ||
| 406 | * can be mapped as snooped (cached system pages) or unsnooped | ||
| 407 | * (uncached system pages). | ||
| 408 | * Each VM has an ID associated with it and there is a page table | ||
| 409 | * associated with each VMID. When execting a command buffer, | ||
| 410 | * the kernel tells the the ring what VMID to use for that command | ||
| 411 | * buffer. VMIDs are allocated dynamically as commands are submitted. | ||
| 412 | * The userspace drivers maintain their own address space and the kernel | ||
| 413 | * sets up their pages tables accordingly when they submit their | ||
| 414 | * command buffers and a VMID is assigned. | ||
| 415 | * Cayman/Trinity support up to 8 active VMs at any given time; | ||
| 416 | * SI supports 16. | ||
| 417 | */ | ||
| 418 | |||
| 419 | /* | ||
| 281 | * vm helpers | 420 | * vm helpers |
| 282 | * | 421 | * |
| 283 | * TODO bind a default page at vm initialization for default address | 422 | * TODO bind a default page at vm initialization for default address |
| 284 | */ | 423 | */ |
| 424 | |||
| 425 | /** | ||
| 426 | * radeon_vm_manager_init - init the vm manager | ||
| 427 | * | ||
| 428 | * @rdev: radeon_device pointer | ||
| 429 | * | ||
| 430 | * Init the vm manager (cayman+). | ||
| 431 | * Returns 0 for success, error for failure. | ||
| 432 | */ | ||
| 285 | int radeon_vm_manager_init(struct radeon_device *rdev) | 433 | int radeon_vm_manager_init(struct radeon_device *rdev) |
| 286 | { | 434 | { |
| 435 | struct radeon_vm *vm; | ||
| 436 | struct radeon_bo_va *bo_va; | ||
| 287 | int r; | 437 | int r; |
| 288 | 438 | ||
| 289 | rdev->vm_manager.enabled = false; | 439 | if (!rdev->vm_manager.enabled) { |
| 440 | /* mark first vm as always in use, it's the system one */ | ||
| 441 | /* allocate enough for 2 full VM pts */ | ||
| 442 | r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, | ||
| 443 | rdev->vm_manager.max_pfn * 8 * 2, | ||
| 444 | RADEON_GEM_DOMAIN_VRAM); | ||
| 445 | if (r) { | ||
| 446 | dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", | ||
| 447 | (rdev->vm_manager.max_pfn * 8) >> 10); | ||
| 448 | return r; | ||
| 449 | } | ||
| 290 | 450 | ||
| 291 | /* mark first vm as always in use, it's the system one */ | 451 | r = rdev->vm_manager.funcs->init(rdev); |
| 292 | /* allocate enough for 2 full VM pts */ | 452 | if (r) |
| 293 | r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, | 453 | return r; |
| 294 | rdev->vm_manager.max_pfn * 8 * 2, | 454 | |
| 295 | RADEON_GEM_DOMAIN_VRAM); | 455 | rdev->vm_manager.enabled = true; |
| 296 | if (r) { | 456 | |
| 297 | dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", | 457 | r = radeon_sa_bo_manager_start(rdev, &rdev->vm_manager.sa_manager); |
| 298 | (rdev->vm_manager.max_pfn * 8) >> 10); | 458 | if (r) |
| 299 | return r; | 459 | return r; |
| 300 | } | 460 | } |
| 301 | 461 | ||
| 302 | r = rdev->vm_manager.funcs->init(rdev); | 462 | /* restore page table */ |
| 303 | if (r == 0) | 463 | list_for_each_entry(vm, &rdev->vm_manager.lru_vm, list) { |
| 304 | rdev->vm_manager.enabled = true; | 464 | if (vm->id == -1) |
| 465 | continue; | ||
| 305 | 466 | ||
| 306 | return r; | 467 | list_for_each_entry(bo_va, &vm->va, vm_list) { |
| 468 | struct ttm_mem_reg *mem = NULL; | ||
| 469 | if (bo_va->valid) | ||
| 470 | mem = &bo_va->bo->tbo.mem; | ||
| 471 | |||
| 472 | bo_va->valid = false; | ||
| 473 | r = radeon_vm_bo_update_pte(rdev, vm, bo_va->bo, mem); | ||
| 474 | if (r) { | ||
| 475 | DRM_ERROR("Failed to update pte for vm %d!\n", vm->id); | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 479 | r = rdev->vm_manager.funcs->bind(rdev, vm, vm->id); | ||
| 480 | if (r) { | ||
| 481 | DRM_ERROR("Failed to bind vm %d!\n", vm->id); | ||
| 482 | } | ||
| 483 | } | ||
| 484 | return 0; | ||
| 307 | } | 485 | } |
| 308 | 486 | ||
| 309 | /* cs mutex must be lock */ | 487 | /* global mutex must be lock */ |
| 488 | /** | ||
| 489 | * radeon_vm_unbind_locked - unbind a specific vm | ||
| 490 | * | ||
| 491 | * @rdev: radeon_device pointer | ||
| 492 | * @vm: vm to unbind | ||
| 493 | * | ||
| 494 | * Unbind the requested vm (cayman+). | ||
| 495 | * Wait for use of the VM to finish, then unbind the page table, | ||
| 496 | * and free the page table memory. | ||
| 497 | */ | ||
| 310 | static void radeon_vm_unbind_locked(struct radeon_device *rdev, | 498 | static void radeon_vm_unbind_locked(struct radeon_device *rdev, |
| 311 | struct radeon_vm *vm) | 499 | struct radeon_vm *vm) |
| 312 | { | 500 | { |
| @@ -317,10 +505,21 @@ static void radeon_vm_unbind_locked(struct radeon_device *rdev, | |||
| 317 | } | 505 | } |
| 318 | 506 | ||
| 319 | /* wait for vm use to end */ | 507 | /* wait for vm use to end */ |
| 320 | if (vm->fence) { | 508 | while (vm->fence) { |
| 321 | radeon_fence_wait(vm->fence, false); | 509 | int r; |
| 322 | radeon_fence_unref(&vm->fence); | 510 | r = radeon_fence_wait(vm->fence, false); |
| 511 | if (r) | ||
| 512 | DRM_ERROR("error while waiting for fence: %d\n", r); | ||
| 513 | if (r == -EDEADLK) { | ||
| 514 | mutex_unlock(&rdev->vm_manager.lock); | ||
| 515 | r = radeon_gpu_reset(rdev); | ||
| 516 | mutex_lock(&rdev->vm_manager.lock); | ||
| 517 | if (!r) | ||
| 518 | continue; | ||
| 519 | } | ||
| 520 | break; | ||
| 323 | } | 521 | } |
| 522 | radeon_fence_unref(&vm->fence); | ||
| 324 | 523 | ||
| 325 | /* hw unbind */ | 524 | /* hw unbind */ |
| 326 | rdev->vm_manager.funcs->unbind(rdev, vm); | 525 | rdev->vm_manager.funcs->unbind(rdev, vm); |
| @@ -335,39 +534,42 @@ static void radeon_vm_unbind_locked(struct radeon_device *rdev, | |||
| 335 | } | 534 | } |
| 336 | } | 535 | } |
| 337 | 536 | ||
| 537 | /** | ||
| 538 | * radeon_vm_manager_fini - tear down the vm manager | ||
| 539 | * | ||
| 540 | * @rdev: radeon_device pointer | ||
| 541 | * | ||
| 542 | * Tear down the VM manager (cayman+). | ||
| 543 | */ | ||
| 338 | void radeon_vm_manager_fini(struct radeon_device *rdev) | 544 | void radeon_vm_manager_fini(struct radeon_device *rdev) |
| 339 | { | 545 | { |
| 340 | if (rdev->vm_manager.sa_manager.bo == NULL) | ||
| 341 | return; | ||
| 342 | radeon_vm_manager_suspend(rdev); | ||
| 343 | rdev->vm_manager.funcs->fini(rdev); | ||
| 344 | radeon_sa_bo_manager_fini(rdev, &rdev->vm_manager.sa_manager); | ||
| 345 | rdev->vm_manager.enabled = false; | ||
| 346 | } | ||
| 347 | |||
| 348 | int radeon_vm_manager_start(struct radeon_device *rdev) | ||
| 349 | { | ||
| 350 | if (rdev->vm_manager.sa_manager.bo == NULL) { | ||
| 351 | return -EINVAL; | ||
| 352 | } | ||
| 353 | return radeon_sa_bo_manager_start(rdev, &rdev->vm_manager.sa_manager); | ||
| 354 | } | ||
| 355 | |||
| 356 | int radeon_vm_manager_suspend(struct radeon_device *rdev) | ||
| 357 | { | ||
| 358 | struct radeon_vm *vm, *tmp; | 546 | struct radeon_vm *vm, *tmp; |
| 359 | 547 | ||
| 360 | radeon_mutex_lock(&rdev->cs_mutex); | 548 | if (!rdev->vm_manager.enabled) |
| 549 | return; | ||
| 550 | |||
| 551 | mutex_lock(&rdev->vm_manager.lock); | ||
| 361 | /* unbind all active vm */ | 552 | /* unbind all active vm */ |
| 362 | list_for_each_entry_safe(vm, tmp, &rdev->vm_manager.lru_vm, list) { | 553 | list_for_each_entry_safe(vm, tmp, &rdev->vm_manager.lru_vm, list) { |
| 363 | radeon_vm_unbind_locked(rdev, vm); | 554 | radeon_vm_unbind_locked(rdev, vm); |
| 364 | } | 555 | } |
| 365 | rdev->vm_manager.funcs->fini(rdev); | 556 | rdev->vm_manager.funcs->fini(rdev); |
| 366 | radeon_mutex_unlock(&rdev->cs_mutex); | 557 | mutex_unlock(&rdev->vm_manager.lock); |
| 367 | return radeon_sa_bo_manager_suspend(rdev, &rdev->vm_manager.sa_manager); | 558 | |
| 559 | radeon_sa_bo_manager_suspend(rdev, &rdev->vm_manager.sa_manager); | ||
| 560 | radeon_sa_bo_manager_fini(rdev, &rdev->vm_manager.sa_manager); | ||
| 561 | rdev->vm_manager.enabled = false; | ||
| 368 | } | 562 | } |
| 369 | 563 | ||
| 370 | /* cs mutex must be lock */ | 564 | /* global mutex must be locked */ |
| 565 | /** | ||
| 566 | * radeon_vm_unbind - locked version of unbind | ||
| 567 | * | ||
| 568 | * @rdev: radeon_device pointer | ||
| 569 | * @vm: vm to unbind | ||
| 570 | * | ||
| 571 | * Locked version that wraps radeon_vm_unbind_locked (cayman+). | ||
| 572 | */ | ||
| 371 | void radeon_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) | 573 | void radeon_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) |
| 372 | { | 574 | { |
| 373 | mutex_lock(&vm->mutex); | 575 | mutex_lock(&vm->mutex); |
| @@ -375,7 +577,19 @@ void radeon_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) | |||
| 375 | mutex_unlock(&vm->mutex); | 577 | mutex_unlock(&vm->mutex); |
| 376 | } | 578 | } |
| 377 | 579 | ||
| 378 | /* cs mutex must be lock & vm mutex must be lock */ | 580 | /* global and local mutex must be locked */ |
| 581 | /** | ||
| 582 | * radeon_vm_bind - bind a page table to a VMID | ||
| 583 | * | ||
| 584 | * @rdev: radeon_device pointer | ||
| 585 | * @vm: vm to bind | ||
| 586 | * | ||
| 587 | * Bind the requested vm (cayman+). | ||
| 588 | * Suballocate memory for the page table, allocate a VMID | ||
| 589 | * and bind the page table to it, and finally start to populate | ||
| 590 | * the page table. | ||
| 591 | * Returns 0 for success, error for failure. | ||
| 592 | */ | ||
| 379 | int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm) | 593 | int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm) |
| 380 | { | 594 | { |
| 381 | struct radeon_vm *vm_evict; | 595 | struct radeon_vm *vm_evict; |
| @@ -438,6 +652,20 @@ retry_id: | |||
| 438 | } | 652 | } |
| 439 | 653 | ||
| 440 | /* object have to be reserved */ | 654 | /* object have to be reserved */ |
| 655 | /** | ||
| 656 | * radeon_vm_bo_add - add a bo to a specific vm | ||
| 657 | * | ||
| 658 | * @rdev: radeon_device pointer | ||
| 659 | * @vm: requested vm | ||
| 660 | * @bo: radeon buffer object | ||
| 661 | * @offset: requested offset of the buffer in the VM address space | ||
| 662 | * @flags: attributes of pages (read/write/valid/etc.) | ||
| 663 | * | ||
| 664 | * Add @bo into the requested vm (cayman+). | ||
| 665 | * Add @bo to the list of bos associated with the vm and validate | ||
| 666 | * the offset requested within the vm address space. | ||
| 667 | * Returns 0 for success, error for failure. | ||
| 668 | */ | ||
| 441 | int radeon_vm_bo_add(struct radeon_device *rdev, | 669 | int radeon_vm_bo_add(struct radeon_device *rdev, |
| 442 | struct radeon_vm *vm, | 670 | struct radeon_vm *vm, |
| 443 | struct radeon_bo *bo, | 671 | struct radeon_bo *bo, |
| @@ -479,7 +707,7 @@ int radeon_vm_bo_add(struct radeon_device *rdev, | |||
| 479 | if (last_pfn > vm->last_pfn) { | 707 | if (last_pfn > vm->last_pfn) { |
| 480 | /* release mutex and lock in right order */ | 708 | /* release mutex and lock in right order */ |
| 481 | mutex_unlock(&vm->mutex); | 709 | mutex_unlock(&vm->mutex); |
| 482 | radeon_mutex_lock(&rdev->cs_mutex); | 710 | mutex_lock(&rdev->vm_manager.lock); |
| 483 | mutex_lock(&vm->mutex); | 711 | mutex_lock(&vm->mutex); |
| 484 | /* and check again */ | 712 | /* and check again */ |
| 485 | if (last_pfn > vm->last_pfn) { | 713 | if (last_pfn > vm->last_pfn) { |
| @@ -488,7 +716,7 @@ int radeon_vm_bo_add(struct radeon_device *rdev, | |||
| 488 | radeon_vm_unbind_locked(rdev, vm); | 716 | radeon_vm_unbind_locked(rdev, vm); |
| 489 | vm->last_pfn = (last_pfn + align) & ~align; | 717 | vm->last_pfn = (last_pfn + align) & ~align; |
| 490 | } | 718 | } |
| 491 | radeon_mutex_unlock(&rdev->cs_mutex); | 719 | mutex_unlock(&rdev->vm_manager.lock); |
| 492 | } | 720 | } |
| 493 | head = &vm->va; | 721 | head = &vm->va; |
| 494 | last_offset = 0; | 722 | last_offset = 0; |
| @@ -515,6 +743,17 @@ int radeon_vm_bo_add(struct radeon_device *rdev, | |||
| 515 | return 0; | 743 | return 0; |
| 516 | } | 744 | } |
| 517 | 745 | ||
| 746 | /** | ||
| 747 | * radeon_vm_get_addr - get the physical address of the page | ||
| 748 | * | ||
| 749 | * @rdev: radeon_device pointer | ||
| 750 | * @mem: ttm mem | ||
| 751 | * @pfn: pfn | ||
| 752 | * | ||
| 753 | * Look up the physical address of the page that the pte resolves | ||
| 754 | * to (cayman+). | ||
| 755 | * Returns the physical address of the page. | ||
| 756 | */ | ||
| 518 | static u64 radeon_vm_get_addr(struct radeon_device *rdev, | 757 | static u64 radeon_vm_get_addr(struct radeon_device *rdev, |
| 519 | struct ttm_mem_reg *mem, | 758 | struct ttm_mem_reg *mem, |
| 520 | unsigned pfn) | 759 | unsigned pfn) |
| @@ -543,7 +782,18 @@ static u64 radeon_vm_get_addr(struct radeon_device *rdev, | |||
| 543 | return addr; | 782 | return addr; |
| 544 | } | 783 | } |
| 545 | 784 | ||
| 546 | /* object have to be reserved & cs mutex took & vm mutex took */ | 785 | /* object have to be reserved & global and local mutex must be locked */ |
| 786 | /** | ||
| 787 | * radeon_vm_bo_update_pte - map a bo into the vm page table | ||
| 788 | * | ||
| 789 | * @rdev: radeon_device pointer | ||
| 790 | * @vm: requested vm | ||
| 791 | * @bo: radeon buffer object | ||
| 792 | * @mem: ttm mem | ||
| 793 | * | ||
| 794 | * Fill in the page table entries for @bo (cayman+). | ||
| 795 | * Returns 0 for success, -EINVAL for failure. | ||
| 796 | */ | ||
| 547 | int radeon_vm_bo_update_pte(struct radeon_device *rdev, | 797 | int radeon_vm_bo_update_pte(struct radeon_device *rdev, |
| 548 | struct radeon_vm *vm, | 798 | struct radeon_vm *vm, |
| 549 | struct radeon_bo *bo, | 799 | struct radeon_bo *bo, |
| @@ -592,6 +842,18 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, | |||
| 592 | } | 842 | } |
| 593 | 843 | ||
| 594 | /* object have to be reserved */ | 844 | /* object have to be reserved */ |
| 845 | /** | ||
| 846 | * radeon_vm_bo_rmv - remove a bo to a specific vm | ||
| 847 | * | ||
| 848 | * @rdev: radeon_device pointer | ||
| 849 | * @vm: requested vm | ||
| 850 | * @bo: radeon buffer object | ||
| 851 | * | ||
| 852 | * Remove @bo from the requested vm (cayman+). | ||
| 853 | * Remove @bo from the list of bos associated with the vm and | ||
| 854 | * remove the ptes for @bo in the page table. | ||
| 855 | * Returns 0 for success. | ||
| 856 | */ | ||
| 595 | int radeon_vm_bo_rmv(struct radeon_device *rdev, | 857 | int radeon_vm_bo_rmv(struct radeon_device *rdev, |
| 596 | struct radeon_vm *vm, | 858 | struct radeon_vm *vm, |
| 597 | struct radeon_bo *bo) | 859 | struct radeon_bo *bo) |
| @@ -602,10 +864,10 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, | |||
| 602 | if (bo_va == NULL) | 864 | if (bo_va == NULL) |
| 603 | return 0; | 865 | return 0; |
| 604 | 866 | ||
| 605 | radeon_mutex_lock(&rdev->cs_mutex); | 867 | mutex_lock(&rdev->vm_manager.lock); |
| 606 | mutex_lock(&vm->mutex); | 868 | mutex_lock(&vm->mutex); |
| 607 | radeon_vm_bo_update_pte(rdev, vm, bo, NULL); | 869 | radeon_vm_bo_update_pte(rdev, vm, bo, NULL); |
| 608 | radeon_mutex_unlock(&rdev->cs_mutex); | 870 | mutex_unlock(&rdev->vm_manager.lock); |
| 609 | list_del(&bo_va->vm_list); | 871 | list_del(&bo_va->vm_list); |
| 610 | mutex_unlock(&vm->mutex); | 872 | mutex_unlock(&vm->mutex); |
| 611 | list_del(&bo_va->bo_list); | 873 | list_del(&bo_va->bo_list); |
| @@ -614,6 +876,15 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, | |||
| 614 | return 0; | 876 | return 0; |
| 615 | } | 877 | } |
| 616 | 878 | ||
| 879 | /** | ||
| 880 | * radeon_vm_bo_invalidate - mark the bo as invalid | ||
| 881 | * | ||
| 882 | * @rdev: radeon_device pointer | ||
| 883 | * @vm: requested vm | ||
| 884 | * @bo: radeon buffer object | ||
| 885 | * | ||
| 886 | * Mark @bo as invalid (cayman+). | ||
| 887 | */ | ||
| 617 | void radeon_vm_bo_invalidate(struct radeon_device *rdev, | 888 | void radeon_vm_bo_invalidate(struct radeon_device *rdev, |
| 618 | struct radeon_bo *bo) | 889 | struct radeon_bo *bo) |
| 619 | { | 890 | { |
| @@ -625,6 +896,17 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev, | |||
| 625 | } | 896 | } |
| 626 | } | 897 | } |
| 627 | 898 | ||
| 899 | /** | ||
| 900 | * radeon_vm_init - initialize a vm instance | ||
| 901 | * | ||
| 902 | * @rdev: radeon_device pointer | ||
| 903 | * @vm: requested vm | ||
| 904 | * | ||
| 905 | * Init @vm (cayman+). | ||
| 906 | * Map the IB pool and any other shared objects into the VM | ||
| 907 | * by default as it's used by all VMs. | ||
| 908 | * Returns 0 for success, error for failure. | ||
| 909 | */ | ||
| 628 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) | 910 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) |
| 629 | { | 911 | { |
| 630 | int r; | 912 | int r; |
| @@ -651,15 +933,24 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) | |||
| 651 | return r; | 933 | return r; |
| 652 | } | 934 | } |
| 653 | 935 | ||
| 936 | /** | ||
| 937 | * radeon_vm_init - tear down a vm instance | ||
| 938 | * | ||
| 939 | * @rdev: radeon_device pointer | ||
| 940 | * @vm: requested vm | ||
| 941 | * | ||
| 942 | * Tear down @vm (cayman+). | ||
| 943 | * Unbind the VM and remove all bos from the vm bo list | ||
| 944 | */ | ||
| 654 | void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) | 945 | void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) |
| 655 | { | 946 | { |
| 656 | struct radeon_bo_va *bo_va, *tmp; | 947 | struct radeon_bo_va *bo_va, *tmp; |
| 657 | int r; | 948 | int r; |
| 658 | 949 | ||
| 659 | radeon_mutex_lock(&rdev->cs_mutex); | 950 | mutex_lock(&rdev->vm_manager.lock); |
| 660 | mutex_lock(&vm->mutex); | 951 | mutex_lock(&vm->mutex); |
| 661 | radeon_vm_unbind_locked(rdev, vm); | 952 | radeon_vm_unbind_locked(rdev, vm); |
| 662 | radeon_mutex_unlock(&rdev->cs_mutex); | 953 | mutex_unlock(&rdev->vm_manager.lock); |
| 663 | 954 | ||
| 664 | /* remove all bo */ | 955 | /* remove all bo */ |
| 665 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); | 956 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 21ec9f5653ce..84d045245739 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
| @@ -159,11 +159,9 @@ void radeon_gem_object_close(struct drm_gem_object *obj, | |||
| 159 | static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) | 159 | static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) |
| 160 | { | 160 | { |
| 161 | if (r == -EDEADLK) { | 161 | if (r == -EDEADLK) { |
| 162 | radeon_mutex_lock(&rdev->cs_mutex); | ||
| 163 | r = radeon_gpu_reset(rdev); | 162 | r = radeon_gpu_reset(rdev); |
| 164 | if (!r) | 163 | if (!r) |
| 165 | r = -EAGAIN; | 164 | r = -EAGAIN; |
| 166 | radeon_mutex_unlock(&rdev->cs_mutex); | ||
| 167 | } | 165 | } |
| 168 | return r; | 166 | return r; |
| 169 | } | 167 | } |
| @@ -217,12 +215,14 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, | |||
| 217 | uint32_t handle; | 215 | uint32_t handle; |
| 218 | int r; | 216 | int r; |
| 219 | 217 | ||
| 218 | down_read(&rdev->exclusive_lock); | ||
| 220 | /* create a gem object to contain this object in */ | 219 | /* create a gem object to contain this object in */ |
| 221 | args->size = roundup(args->size, PAGE_SIZE); | 220 | args->size = roundup(args->size, PAGE_SIZE); |
| 222 | r = radeon_gem_object_create(rdev, args->size, args->alignment, | 221 | r = radeon_gem_object_create(rdev, args->size, args->alignment, |
| 223 | args->initial_domain, false, | 222 | args->initial_domain, false, |
| 224 | false, &gobj); | 223 | false, &gobj); |
| 225 | if (r) { | 224 | if (r) { |
| 225 | up_read(&rdev->exclusive_lock); | ||
| 226 | r = radeon_gem_handle_lockup(rdev, r); | 226 | r = radeon_gem_handle_lockup(rdev, r); |
| 227 | return r; | 227 | return r; |
| 228 | } | 228 | } |
| @@ -230,10 +230,12 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, | |||
| 230 | /* drop reference from allocate - handle holds it now */ | 230 | /* drop reference from allocate - handle holds it now */ |
| 231 | drm_gem_object_unreference_unlocked(gobj); | 231 | drm_gem_object_unreference_unlocked(gobj); |
| 232 | if (r) { | 232 | if (r) { |
| 233 | up_read(&rdev->exclusive_lock); | ||
| 233 | r = radeon_gem_handle_lockup(rdev, r); | 234 | r = radeon_gem_handle_lockup(rdev, r); |
| 234 | return r; | 235 | return r; |
| 235 | } | 236 | } |
| 236 | args->handle = handle; | 237 | args->handle = handle; |
| 238 | up_read(&rdev->exclusive_lock); | ||
| 237 | return 0; | 239 | return 0; |
| 238 | } | 240 | } |
| 239 | 241 | ||
| @@ -242,6 +244,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
| 242 | { | 244 | { |
| 243 | /* transition the BO to a domain - | 245 | /* transition the BO to a domain - |
| 244 | * just validate the BO into a certain domain */ | 246 | * just validate the BO into a certain domain */ |
| 247 | struct radeon_device *rdev = dev->dev_private; | ||
| 245 | struct drm_radeon_gem_set_domain *args = data; | 248 | struct drm_radeon_gem_set_domain *args = data; |
| 246 | struct drm_gem_object *gobj; | 249 | struct drm_gem_object *gobj; |
| 247 | struct radeon_bo *robj; | 250 | struct radeon_bo *robj; |
| @@ -249,10 +252,12 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
| 249 | 252 | ||
| 250 | /* for now if someone requests domain CPU - | 253 | /* for now if someone requests domain CPU - |
| 251 | * just make sure the buffer is finished with */ | 254 | * just make sure the buffer is finished with */ |
| 255 | down_read(&rdev->exclusive_lock); | ||
| 252 | 256 | ||
| 253 | /* just do a BO wait for now */ | 257 | /* just do a BO wait for now */ |
| 254 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 258 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
| 255 | if (gobj == NULL) { | 259 | if (gobj == NULL) { |
| 260 | up_read(&rdev->exclusive_lock); | ||
| 256 | return -ENOENT; | 261 | return -ENOENT; |
| 257 | } | 262 | } |
| 258 | robj = gem_to_radeon_bo(gobj); | 263 | robj = gem_to_radeon_bo(gobj); |
| @@ -260,6 +265,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
| 260 | r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); | 265 | r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); |
| 261 | 266 | ||
| 262 | drm_gem_object_unreference_unlocked(gobj); | 267 | drm_gem_object_unreference_unlocked(gobj); |
| 268 | up_read(&rdev->exclusive_lock); | ||
| 263 | r = radeon_gem_handle_lockup(robj->rdev, r); | 269 | r = radeon_gem_handle_lockup(robj->rdev, r); |
| 264 | return r; | 270 | return r; |
| 265 | } | 271 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 5df58d1aba06..afaa1727abd2 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |||
| @@ -32,6 +32,17 @@ | |||
| 32 | #include "radeon.h" | 32 | #include "radeon.h" |
| 33 | #include "atom.h" | 33 | #include "atom.h" |
| 34 | 34 | ||
| 35 | #define RADEON_WAIT_IDLE_TIMEOUT 200 | ||
| 36 | |||
| 37 | /** | ||
| 38 | * radeon_driver_irq_handler_kms - irq handler for KMS | ||
| 39 | * | ||
| 40 | * @DRM_IRQ_ARGS: args | ||
| 41 | * | ||
| 42 | * This is the irq handler for the radeon KMS driver (all asics). | ||
| 43 | * radeon_irq_process is a macro that points to the per-asic | ||
| 44 | * irq handler callback. | ||
| 45 | */ | ||
| 35 | irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) | 46 | irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) |
| 36 | { | 47 | { |
| 37 | struct drm_device *dev = (struct drm_device *) arg; | 48 | struct drm_device *dev = (struct drm_device *) arg; |
| @@ -43,6 +54,17 @@ irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) | |||
| 43 | /* | 54 | /* |
| 44 | * Handle hotplug events outside the interrupt handler proper. | 55 | * Handle hotplug events outside the interrupt handler proper. |
| 45 | */ | 56 | */ |
| 57 | /** | ||
| 58 | * radeon_hotplug_work_func - display hotplug work handler | ||
| 59 | * | ||
| 60 | * @work: work struct | ||
| 61 | * | ||
| 62 | * This is the hot plug event work handler (all asics). | ||
| 63 | * The work gets scheduled from the irq handler if there | ||
| 64 | * was a hot plug interrupt. It walks the connector table | ||
| 65 | * and calls the hotplug handler for each one, then sends | ||
| 66 | * a drm hotplug event to alert userspace. | ||
| 67 | */ | ||
| 46 | static void radeon_hotplug_work_func(struct work_struct *work) | 68 | static void radeon_hotplug_work_func(struct work_struct *work) |
| 47 | { | 69 | { |
| 48 | struct radeon_device *rdev = container_of(work, struct radeon_device, | 70 | struct radeon_device *rdev = container_of(work, struct radeon_device, |
| @@ -59,61 +81,94 @@ static void radeon_hotplug_work_func(struct work_struct *work) | |||
| 59 | drm_helper_hpd_irq_event(dev); | 81 | drm_helper_hpd_irq_event(dev); |
| 60 | } | 82 | } |
| 61 | 83 | ||
| 84 | /** | ||
| 85 | * radeon_driver_irq_preinstall_kms - drm irq preinstall callback | ||
| 86 | * | ||
| 87 | * @dev: drm dev pointer | ||
| 88 | * | ||
| 89 | * Gets the hw ready to enable irqs (all asics). | ||
| 90 | * This function disables all interrupt sources on the GPU. | ||
| 91 | */ | ||
| 62 | void radeon_driver_irq_preinstall_kms(struct drm_device *dev) | 92 | void radeon_driver_irq_preinstall_kms(struct drm_device *dev) |
| 63 | { | 93 | { |
| 64 | struct radeon_device *rdev = dev->dev_private; | 94 | struct radeon_device *rdev = dev->dev_private; |
| 95 | unsigned long irqflags; | ||
| 65 | unsigned i; | 96 | unsigned i; |
| 66 | 97 | ||
| 98 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 67 | /* Disable *all* interrupts */ | 99 | /* Disable *all* interrupts */ |
| 68 | for (i = 0; i < RADEON_NUM_RINGS; i++) | 100 | for (i = 0; i < RADEON_NUM_RINGS; i++) |
| 69 | rdev->irq.sw_int[i] = false; | 101 | atomic_set(&rdev->irq.ring_int[i], 0); |
| 70 | rdev->irq.gui_idle = false; | 102 | rdev->irq.gui_idle = false; |
| 71 | for (i = 0; i < RADEON_MAX_HPD_PINS; i++) | 103 | for (i = 0; i < RADEON_MAX_HPD_PINS; i++) |
| 72 | rdev->irq.hpd[i] = false; | 104 | rdev->irq.hpd[i] = false; |
| 73 | for (i = 0; i < RADEON_MAX_CRTCS; i++) { | 105 | for (i = 0; i < RADEON_MAX_CRTCS; i++) { |
| 74 | rdev->irq.crtc_vblank_int[i] = false; | 106 | rdev->irq.crtc_vblank_int[i] = false; |
| 75 | rdev->irq.pflip[i] = false; | 107 | atomic_set(&rdev->irq.pflip[i], 0); |
| 76 | rdev->irq.afmt[i] = false; | 108 | rdev->irq.afmt[i] = false; |
| 77 | } | 109 | } |
| 78 | radeon_irq_set(rdev); | 110 | radeon_irq_set(rdev); |
| 111 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 79 | /* Clear bits */ | 112 | /* Clear bits */ |
| 80 | radeon_irq_process(rdev); | 113 | radeon_irq_process(rdev); |
| 81 | } | 114 | } |
| 82 | 115 | ||
| 116 | /** | ||
| 117 | * radeon_driver_irq_postinstall_kms - drm irq preinstall callback | ||
| 118 | * | ||
| 119 | * @dev: drm dev pointer | ||
| 120 | * | ||
| 121 | * Handles stuff to be done after enabling irqs (all asics). | ||
| 122 | * Returns 0 on success. | ||
| 123 | */ | ||
| 83 | int radeon_driver_irq_postinstall_kms(struct drm_device *dev) | 124 | int radeon_driver_irq_postinstall_kms(struct drm_device *dev) |
| 84 | { | 125 | { |
| 85 | struct radeon_device *rdev = dev->dev_private; | ||
| 86 | unsigned i; | ||
| 87 | |||
| 88 | dev->max_vblank_count = 0x001fffff; | 126 | dev->max_vblank_count = 0x001fffff; |
| 89 | for (i = 0; i < RADEON_NUM_RINGS; i++) | ||
| 90 | rdev->irq.sw_int[i] = true; | ||
| 91 | radeon_irq_set(rdev); | ||
| 92 | return 0; | 127 | return 0; |
| 93 | } | 128 | } |
| 94 | 129 | ||
| 130 | /** | ||
| 131 | * radeon_driver_irq_uninstall_kms - drm irq uninstall callback | ||
| 132 | * | ||
| 133 | * @dev: drm dev pointer | ||
| 134 | * | ||
| 135 | * This function disables all interrupt sources on the GPU (all asics). | ||
| 136 | */ | ||
| 95 | void radeon_driver_irq_uninstall_kms(struct drm_device *dev) | 137 | void radeon_driver_irq_uninstall_kms(struct drm_device *dev) |
| 96 | { | 138 | { |
| 97 | struct radeon_device *rdev = dev->dev_private; | 139 | struct radeon_device *rdev = dev->dev_private; |
| 140 | unsigned long irqflags; | ||
| 98 | unsigned i; | 141 | unsigned i; |
| 99 | 142 | ||
| 100 | if (rdev == NULL) { | 143 | if (rdev == NULL) { |
| 101 | return; | 144 | return; |
| 102 | } | 145 | } |
| 146 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 103 | /* Disable *all* interrupts */ | 147 | /* Disable *all* interrupts */ |
| 104 | for (i = 0; i < RADEON_NUM_RINGS; i++) | 148 | for (i = 0; i < RADEON_NUM_RINGS; i++) |
| 105 | rdev->irq.sw_int[i] = false; | 149 | atomic_set(&rdev->irq.ring_int[i], 0); |
| 106 | rdev->irq.gui_idle = false; | 150 | rdev->irq.gui_idle = false; |
| 107 | for (i = 0; i < RADEON_MAX_HPD_PINS; i++) | 151 | for (i = 0; i < RADEON_MAX_HPD_PINS; i++) |
| 108 | rdev->irq.hpd[i] = false; | 152 | rdev->irq.hpd[i] = false; |
| 109 | for (i = 0; i < RADEON_MAX_CRTCS; i++) { | 153 | for (i = 0; i < RADEON_MAX_CRTCS; i++) { |
| 110 | rdev->irq.crtc_vblank_int[i] = false; | 154 | rdev->irq.crtc_vblank_int[i] = false; |
| 111 | rdev->irq.pflip[i] = false; | 155 | atomic_set(&rdev->irq.pflip[i], 0); |
| 112 | rdev->irq.afmt[i] = false; | 156 | rdev->irq.afmt[i] = false; |
| 113 | } | 157 | } |
| 114 | radeon_irq_set(rdev); | 158 | radeon_irq_set(rdev); |
| 159 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 115 | } | 160 | } |
| 116 | 161 | ||
| 162 | /** | ||
| 163 | * radeon_msi_ok - asic specific msi checks | ||
| 164 | * | ||
| 165 | * @rdev: radeon device pointer | ||
| 166 | * | ||
| 167 | * Handles asic specific MSI checks to determine if | ||
| 168 | * MSIs should be enabled on a particular chip (all asics). | ||
| 169 | * Returns true if MSIs should be enabled, false if MSIs | ||
| 170 | * should not be enabled. | ||
| 171 | */ | ||
| 117 | static bool radeon_msi_ok(struct radeon_device *rdev) | 172 | static bool radeon_msi_ok(struct radeon_device *rdev) |
| 118 | { | 173 | { |
| 119 | /* RV370/RV380 was first asic with MSI support */ | 174 | /* RV370/RV380 was first asic with MSI support */ |
| @@ -166,17 +221,22 @@ static bool radeon_msi_ok(struct radeon_device *rdev) | |||
| 166 | return true; | 221 | return true; |
| 167 | } | 222 | } |
| 168 | 223 | ||
| 224 | /** | ||
| 225 | * radeon_irq_kms_init - init driver interrupt info | ||
| 226 | * | ||
| 227 | * @rdev: radeon device pointer | ||
| 228 | * | ||
| 229 | * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics). | ||
| 230 | * Returns 0 for success, error for failure. | ||
| 231 | */ | ||
| 169 | int radeon_irq_kms_init(struct radeon_device *rdev) | 232 | int radeon_irq_kms_init(struct radeon_device *rdev) |
| 170 | { | 233 | { |
| 171 | int i; | ||
| 172 | int r = 0; | 234 | int r = 0; |
| 173 | 235 | ||
| 174 | INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); | 236 | INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); |
| 175 | INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); | 237 | INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); |
| 176 | 238 | ||
| 177 | spin_lock_init(&rdev->irq.sw_lock); | 239 | spin_lock_init(&rdev->irq.lock); |
| 178 | for (i = 0; i < rdev->num_crtc; i++) | ||
| 179 | spin_lock_init(&rdev->irq.pflip_lock[i]); | ||
| 180 | r = drm_vblank_init(rdev->ddev, rdev->num_crtc); | 240 | r = drm_vblank_init(rdev->ddev, rdev->num_crtc); |
| 181 | if (r) { | 241 | if (r) { |
| 182 | return r; | 242 | return r; |
| @@ -201,6 +261,13 @@ int radeon_irq_kms_init(struct radeon_device *rdev) | |||
| 201 | return 0; | 261 | return 0; |
| 202 | } | 262 | } |
| 203 | 263 | ||
| 264 | /** | ||
| 265 | * radeon_irq_kms_fini - tear down driver interrrupt info | ||
| 266 | * | ||
| 267 | * @rdev: radeon device pointer | ||
| 268 | * | ||
| 269 | * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). | ||
| 270 | */ | ||
| 204 | void radeon_irq_kms_fini(struct radeon_device *rdev) | 271 | void radeon_irq_kms_fini(struct radeon_device *rdev) |
| 205 | { | 272 | { |
| 206 | drm_vblank_cleanup(rdev->ddev); | 273 | drm_vblank_cleanup(rdev->ddev); |
| @@ -213,31 +280,63 @@ void radeon_irq_kms_fini(struct radeon_device *rdev) | |||
| 213 | flush_work_sync(&rdev->hotplug_work); | 280 | flush_work_sync(&rdev->hotplug_work); |
| 214 | } | 281 | } |
| 215 | 282 | ||
| 283 | /** | ||
| 284 | * radeon_irq_kms_sw_irq_get - enable software interrupt | ||
| 285 | * | ||
| 286 | * @rdev: radeon device pointer | ||
| 287 | * @ring: ring whose interrupt you want to enable | ||
| 288 | * | ||
| 289 | * Enables the software interrupt for a specific ring (all asics). | ||
| 290 | * The software interrupt is generally used to signal a fence on | ||
| 291 | * a particular ring. | ||
| 292 | */ | ||
| 216 | void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) | 293 | void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) |
| 217 | { | 294 | { |
| 218 | unsigned long irqflags; | 295 | unsigned long irqflags; |
| 219 | 296 | ||
| 220 | spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); | 297 | if (!rdev->ddev->irq_enabled) |
| 221 | if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount[ring] == 1)) { | 298 | return; |
| 222 | rdev->irq.sw_int[ring] = true; | 299 | |
| 300 | if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) { | ||
| 301 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 223 | radeon_irq_set(rdev); | 302 | radeon_irq_set(rdev); |
| 303 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 224 | } | 304 | } |
| 225 | spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); | ||
| 226 | } | 305 | } |
| 227 | 306 | ||
| 307 | /** | ||
| 308 | * radeon_irq_kms_sw_irq_put - disable software interrupt | ||
| 309 | * | ||
| 310 | * @rdev: radeon device pointer | ||
| 311 | * @ring: ring whose interrupt you want to disable | ||
| 312 | * | ||
| 313 | * Disables the software interrupt for a specific ring (all asics). | ||
| 314 | * The software interrupt is generally used to signal a fence on | ||
| 315 | * a particular ring. | ||
| 316 | */ | ||
| 228 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) | 317 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) |
| 229 | { | 318 | { |
| 230 | unsigned long irqflags; | 319 | unsigned long irqflags; |
| 231 | 320 | ||
| 232 | spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); | 321 | if (!rdev->ddev->irq_enabled) |
| 233 | BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount[ring] <= 0); | 322 | return; |
| 234 | if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount[ring] == 0)) { | 323 | |
| 235 | rdev->irq.sw_int[ring] = false; | 324 | if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) { |
| 325 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 236 | radeon_irq_set(rdev); | 326 | radeon_irq_set(rdev); |
| 327 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 237 | } | 328 | } |
| 238 | spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); | ||
| 239 | } | 329 | } |
| 240 | 330 | ||
| 331 | /** | ||
| 332 | * radeon_irq_kms_pflip_irq_get - enable pageflip interrupt | ||
| 333 | * | ||
| 334 | * @rdev: radeon device pointer | ||
| 335 | * @crtc: crtc whose interrupt you want to enable | ||
| 336 | * | ||
| 337 | * Enables the pageflip interrupt for a specific crtc (all asics). | ||
| 338 | * For pageflips we use the vblank interrupt source. | ||
| 339 | */ | ||
| 241 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) | 340 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) |
| 242 | { | 341 | { |
| 243 | unsigned long irqflags; | 342 | unsigned long irqflags; |
| @@ -245,14 +344,25 @@ void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) | |||
| 245 | if (crtc < 0 || crtc >= rdev->num_crtc) | 344 | if (crtc < 0 || crtc >= rdev->num_crtc) |
| 246 | return; | 345 | return; |
| 247 | 346 | ||
| 248 | spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); | 347 | if (!rdev->ddev->irq_enabled) |
| 249 | if (rdev->ddev->irq_enabled && (++rdev->irq.pflip_refcount[crtc] == 1)) { | 348 | return; |
| 250 | rdev->irq.pflip[crtc] = true; | 349 | |
| 350 | if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) { | ||
| 351 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 251 | radeon_irq_set(rdev); | 352 | radeon_irq_set(rdev); |
| 353 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 252 | } | 354 | } |
| 253 | spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); | ||
| 254 | } | 355 | } |
| 255 | 356 | ||
| 357 | /** | ||
| 358 | * radeon_irq_kms_pflip_irq_put - disable pageflip interrupt | ||
| 359 | * | ||
| 360 | * @rdev: radeon device pointer | ||
| 361 | * @crtc: crtc whose interrupt you want to disable | ||
| 362 | * | ||
| 363 | * Disables the pageflip interrupt for a specific crtc (all asics). | ||
| 364 | * For pageflips we use the vblank interrupt source. | ||
| 365 | */ | ||
| 256 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) | 366 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) |
| 257 | { | 367 | { |
| 258 | unsigned long irqflags; | 368 | unsigned long irqflags; |
| @@ -260,12 +370,121 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) | |||
| 260 | if (crtc < 0 || crtc >= rdev->num_crtc) | 370 | if (crtc < 0 || crtc >= rdev->num_crtc) |
| 261 | return; | 371 | return; |
| 262 | 372 | ||
| 263 | spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); | 373 | if (!rdev->ddev->irq_enabled) |
| 264 | BUG_ON(rdev->ddev->irq_enabled && rdev->irq.pflip_refcount[crtc] <= 0); | 374 | return; |
| 265 | if (rdev->ddev->irq_enabled && (--rdev->irq.pflip_refcount[crtc] == 0)) { | 375 | |
| 266 | rdev->irq.pflip[crtc] = false; | 376 | if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) { |
| 377 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 267 | radeon_irq_set(rdev); | 378 | radeon_irq_set(rdev); |
| 379 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 268 | } | 380 | } |
| 269 | spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); | ||
| 270 | } | 381 | } |
| 271 | 382 | ||
| 383 | /** | ||
| 384 | * radeon_irq_kms_enable_afmt - enable audio format change interrupt | ||
| 385 | * | ||
| 386 | * @rdev: radeon device pointer | ||
| 387 | * @block: afmt block whose interrupt you want to enable | ||
| 388 | * | ||
| 389 | * Enables the afmt change interrupt for a specific afmt block (all asics). | ||
| 390 | */ | ||
| 391 | void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block) | ||
| 392 | { | ||
| 393 | unsigned long irqflags; | ||
| 394 | |||
| 395 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 396 | rdev->irq.afmt[block] = true; | ||
| 397 | radeon_irq_set(rdev); | ||
| 398 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 399 | |||
| 400 | } | ||
| 401 | |||
| 402 | /** | ||
| 403 | * radeon_irq_kms_disable_afmt - disable audio format change interrupt | ||
| 404 | * | ||
| 405 | * @rdev: radeon device pointer | ||
| 406 | * @block: afmt block whose interrupt you want to disable | ||
| 407 | * | ||
| 408 | * Disables the afmt change interrupt for a specific afmt block (all asics). | ||
| 409 | */ | ||
| 410 | void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block) | ||
| 411 | { | ||
| 412 | unsigned long irqflags; | ||
| 413 | |||
| 414 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 415 | rdev->irq.afmt[block] = false; | ||
| 416 | radeon_irq_set(rdev); | ||
| 417 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 418 | } | ||
| 419 | |||
| 420 | /** | ||
| 421 | * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt | ||
| 422 | * | ||
| 423 | * @rdev: radeon device pointer | ||
| 424 | * @hpd_mask: mask of hpd pins you want to enable. | ||
| 425 | * | ||
| 426 | * Enables the hotplug detect interrupt for a specific hpd pin (all asics). | ||
| 427 | */ | ||
| 428 | void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) | ||
| 429 | { | ||
| 430 | unsigned long irqflags; | ||
| 431 | int i; | ||
| 432 | |||
| 433 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 434 | for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) | ||
| 435 | rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i)); | ||
| 436 | radeon_irq_set(rdev); | ||
| 437 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 438 | } | ||
| 439 | |||
| 440 | /** | ||
| 441 | * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt | ||
| 442 | * | ||
| 443 | * @rdev: radeon device pointer | ||
| 444 | * @hpd_mask: mask of hpd pins you want to disable. | ||
| 445 | * | ||
| 446 | * Disables the hotplug detect interrupt for a specific hpd pin (all asics). | ||
| 447 | */ | ||
| 448 | void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) | ||
| 449 | { | ||
| 450 | unsigned long irqflags; | ||
| 451 | int i; | ||
| 452 | |||
| 453 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 454 | for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) | ||
| 455 | rdev->irq.hpd[i] &= !(hpd_mask & (1 << i)); | ||
| 456 | radeon_irq_set(rdev); | ||
| 457 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 458 | } | ||
| 459 | |||
| 460 | /** | ||
| 461 | * radeon_irq_kms_wait_gui_idle - waits for drawing engine to be idle | ||
| 462 | * | ||
| 463 | * @rdev: radeon device pointer | ||
| 464 | * | ||
| 465 | * Enabled the GUI idle interrupt and waits for it to fire (r6xx+). | ||
| 466 | * This is currently used to make sure the 3D engine is idle for power | ||
| 467 | * management, but should be replaces with proper fence waits. | ||
| 468 | * GUI idle interrupts don't work very well on pre-r6xx hw and it also | ||
| 469 | * does not take into account other aspects of the chip that may be busy. | ||
| 470 | * DO NOT USE GOING FORWARD. | ||
| 471 | */ | ||
| 472 | int radeon_irq_kms_wait_gui_idle(struct radeon_device *rdev) | ||
| 473 | { | ||
| 474 | unsigned long irqflags; | ||
| 475 | int r; | ||
| 476 | |||
| 477 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 478 | rdev->irq.gui_idle = true; | ||
| 479 | radeon_irq_set(rdev); | ||
| 480 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 481 | |||
| 482 | r = wait_event_timeout(rdev->irq.idle_queue, radeon_gui_idle(rdev), | ||
| 483 | msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); | ||
| 484 | |||
| 485 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 486 | rdev->irq.gui_idle = false; | ||
| 487 | radeon_irq_set(rdev); | ||
| 488 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 489 | return r; | ||
| 490 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 5c58d7d90cb2..1d73f16b5d97 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
| @@ -33,6 +33,17 @@ | |||
| 33 | #include <linux/vga_switcheroo.h> | 33 | #include <linux/vga_switcheroo.h> |
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 35 | 35 | ||
| 36 | /** | ||
| 37 | * radeon_driver_unload_kms - Main unload function for KMS. | ||
| 38 | * | ||
| 39 | * @dev: drm dev pointer | ||
| 40 | * | ||
| 41 | * This is the main unload function for KMS (all asics). | ||
| 42 | * It calls radeon_modeset_fini() to tear down the | ||
| 43 | * displays, and radeon_device_fini() to tear down | ||
| 44 | * the rest of the device (CP, writeback, etc.). | ||
| 45 | * Returns 0 on success. | ||
| 46 | */ | ||
| 36 | int radeon_driver_unload_kms(struct drm_device *dev) | 47 | int radeon_driver_unload_kms(struct drm_device *dev) |
| 37 | { | 48 | { |
| 38 | struct radeon_device *rdev = dev->dev_private; | 49 | struct radeon_device *rdev = dev->dev_private; |
| @@ -46,6 +57,19 @@ int radeon_driver_unload_kms(struct drm_device *dev) | |||
| 46 | return 0; | 57 | return 0; |
| 47 | } | 58 | } |
| 48 | 59 | ||
| 60 | /** | ||
| 61 | * radeon_driver_load_kms - Main load function for KMS. | ||
| 62 | * | ||
| 63 | * @dev: drm dev pointer | ||
| 64 | * @flags: device flags | ||
| 65 | * | ||
| 66 | * This is the main load function for KMS (all asics). | ||
| 67 | * It calls radeon_device_init() to set up the non-display | ||
| 68 | * parts of the chip (asic init, CP, writeback, etc.), and | ||
| 69 | * radeon_modeset_init() to set up the display parts | ||
| 70 | * (crtcs, encoders, hotplug detect, etc.). | ||
| 71 | * Returns 0 on success, error on failure. | ||
| 72 | */ | ||
| 49 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) | 73 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) |
| 50 | { | 74 | { |
| 51 | struct radeon_device *rdev; | 75 | struct radeon_device *rdev; |
| @@ -96,6 +120,16 @@ out: | |||
| 96 | return r; | 120 | return r; |
| 97 | } | 121 | } |
| 98 | 122 | ||
| 123 | /** | ||
| 124 | * radeon_set_filp_rights - Set filp right. | ||
| 125 | * | ||
| 126 | * @dev: drm dev pointer | ||
| 127 | * @owner: drm file | ||
| 128 | * @applier: drm file | ||
| 129 | * @value: value | ||
| 130 | * | ||
| 131 | * Sets the filp rights for the device (all asics). | ||
| 132 | */ | ||
| 99 | static void radeon_set_filp_rights(struct drm_device *dev, | 133 | static void radeon_set_filp_rights(struct drm_device *dev, |
| 100 | struct drm_file **owner, | 134 | struct drm_file **owner, |
| 101 | struct drm_file *applier, | 135 | struct drm_file *applier, |
| @@ -118,6 +152,18 @@ static void radeon_set_filp_rights(struct drm_device *dev, | |||
| 118 | /* | 152 | /* |
| 119 | * Userspace get information ioctl | 153 | * Userspace get information ioctl |
| 120 | */ | 154 | */ |
| 155 | /** | ||
| 156 | * radeon_info_ioctl - answer a device specific request. | ||
| 157 | * | ||
| 158 | * @rdev: radeon device pointer | ||
| 159 | * @data: request object | ||
| 160 | * @filp: drm filp | ||
| 161 | * | ||
| 162 | * This function is used to pass device specific parameters to the userspace | ||
| 163 | * drivers. Examples include: pci device id, pipeline parms, tiling params, | ||
| 164 | * etc. (all asics). | ||
| 165 | * Returns 0 on success, -EINVAL on failure. | ||
| 166 | */ | ||
| 121 | int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | 167 | int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) |
| 122 | { | 168 | { |
| 123 | struct radeon_device *rdev = dev->dev_private; | 169 | struct radeon_device *rdev = dev->dev_private; |
| @@ -301,16 +347,40 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 301 | /* | 347 | /* |
| 302 | * Outdated mess for old drm with Xorg being in charge (void function now). | 348 | * Outdated mess for old drm with Xorg being in charge (void function now). |
| 303 | */ | 349 | */ |
| 350 | /** | ||
| 351 | * radeon_driver_firstopen_kms - drm callback for first open | ||
| 352 | * | ||
| 353 | * @dev: drm dev pointer | ||
| 354 | * | ||
| 355 | * Nothing to be done for KMS (all asics). | ||
| 356 | * Returns 0 on success. | ||
| 357 | */ | ||
| 304 | int radeon_driver_firstopen_kms(struct drm_device *dev) | 358 | int radeon_driver_firstopen_kms(struct drm_device *dev) |
| 305 | { | 359 | { |
| 306 | return 0; | 360 | return 0; |
| 307 | } | 361 | } |
| 308 | 362 | ||
| 363 | /** | ||
| 364 | * radeon_driver_firstopen_kms - drm callback for last close | ||
| 365 | * | ||
| 366 | * @dev: drm dev pointer | ||
| 367 | * | ||
| 368 | * Switch vga switcheroo state after last close (all asics). | ||
| 369 | */ | ||
| 309 | void radeon_driver_lastclose_kms(struct drm_device *dev) | 370 | void radeon_driver_lastclose_kms(struct drm_device *dev) |
| 310 | { | 371 | { |
| 311 | vga_switcheroo_process_delayed_switch(); | 372 | vga_switcheroo_process_delayed_switch(); |
| 312 | } | 373 | } |
| 313 | 374 | ||
| 375 | /** | ||
| 376 | * radeon_driver_open_kms - drm callback for open | ||
| 377 | * | ||
| 378 | * @dev: drm dev pointer | ||
| 379 | * @file_priv: drm file | ||
| 380 | * | ||
| 381 | * On device open, init vm on cayman+ (all asics). | ||
| 382 | * Returns 0 on success, error on failure. | ||
| 383 | */ | ||
| 314 | int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) | 384 | int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) |
| 315 | { | 385 | { |
| 316 | struct radeon_device *rdev = dev->dev_private; | 386 | struct radeon_device *rdev = dev->dev_private; |
| @@ -339,6 +409,14 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) | |||
| 339 | return 0; | 409 | return 0; |
| 340 | } | 410 | } |
| 341 | 411 | ||
| 412 | /** | ||
| 413 | * radeon_driver_postclose_kms - drm callback for post close | ||
| 414 | * | ||
| 415 | * @dev: drm dev pointer | ||
| 416 | * @file_priv: drm file | ||
| 417 | * | ||
| 418 | * On device post close, tear down vm on cayman+ (all asics). | ||
| 419 | */ | ||
| 342 | void radeon_driver_postclose_kms(struct drm_device *dev, | 420 | void radeon_driver_postclose_kms(struct drm_device *dev, |
| 343 | struct drm_file *file_priv) | 421 | struct drm_file *file_priv) |
| 344 | { | 422 | { |
| @@ -354,6 +432,15 @@ void radeon_driver_postclose_kms(struct drm_device *dev, | |||
| 354 | } | 432 | } |
| 355 | } | 433 | } |
| 356 | 434 | ||
| 435 | /** | ||
| 436 | * radeon_driver_preclose_kms - drm callback for pre close | ||
| 437 | * | ||
| 438 | * @dev: drm dev pointer | ||
| 439 | * @file_priv: drm file | ||
| 440 | * | ||
| 441 | * On device pre close, tear down hyperz and cmask filps on r1xx-r5xx | ||
| 442 | * (all asics). | ||
| 443 | */ | ||
| 357 | void radeon_driver_preclose_kms(struct drm_device *dev, | 444 | void radeon_driver_preclose_kms(struct drm_device *dev, |
| 358 | struct drm_file *file_priv) | 445 | struct drm_file *file_priv) |
| 359 | { | 446 | { |
| @@ -367,6 +454,15 @@ void radeon_driver_preclose_kms(struct drm_device *dev, | |||
| 367 | /* | 454 | /* |
| 368 | * VBlank related functions. | 455 | * VBlank related functions. |
| 369 | */ | 456 | */ |
| 457 | /** | ||
| 458 | * radeon_get_vblank_counter_kms - get frame count | ||
| 459 | * | ||
| 460 | * @dev: drm dev pointer | ||
| 461 | * @crtc: crtc to get the frame count from | ||
| 462 | * | ||
| 463 | * Gets the frame count on the requested crtc (all asics). | ||
| 464 | * Returns frame count on success, -EINVAL on failure. | ||
| 465 | */ | ||
| 370 | u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) | 466 | u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) |
| 371 | { | 467 | { |
| 372 | struct radeon_device *rdev = dev->dev_private; | 468 | struct radeon_device *rdev = dev->dev_private; |
| @@ -379,34 +475,70 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) | |||
| 379 | return radeon_get_vblank_counter(rdev, crtc); | 475 | return radeon_get_vblank_counter(rdev, crtc); |
| 380 | } | 476 | } |
| 381 | 477 | ||
| 478 | /** | ||
| 479 | * radeon_enable_vblank_kms - enable vblank interrupt | ||
| 480 | * | ||
| 481 | * @dev: drm dev pointer | ||
| 482 | * @crtc: crtc to enable vblank interrupt for | ||
| 483 | * | ||
| 484 | * Enable the interrupt on the requested crtc (all asics). | ||
| 485 | * Returns 0 on success, -EINVAL on failure. | ||
| 486 | */ | ||
| 382 | int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) | 487 | int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) |
| 383 | { | 488 | { |
| 384 | struct radeon_device *rdev = dev->dev_private; | 489 | struct radeon_device *rdev = dev->dev_private; |
| 490 | unsigned long irqflags; | ||
| 491 | int r; | ||
| 385 | 492 | ||
| 386 | if (crtc < 0 || crtc >= rdev->num_crtc) { | 493 | if (crtc < 0 || crtc >= rdev->num_crtc) { |
| 387 | DRM_ERROR("Invalid crtc %d\n", crtc); | 494 | DRM_ERROR("Invalid crtc %d\n", crtc); |
| 388 | return -EINVAL; | 495 | return -EINVAL; |
| 389 | } | 496 | } |
| 390 | 497 | ||
| 498 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 391 | rdev->irq.crtc_vblank_int[crtc] = true; | 499 | rdev->irq.crtc_vblank_int[crtc] = true; |
| 392 | 500 | r = radeon_irq_set(rdev); | |
| 393 | return radeon_irq_set(rdev); | 501 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); |
| 502 | return r; | ||
| 394 | } | 503 | } |
| 395 | 504 | ||
| 505 | /** | ||
| 506 | * radeon_disable_vblank_kms - disable vblank interrupt | ||
| 507 | * | ||
| 508 | * @dev: drm dev pointer | ||
| 509 | * @crtc: crtc to disable vblank interrupt for | ||
| 510 | * | ||
| 511 | * Disable the interrupt on the requested crtc (all asics). | ||
| 512 | */ | ||
| 396 | void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) | 513 | void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) |
| 397 | { | 514 | { |
| 398 | struct radeon_device *rdev = dev->dev_private; | 515 | struct radeon_device *rdev = dev->dev_private; |
| 516 | unsigned long irqflags; | ||
| 399 | 517 | ||
| 400 | if (crtc < 0 || crtc >= rdev->num_crtc) { | 518 | if (crtc < 0 || crtc >= rdev->num_crtc) { |
| 401 | DRM_ERROR("Invalid crtc %d\n", crtc); | 519 | DRM_ERROR("Invalid crtc %d\n", crtc); |
| 402 | return; | 520 | return; |
| 403 | } | 521 | } |
| 404 | 522 | ||
| 523 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 405 | rdev->irq.crtc_vblank_int[crtc] = false; | 524 | rdev->irq.crtc_vblank_int[crtc] = false; |
| 406 | |||
| 407 | radeon_irq_set(rdev); | 525 | radeon_irq_set(rdev); |
| 526 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 408 | } | 527 | } |
| 409 | 528 | ||
| 529 | /** | ||
| 530 | * radeon_get_vblank_timestamp_kms - get vblank timestamp | ||
| 531 | * | ||
| 532 | * @dev: drm dev pointer | ||
| 533 | * @crtc: crtc to get the timestamp for | ||
| 534 | * @max_error: max error | ||
| 535 | * @vblank_time: time value | ||
| 536 | * @flags: flags passed to the driver | ||
| 537 | * | ||
| 538 | * Gets the timestamp on the requested crtc based on the | ||
| 539 | * scanout position. (all asics). | ||
| 540 | * Returns postive status flags on success, negative error on failure. | ||
| 541 | */ | ||
| 410 | int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, | 542 | int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, |
| 411 | int *max_error, | 543 | int *max_error, |
| 412 | struct timeval *vblank_time, | 544 | struct timeval *vblank_time, |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 210317c7045e..d5fd615897ec 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c | |||
| @@ -990,7 +990,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
| 990 | } | 990 | } |
| 991 | 991 | ||
| 992 | static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, | 992 | static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, |
| 993 | struct drm_display_mode *mode, | 993 | const struct drm_display_mode *mode, |
| 994 | struct drm_display_mode *adjusted_mode) | 994 | struct drm_display_mode *adjusted_mode) |
| 995 | { | 995 | { |
| 996 | if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) | 996 | if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index a0c82229e8f0..670e9910f869 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c | |||
| @@ -244,7 +244,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, | |||
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder, | 246 | static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder, |
| 247 | struct drm_display_mode *mode, | 247 | const struct drm_display_mode *mode, |
| 248 | struct drm_display_mode *adjusted_mode) | 248 | struct drm_display_mode *adjusted_mode) |
| 249 | { | 249 | { |
| 250 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 250 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 5b10ffd7bb2f..f380d59c5763 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -488,7 +488,7 @@ extern void radeon_connector_hotplug(struct drm_connector *connector); | |||
| 488 | extern int radeon_dp_mode_valid_helper(struct drm_connector *connector, | 488 | extern int radeon_dp_mode_valid_helper(struct drm_connector *connector, |
| 489 | struct drm_display_mode *mode); | 489 | struct drm_display_mode *mode); |
| 490 | extern void radeon_dp_set_link_config(struct drm_connector *connector, | 490 | extern void radeon_dp_set_link_config(struct drm_connector *connector, |
| 491 | struct drm_display_mode *mode); | 491 | const struct drm_display_mode *mode); |
| 492 | extern void radeon_dp_link_train(struct drm_encoder *encoder, | 492 | extern void radeon_dp_link_train(struct drm_encoder *encoder, |
| 493 | struct drm_connector *connector); | 493 | struct drm_connector *connector); |
| 494 | extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); | 494 | extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); |
| @@ -678,7 +678,7 @@ void radeon_enc_destroy(struct drm_encoder *encoder); | |||
| 678 | void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); | 678 | void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); |
| 679 | void radeon_combios_asic_init(struct drm_device *dev); | 679 | void radeon_combios_asic_init(struct drm_device *dev); |
| 680 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | 680 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, |
| 681 | struct drm_display_mode *mode, | 681 | const struct drm_display_mode *mode, |
| 682 | struct drm_display_mode *adjusted_mode); | 682 | struct drm_display_mode *adjusted_mode); |
| 683 | void radeon_panel_mode_fixup(struct drm_encoder *encoder, | 683 | void radeon_panel_mode_fixup(struct drm_encoder *encoder, |
| 684 | struct drm_display_mode *adjusted_mode); | 684 | struct drm_display_mode *adjusted_mode); |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 830f1a7b486f..1f1a4c803c1d 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
| @@ -115,9 +115,7 @@ int radeon_bo_create(struct radeon_device *rdev, | |||
| 115 | 115 | ||
| 116 | size = ALIGN(size, PAGE_SIZE); | 116 | size = ALIGN(size, PAGE_SIZE); |
| 117 | 117 | ||
| 118 | if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { | 118 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; |
| 119 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; | ||
| 120 | } | ||
| 121 | if (kernel) { | 119 | if (kernel) { |
| 122 | type = ttm_bo_type_kernel; | 120 | type = ttm_bo_type_kernel; |
| 123 | } else if (sg) { | 121 | } else if (sg) { |
| @@ -138,7 +136,6 @@ int radeon_bo_create(struct radeon_device *rdev, | |||
| 138 | acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, | 136 | acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, |
| 139 | sizeof(struct radeon_bo)); | 137 | sizeof(struct radeon_bo)); |
| 140 | 138 | ||
| 141 | retry: | ||
| 142 | bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); | 139 | bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); |
| 143 | if (bo == NULL) | 140 | if (bo == NULL) |
| 144 | return -ENOMEM; | 141 | return -ENOMEM; |
| @@ -152,13 +149,15 @@ retry: | |||
| 152 | bo->surface_reg = -1; | 149 | bo->surface_reg = -1; |
| 153 | INIT_LIST_HEAD(&bo->list); | 150 | INIT_LIST_HEAD(&bo->list); |
| 154 | INIT_LIST_HEAD(&bo->va); | 151 | INIT_LIST_HEAD(&bo->va); |
| 152 | |||
| 153 | retry: | ||
| 155 | radeon_ttm_placement_from_domain(bo, domain); | 154 | radeon_ttm_placement_from_domain(bo, domain); |
| 156 | /* Kernel allocation are uninterruptible */ | 155 | /* Kernel allocation are uninterruptible */ |
| 157 | mutex_lock(&rdev->vram_mutex); | 156 | down_read(&rdev->pm.mclk_lock); |
| 158 | r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type, | 157 | r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type, |
| 159 | &bo->placement, page_align, 0, !kernel, NULL, | 158 | &bo->placement, page_align, 0, !kernel, NULL, |
| 160 | acc_size, sg, &radeon_ttm_bo_destroy); | 159 | acc_size, sg, &radeon_ttm_bo_destroy); |
| 161 | mutex_unlock(&rdev->vram_mutex); | 160 | up_read(&rdev->pm.mclk_lock); |
| 162 | if (unlikely(r != 0)) { | 161 | if (unlikely(r != 0)) { |
| 163 | if (r != -ERESTARTSYS) { | 162 | if (r != -ERESTARTSYS) { |
| 164 | if (domain == RADEON_GEM_DOMAIN_VRAM) { | 163 | if (domain == RADEON_GEM_DOMAIN_VRAM) { |
| @@ -219,9 +218,9 @@ void radeon_bo_unref(struct radeon_bo **bo) | |||
| 219 | return; | 218 | return; |
| 220 | rdev = (*bo)->rdev; | 219 | rdev = (*bo)->rdev; |
| 221 | tbo = &((*bo)->tbo); | 220 | tbo = &((*bo)->tbo); |
| 222 | mutex_lock(&rdev->vram_mutex); | 221 | down_read(&rdev->pm.mclk_lock); |
| 223 | ttm_bo_unref(&tbo); | 222 | ttm_bo_unref(&tbo); |
| 224 | mutex_unlock(&rdev->vram_mutex); | 223 | up_read(&rdev->pm.mclk_lock); |
| 225 | if (tbo == NULL) | 224 | if (tbo == NULL) |
| 226 | *bo = NULL; | 225 | *bo = NULL; |
| 227 | } | 226 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 5b37e283ec38..7ae606600107 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #define RADEON_IDLE_LOOP_MS 100 | 34 | #define RADEON_IDLE_LOOP_MS 100 |
| 35 | #define RADEON_RECLOCK_DELAY_MS 200 | 35 | #define RADEON_RECLOCK_DELAY_MS 200 |
| 36 | #define RADEON_WAIT_VBLANK_TIMEOUT 200 | 36 | #define RADEON_WAIT_VBLANK_TIMEOUT 200 |
| 37 | #define RADEON_WAIT_IDLE_TIMEOUT 200 | ||
| 38 | 37 | ||
| 39 | static const char *radeon_pm_state_type_name[5] = { | 38 | static const char *radeon_pm_state_type_name[5] = { |
| 40 | "Default", | 39 | "Default", |
| @@ -251,21 +250,14 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) | |||
| 251 | return; | 250 | return; |
| 252 | 251 | ||
| 253 | mutex_lock(&rdev->ddev->struct_mutex); | 252 | mutex_lock(&rdev->ddev->struct_mutex); |
| 254 | mutex_lock(&rdev->vram_mutex); | 253 | down_write(&rdev->pm.mclk_lock); |
| 255 | mutex_lock(&rdev->ring_lock); | 254 | mutex_lock(&rdev->ring_lock); |
| 256 | 255 | ||
| 257 | /* gui idle int has issues on older chips it seems */ | 256 | /* gui idle int has issues on older chips it seems */ |
| 258 | if (rdev->family >= CHIP_R600) { | 257 | if (rdev->family >= CHIP_R600) { |
| 259 | if (rdev->irq.installed) { | 258 | if (rdev->irq.installed) { |
| 260 | /* wait for GPU idle */ | 259 | /* wait for GPU to become idle */ |
| 261 | rdev->pm.gui_idle = false; | 260 | radeon_irq_kms_wait_gui_idle(rdev); |
| 262 | rdev->irq.gui_idle = true; | ||
| 263 | radeon_irq_set(rdev); | ||
| 264 | wait_event_interruptible_timeout( | ||
| 265 | rdev->irq.idle_queue, rdev->pm.gui_idle, | ||
| 266 | msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); | ||
| 267 | rdev->irq.gui_idle = false; | ||
| 268 | radeon_irq_set(rdev); | ||
| 269 | } | 261 | } |
| 270 | } else { | 262 | } else { |
| 271 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 263 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| @@ -303,7 +295,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) | |||
| 303 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; | 295 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; |
| 304 | 296 | ||
| 305 | mutex_unlock(&rdev->ring_lock); | 297 | mutex_unlock(&rdev->ring_lock); |
| 306 | mutex_unlock(&rdev->vram_mutex); | 298 | up_write(&rdev->pm.mclk_lock); |
| 307 | mutex_unlock(&rdev->ddev->struct_mutex); | 299 | mutex_unlock(&rdev->ddev->struct_mutex); |
| 308 | } | 300 | } |
| 309 | 301 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 983658c91358..ec79b3750430 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
| @@ -35,47 +35,97 @@ | |||
| 35 | #include "atom.h" | 35 | #include "atom.h" |
| 36 | 36 | ||
| 37 | /* | 37 | /* |
| 38 | * IB. | 38 | * IB |
| 39 | * IBs (Indirect Buffers) and areas of GPU accessible memory where | ||
| 40 | * commands are stored. You can put a pointer to the IB in the | ||
| 41 | * command ring and the hw will fetch the commands from the IB | ||
| 42 | * and execute them. Generally userspace acceleration drivers | ||
| 43 | * produce command buffers which are send to the kernel and | ||
| 44 | * put in IBs for execution by the requested ring. | ||
| 39 | */ | 45 | */ |
| 40 | int radeon_debugfs_sa_init(struct radeon_device *rdev); | 46 | int radeon_debugfs_sa_init(struct radeon_device *rdev); |
| 41 | 47 | ||
| 48 | /** | ||
| 49 | * radeon_ib_get - request an IB (Indirect Buffer) | ||
| 50 | * | ||
| 51 | * @rdev: radeon_device pointer | ||
| 52 | * @ring: ring index the IB is associated with | ||
| 53 | * @ib: IB object returned | ||
| 54 | * @size: requested IB size | ||
| 55 | * | ||
| 56 | * Request an IB (all asics). IBs are allocated using the | ||
| 57 | * suballocator. | ||
| 58 | * Returns 0 on success, error on failure. | ||
| 59 | */ | ||
| 42 | int radeon_ib_get(struct radeon_device *rdev, int ring, | 60 | int radeon_ib_get(struct radeon_device *rdev, int ring, |
| 43 | struct radeon_ib *ib, unsigned size) | 61 | struct radeon_ib *ib, unsigned size) |
| 44 | { | 62 | { |
| 45 | int r; | 63 | int i, r; |
| 46 | 64 | ||
| 47 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256, true); | 65 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256, true); |
| 48 | if (r) { | 66 | if (r) { |
| 49 | dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); | 67 | dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); |
| 50 | return r; | 68 | return r; |
| 51 | } | 69 | } |
| 52 | r = radeon_fence_create(rdev, &ib->fence, ring); | 70 | |
| 71 | r = radeon_semaphore_create(rdev, &ib->semaphore); | ||
| 53 | if (r) { | 72 | if (r) { |
| 54 | dev_err(rdev->dev, "failed to create fence for new IB (%d)\n", r); | ||
| 55 | radeon_sa_bo_free(rdev, &ib->sa_bo, NULL); | ||
| 56 | return r; | 73 | return r; |
| 57 | } | 74 | } |
| 58 | 75 | ||
| 76 | ib->ring = ring; | ||
| 77 | ib->fence = NULL; | ||
| 59 | ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo); | 78 | ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo); |
| 60 | ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo); | 79 | ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo); |
| 61 | ib->vm_id = 0; | 80 | ib->vm_id = 0; |
| 62 | ib->is_const_ib = false; | 81 | ib->is_const_ib = false; |
| 63 | ib->semaphore = NULL; | 82 | for (i = 0; i < RADEON_NUM_RINGS; ++i) |
| 83 | ib->sync_to[i] = NULL; | ||
| 64 | 84 | ||
| 65 | return 0; | 85 | return 0; |
| 66 | } | 86 | } |
| 67 | 87 | ||
| 88 | /** | ||
| 89 | * radeon_ib_free - free an IB (Indirect Buffer) | ||
| 90 | * | ||
| 91 | * @rdev: radeon_device pointer | ||
| 92 | * @ib: IB object to free | ||
| 93 | * | ||
| 94 | * Free an IB (all asics). | ||
| 95 | */ | ||
| 68 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) | 96 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) |
| 69 | { | 97 | { |
| 70 | radeon_semaphore_free(rdev, ib->semaphore, ib->fence); | 98 | radeon_semaphore_free(rdev, &ib->semaphore, ib->fence); |
| 71 | radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence); | 99 | radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence); |
| 72 | radeon_fence_unref(&ib->fence); | 100 | radeon_fence_unref(&ib->fence); |
| 73 | } | 101 | } |
| 74 | 102 | ||
| 75 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) | 103 | /** |
| 104 | * radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring | ||
| 105 | * | ||
| 106 | * @rdev: radeon_device pointer | ||
| 107 | * @ib: IB object to schedule | ||
| 108 | * @const_ib: Const IB to schedule (SI only) | ||
| 109 | * | ||
| 110 | * Schedule an IB on the associated ring (all asics). | ||
| 111 | * Returns 0 on success, error on failure. | ||
| 112 | * | ||
| 113 | * On SI, there are two parallel engines fed from the primary ring, | ||
| 114 | * the CE (Constant Engine) and the DE (Drawing Engine). Since | ||
| 115 | * resource descriptors have moved to memory, the CE allows you to | ||
| 116 | * prime the caches while the DE is updating register state so that | ||
| 117 | * the resource descriptors will be already in cache when the draw is | ||
| 118 | * processed. To accomplish this, the userspace driver submits two | ||
| 119 | * IBs, one for the CE and one for the DE. If there is a CE IB (called | ||
| 120 | * a CONST_IB), it will be put on the ring prior to the DE IB. Prior | ||
| 121 | * to SI there was just a DE IB. | ||
| 122 | */ | ||
| 123 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, | ||
| 124 | struct radeon_ib *const_ib) | ||
| 76 | { | 125 | { |
| 77 | struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; | 126 | struct radeon_ring *ring = &rdev->ring[ib->ring]; |
| 78 | int r = 0; | 127 | bool need_sync = false; |
| 128 | int i, r = 0; | ||
| 79 | 129 | ||
| 80 | if (!ib->length_dw || !ring->ready) { | 130 | if (!ib->length_dw || !ring->ready) { |
| 81 | /* TODO: Nothings in the ib we should report. */ | 131 | /* TODO: Nothings in the ib we should report. */ |
| @@ -84,17 +134,51 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 84 | } | 134 | } |
| 85 | 135 | ||
| 86 | /* 64 dwords should be enough for fence too */ | 136 | /* 64 dwords should be enough for fence too */ |
| 87 | r = radeon_ring_lock(rdev, ring, 64); | 137 | r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8); |
| 88 | if (r) { | 138 | if (r) { |
| 89 | dev_err(rdev->dev, "scheduling IB failed (%d).\n", r); | 139 | dev_err(rdev->dev, "scheduling IB failed (%d).\n", r); |
| 90 | return r; | 140 | return r; |
| 91 | } | 141 | } |
| 92 | radeon_ring_ib_execute(rdev, ib->fence->ring, ib); | 142 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
| 93 | radeon_fence_emit(rdev, ib->fence); | 143 | struct radeon_fence *fence = ib->sync_to[i]; |
| 144 | if (radeon_fence_need_sync(fence, ib->ring)) { | ||
| 145 | need_sync = true; | ||
| 146 | radeon_semaphore_sync_rings(rdev, ib->semaphore, | ||
| 147 | fence->ring, ib->ring); | ||
| 148 | radeon_fence_note_sync(fence, ib->ring); | ||
| 149 | } | ||
| 150 | } | ||
| 151 | /* immediately free semaphore when we don't need to sync */ | ||
| 152 | if (!need_sync) { | ||
| 153 | radeon_semaphore_free(rdev, &ib->semaphore, NULL); | ||
| 154 | } | ||
| 155 | if (const_ib) { | ||
| 156 | radeon_ring_ib_execute(rdev, const_ib->ring, const_ib); | ||
| 157 | radeon_semaphore_free(rdev, &const_ib->semaphore, NULL); | ||
| 158 | } | ||
| 159 | radeon_ring_ib_execute(rdev, ib->ring, ib); | ||
| 160 | r = radeon_fence_emit(rdev, &ib->fence, ib->ring); | ||
| 161 | if (r) { | ||
| 162 | dev_err(rdev->dev, "failed to emit fence for new IB (%d)\n", r); | ||
| 163 | radeon_ring_unlock_undo(rdev, ring); | ||
| 164 | return r; | ||
| 165 | } | ||
| 166 | if (const_ib) { | ||
| 167 | const_ib->fence = radeon_fence_ref(ib->fence); | ||
| 168 | } | ||
| 94 | radeon_ring_unlock_commit(rdev, ring); | 169 | radeon_ring_unlock_commit(rdev, ring); |
| 95 | return 0; | 170 | return 0; |
| 96 | } | 171 | } |
| 97 | 172 | ||
| 173 | /** | ||
| 174 | * radeon_ib_pool_init - Init the IB (Indirect Buffer) pool | ||
| 175 | * | ||
| 176 | * @rdev: radeon_device pointer | ||
| 177 | * | ||
| 178 | * Initialize the suballocator to manage a pool of memory | ||
| 179 | * for use as IBs (all asics). | ||
| 180 | * Returns 0 on success, error on failure. | ||
| 181 | */ | ||
| 98 | int radeon_ib_pool_init(struct radeon_device *rdev) | 182 | int radeon_ib_pool_init(struct radeon_device *rdev) |
| 99 | { | 183 | { |
| 100 | int r; | 184 | int r; |
| @@ -108,6 +192,12 @@ int radeon_ib_pool_init(struct radeon_device *rdev) | |||
| 108 | if (r) { | 192 | if (r) { |
| 109 | return r; | 193 | return r; |
| 110 | } | 194 | } |
| 195 | |||
| 196 | r = radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo); | ||
| 197 | if (r) { | ||
| 198 | return r; | ||
| 199 | } | ||
| 200 | |||
| 111 | rdev->ib_pool_ready = true; | 201 | rdev->ib_pool_ready = true; |
| 112 | if (radeon_debugfs_sa_init(rdev)) { | 202 | if (radeon_debugfs_sa_init(rdev)) { |
| 113 | dev_err(rdev->dev, "failed to register debugfs file for SA\n"); | 203 | dev_err(rdev->dev, "failed to register debugfs file for SA\n"); |
| @@ -115,24 +205,33 @@ int radeon_ib_pool_init(struct radeon_device *rdev) | |||
| 115 | return 0; | 205 | return 0; |
| 116 | } | 206 | } |
| 117 | 207 | ||
| 208 | /** | ||
| 209 | * radeon_ib_pool_fini - Free the IB (Indirect Buffer) pool | ||
| 210 | * | ||
| 211 | * @rdev: radeon_device pointer | ||
| 212 | * | ||
| 213 | * Tear down the suballocator managing the pool of memory | ||
| 214 | * for use as IBs (all asics). | ||
| 215 | */ | ||
| 118 | void radeon_ib_pool_fini(struct radeon_device *rdev) | 216 | void radeon_ib_pool_fini(struct radeon_device *rdev) |
| 119 | { | 217 | { |
| 120 | if (rdev->ib_pool_ready) { | 218 | if (rdev->ib_pool_ready) { |
| 219 | radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo); | ||
| 121 | radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo); | 220 | radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo); |
| 122 | rdev->ib_pool_ready = false; | 221 | rdev->ib_pool_ready = false; |
| 123 | } | 222 | } |
| 124 | } | 223 | } |
| 125 | 224 | ||
| 126 | int radeon_ib_pool_start(struct radeon_device *rdev) | 225 | /** |
| 127 | { | 226 | * radeon_ib_ring_tests - test IBs on the rings |
| 128 | return radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo); | 227 | * |
| 129 | } | 228 | * @rdev: radeon_device pointer |
| 130 | 229 | * | |
| 131 | int radeon_ib_pool_suspend(struct radeon_device *rdev) | 230 | * Test an IB (Indirect Buffer) on each ring. |
| 132 | { | 231 | * If the test fails, disable the ring. |
| 133 | return radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo); | 232 | * Returns 0 on success, error if the primary GFX ring |
| 134 | } | 233 | * IB test fails. |
| 135 | 234 | */ | |
| 136 | int radeon_ib_ring_tests(struct radeon_device *rdev) | 235 | int radeon_ib_ring_tests(struct radeon_device *rdev) |
| 137 | { | 236 | { |
| 138 | unsigned i; | 237 | unsigned i; |
| @@ -164,10 +263,28 @@ int radeon_ib_ring_tests(struct radeon_device *rdev) | |||
| 164 | } | 263 | } |
| 165 | 264 | ||
| 166 | /* | 265 | /* |
| 167 | * Ring. | 266 | * Rings |
| 267 | * Most engines on the GPU are fed via ring buffers. Ring | ||
| 268 | * buffers are areas of GPU accessible memory that the host | ||
| 269 | * writes commands into and the GPU reads commands out of. | ||
| 270 | * There is a rptr (read pointer) that determines where the | ||
| 271 | * GPU is currently reading, and a wptr (write pointer) | ||
| 272 | * which determines where the host has written. When the | ||
| 273 | * pointers are equal, the ring is idle. When the host | ||
| 274 | * writes commands to the ring buffer, it increments the | ||
| 275 | * wptr. The GPU then starts fetching commands and executes | ||
| 276 | * them until the pointers are equal again. | ||
| 168 | */ | 277 | */ |
| 169 | int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring); | 278 | int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring); |
| 170 | 279 | ||
| 280 | /** | ||
| 281 | * radeon_ring_write - write a value to the ring | ||
| 282 | * | ||
| 283 | * @ring: radeon_ring structure holding ring information | ||
| 284 | * @v: dword (dw) value to write | ||
| 285 | * | ||
| 286 | * Write a value to the requested ring buffer (all asics). | ||
| 287 | */ | ||
| 171 | void radeon_ring_write(struct radeon_ring *ring, uint32_t v) | 288 | void radeon_ring_write(struct radeon_ring *ring, uint32_t v) |
| 172 | { | 289 | { |
| 173 | #if DRM_DEBUG_CODE | 290 | #if DRM_DEBUG_CODE |
| @@ -181,21 +298,37 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v) | |||
| 181 | ring->ring_free_dw--; | 298 | ring->ring_free_dw--; |
| 182 | } | 299 | } |
| 183 | 300 | ||
| 184 | int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *ring) | 301 | /** |
| 302 | * radeon_ring_supports_scratch_reg - check if the ring supports | ||
| 303 | * writing to scratch registers | ||
| 304 | * | ||
| 305 | * @rdev: radeon_device pointer | ||
| 306 | * @ring: radeon_ring structure holding ring information | ||
| 307 | * | ||
| 308 | * Check if a specific ring supports writing to scratch registers (all asics). | ||
| 309 | * Returns true if the ring supports writing to scratch regs, false if not. | ||
| 310 | */ | ||
| 311 | bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, | ||
| 312 | struct radeon_ring *ring) | ||
| 185 | { | 313 | { |
| 186 | /* r1xx-r5xx only has CP ring */ | 314 | switch (ring->idx) { |
| 187 | if (rdev->family < CHIP_R600) | 315 | case RADEON_RING_TYPE_GFX_INDEX: |
| 188 | return RADEON_RING_TYPE_GFX_INDEX; | 316 | case CAYMAN_RING_TYPE_CP1_INDEX: |
| 189 | 317 | case CAYMAN_RING_TYPE_CP2_INDEX: | |
| 190 | if (rdev->family >= CHIP_CAYMAN) { | 318 | return true; |
| 191 | if (ring == &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]) | 319 | default: |
| 192 | return CAYMAN_RING_TYPE_CP1_INDEX; | 320 | return false; |
| 193 | else if (ring == &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]) | ||
| 194 | return CAYMAN_RING_TYPE_CP2_INDEX; | ||
| 195 | } | 321 | } |
| 196 | return RADEON_RING_TYPE_GFX_INDEX; | ||
| 197 | } | 322 | } |
| 198 | 323 | ||
| 324 | /** | ||
| 325 | * radeon_ring_free_size - update the free size | ||
| 326 | * | ||
| 327 | * @rdev: radeon_device pointer | ||
| 328 | * @ring: radeon_ring structure holding ring information | ||
| 329 | * | ||
| 330 | * Update the free dw slots in the ring buffer (all asics). | ||
| 331 | */ | ||
| 199 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) | 332 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) |
| 200 | { | 333 | { |
| 201 | u32 rptr; | 334 | u32 rptr; |
| @@ -214,7 +347,16 @@ void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 214 | } | 347 | } |
| 215 | } | 348 | } |
| 216 | 349 | ||
| 217 | 350 | /** | |
| 351 | * radeon_ring_alloc - allocate space on the ring buffer | ||
| 352 | * | ||
| 353 | * @rdev: radeon_device pointer | ||
| 354 | * @ring: radeon_ring structure holding ring information | ||
| 355 | * @ndw: number of dwords to allocate in the ring buffer | ||
| 356 | * | ||
| 357 | * Allocate @ndw dwords in the ring buffer (all asics). | ||
| 358 | * Returns 0 on success, error on failure. | ||
| 359 | */ | ||
| 218 | int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) | 360 | int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) |
| 219 | { | 361 | { |
| 220 | int r; | 362 | int r; |
| @@ -227,7 +369,7 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi | |||
| 227 | if (ndw < ring->ring_free_dw) { | 369 | if (ndw < ring->ring_free_dw) { |
| 228 | break; | 370 | break; |
| 229 | } | 371 | } |
| 230 | r = radeon_fence_wait_next_locked(rdev, radeon_ring_index(rdev, ring)); | 372 | r = radeon_fence_wait_next_locked(rdev, ring->idx); |
| 231 | if (r) | 373 | if (r) |
| 232 | return r; | 374 | return r; |
| 233 | } | 375 | } |
| @@ -236,6 +378,17 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi | |||
| 236 | return 0; | 378 | return 0; |
| 237 | } | 379 | } |
| 238 | 380 | ||
| 381 | /** | ||
| 382 | * radeon_ring_lock - lock the ring and allocate space on it | ||
| 383 | * | ||
| 384 | * @rdev: radeon_device pointer | ||
| 385 | * @ring: radeon_ring structure holding ring information | ||
| 386 | * @ndw: number of dwords to allocate in the ring buffer | ||
| 387 | * | ||
| 388 | * Lock the ring and allocate @ndw dwords in the ring buffer | ||
| 389 | * (all asics). | ||
| 390 | * Returns 0 on success, error on failure. | ||
| 391 | */ | ||
| 239 | int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) | 392 | int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) |
| 240 | { | 393 | { |
| 241 | int r; | 394 | int r; |
| @@ -249,15 +402,20 @@ int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsig | |||
| 249 | return 0; | 402 | return 0; |
| 250 | } | 403 | } |
| 251 | 404 | ||
| 405 | /** | ||
| 406 | * radeon_ring_commit - tell the GPU to execute the new | ||
| 407 | * commands on the ring buffer | ||
| 408 | * | ||
| 409 | * @rdev: radeon_device pointer | ||
| 410 | * @ring: radeon_ring structure holding ring information | ||
| 411 | * | ||
| 412 | * Update the wptr (write pointer) to tell the GPU to | ||
| 413 | * execute new commands on the ring buffer (all asics). | ||
| 414 | */ | ||
| 252 | void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) | 415 | void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) |
| 253 | { | 416 | { |
| 254 | unsigned count_dw_pad; | ||
| 255 | unsigned i; | ||
| 256 | |||
| 257 | /* We pad to match fetch size */ | 417 | /* We pad to match fetch size */ |
| 258 | count_dw_pad = (ring->align_mask + 1) - | 418 | while (ring->wptr & ring->align_mask) { |
| 259 | (ring->wptr & ring->align_mask); | ||
| 260 | for (i = 0; i < count_dw_pad; i++) { | ||
| 261 | radeon_ring_write(ring, ring->nop); | 419 | radeon_ring_write(ring, ring->nop); |
| 262 | } | 420 | } |
| 263 | DRM_MEMORYBARRIER(); | 421 | DRM_MEMORYBARRIER(); |
| @@ -265,23 +423,55 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 265 | (void)RREG32(ring->wptr_reg); | 423 | (void)RREG32(ring->wptr_reg); |
| 266 | } | 424 | } |
| 267 | 425 | ||
| 426 | /** | ||
| 427 | * radeon_ring_unlock_commit - tell the GPU to execute the new | ||
| 428 | * commands on the ring buffer and unlock it | ||
| 429 | * | ||
| 430 | * @rdev: radeon_device pointer | ||
| 431 | * @ring: radeon_ring structure holding ring information | ||
| 432 | * | ||
| 433 | * Call radeon_ring_commit() then unlock the ring (all asics). | ||
| 434 | */ | ||
| 268 | void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring) | 435 | void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring) |
| 269 | { | 436 | { |
| 270 | radeon_ring_commit(rdev, ring); | 437 | radeon_ring_commit(rdev, ring); |
| 271 | mutex_unlock(&rdev->ring_lock); | 438 | mutex_unlock(&rdev->ring_lock); |
| 272 | } | 439 | } |
| 273 | 440 | ||
| 441 | /** | ||
| 442 | * radeon_ring_undo - reset the wptr | ||
| 443 | * | ||
| 444 | * @ring: radeon_ring structure holding ring information | ||
| 445 | * | ||
| 446 | * Reset the driver's copy of the wtpr (all asics). | ||
| 447 | */ | ||
| 274 | void radeon_ring_undo(struct radeon_ring *ring) | 448 | void radeon_ring_undo(struct radeon_ring *ring) |
| 275 | { | 449 | { |
| 276 | ring->wptr = ring->wptr_old; | 450 | ring->wptr = ring->wptr_old; |
| 277 | } | 451 | } |
| 278 | 452 | ||
| 453 | /** | ||
| 454 | * radeon_ring_unlock_undo - reset the wptr and unlock the ring | ||
| 455 | * | ||
| 456 | * @ring: radeon_ring structure holding ring information | ||
| 457 | * | ||
| 458 | * Call radeon_ring_undo() then unlock the ring (all asics). | ||
| 459 | */ | ||
| 279 | void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring) | 460 | void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring) |
| 280 | { | 461 | { |
| 281 | radeon_ring_undo(ring); | 462 | radeon_ring_undo(ring); |
| 282 | mutex_unlock(&rdev->ring_lock); | 463 | mutex_unlock(&rdev->ring_lock); |
| 283 | } | 464 | } |
| 284 | 465 | ||
| 466 | /** | ||
| 467 | * radeon_ring_force_activity - add some nop packets to the ring | ||
| 468 | * | ||
| 469 | * @rdev: radeon_device pointer | ||
| 470 | * @ring: radeon_ring structure holding ring information | ||
| 471 | * | ||
| 472 | * Add some nop packets to the ring to force activity (all asics). | ||
| 473 | * Used for lockup detection to see if the rptr is advancing. | ||
| 474 | */ | ||
| 285 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) | 475 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) |
| 286 | { | 476 | { |
| 287 | int r; | 477 | int r; |
| @@ -296,6 +486,13 @@ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring * | |||
| 296 | } | 486 | } |
| 297 | } | 487 | } |
| 298 | 488 | ||
| 489 | /** | ||
| 490 | * radeon_ring_force_activity - update lockup variables | ||
| 491 | * | ||
| 492 | * @ring: radeon_ring structure holding ring information | ||
| 493 | * | ||
| 494 | * Update the last rptr value and timestamp (all asics). | ||
| 495 | */ | ||
| 299 | void radeon_ring_lockup_update(struct radeon_ring *ring) | 496 | void radeon_ring_lockup_update(struct radeon_ring *ring) |
| 300 | { | 497 | { |
| 301 | ring->last_rptr = ring->rptr; | 498 | ring->last_rptr = ring->rptr; |
| @@ -349,6 +546,116 @@ bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *rin | |||
| 349 | return false; | 546 | return false; |
| 350 | } | 547 | } |
| 351 | 548 | ||
| 549 | /** | ||
| 550 | * radeon_ring_backup - Back up the content of a ring | ||
| 551 | * | ||
| 552 | * @rdev: radeon_device pointer | ||
| 553 | * @ring: the ring we want to back up | ||
| 554 | * | ||
| 555 | * Saves all unprocessed commits from a ring, returns the number of dwords saved. | ||
| 556 | */ | ||
| 557 | unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, | ||
| 558 | uint32_t **data) | ||
| 559 | { | ||
| 560 | unsigned size, ptr, i; | ||
| 561 | |||
| 562 | /* just in case lock the ring */ | ||
| 563 | mutex_lock(&rdev->ring_lock); | ||
| 564 | *data = NULL; | ||
| 565 | |||
| 566 | if (ring->ring_obj == NULL) { | ||
| 567 | mutex_unlock(&rdev->ring_lock); | ||
| 568 | return 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | /* it doesn't make sense to save anything if all fences are signaled */ | ||
| 572 | if (!radeon_fence_count_emitted(rdev, ring->idx)) { | ||
| 573 | mutex_unlock(&rdev->ring_lock); | ||
| 574 | return 0; | ||
| 575 | } | ||
| 576 | |||
| 577 | /* calculate the number of dw on the ring */ | ||
| 578 | if (ring->rptr_save_reg) | ||
| 579 | ptr = RREG32(ring->rptr_save_reg); | ||
| 580 | else if (rdev->wb.enabled) | ||
| 581 | ptr = le32_to_cpu(*ring->next_rptr_cpu_addr); | ||
| 582 | else { | ||
| 583 | /* no way to read back the next rptr */ | ||
| 584 | mutex_unlock(&rdev->ring_lock); | ||
| 585 | return 0; | ||
| 586 | } | ||
| 587 | |||
| 588 | size = ring->wptr + (ring->ring_size / 4); | ||
| 589 | size -= ptr; | ||
| 590 | size &= ring->ptr_mask; | ||
| 591 | if (size == 0) { | ||
| 592 | mutex_unlock(&rdev->ring_lock); | ||
| 593 | return 0; | ||
| 594 | } | ||
| 595 | |||
| 596 | /* and then save the content of the ring */ | ||
| 597 | *data = kmalloc_array(size, sizeof(uint32_t), GFP_KERNEL); | ||
| 598 | if (!*data) { | ||
| 599 | mutex_unlock(&rdev->ring_lock); | ||
| 600 | return 0; | ||
| 601 | } | ||
| 602 | for (i = 0; i < size; ++i) { | ||
| 603 | (*data)[i] = ring->ring[ptr++]; | ||
| 604 | ptr &= ring->ptr_mask; | ||
| 605 | } | ||
| 606 | |||
| 607 | mutex_unlock(&rdev->ring_lock); | ||
| 608 | return size; | ||
| 609 | } | ||
| 610 | |||
| 611 | /** | ||
| 612 | * radeon_ring_restore - append saved commands to the ring again | ||
| 613 | * | ||
| 614 | * @rdev: radeon_device pointer | ||
| 615 | * @ring: ring to append commands to | ||
| 616 | * @size: number of dwords we want to write | ||
| 617 | * @data: saved commands | ||
| 618 | * | ||
| 619 | * Allocates space on the ring and restore the previously saved commands. | ||
| 620 | */ | ||
| 621 | int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, | ||
| 622 | unsigned size, uint32_t *data) | ||
| 623 | { | ||
| 624 | int i, r; | ||
| 625 | |||
| 626 | if (!size || !data) | ||
| 627 | return 0; | ||
| 628 | |||
| 629 | /* restore the saved ring content */ | ||
| 630 | r = radeon_ring_lock(rdev, ring, size); | ||
| 631 | if (r) | ||
| 632 | return r; | ||
| 633 | |||
| 634 | for (i = 0; i < size; ++i) { | ||
| 635 | radeon_ring_write(ring, data[i]); | ||
| 636 | } | ||
| 637 | |||
| 638 | radeon_ring_unlock_commit(rdev, ring); | ||
| 639 | kfree(data); | ||
| 640 | return 0; | ||
| 641 | } | ||
| 642 | |||
| 643 | /** | ||
| 644 | * radeon_ring_init - init driver ring struct. | ||
| 645 | * | ||
| 646 | * @rdev: radeon_device pointer | ||
| 647 | * @ring: radeon_ring structure holding ring information | ||
| 648 | * @ring_size: size of the ring | ||
| 649 | * @rptr_offs: offset of the rptr writeback location in the WB buffer | ||
| 650 | * @rptr_reg: MMIO offset of the rptr register | ||
| 651 | * @wptr_reg: MMIO offset of the wptr register | ||
| 652 | * @ptr_reg_shift: bit offset of the rptr/wptr values | ||
| 653 | * @ptr_reg_mask: bit mask of the rptr/wptr values | ||
| 654 | * @nop: nop packet for this ring | ||
| 655 | * | ||
| 656 | * Initialize the driver information for the selected ring (all asics). | ||
| 657 | * Returns 0 on success, error on failure. | ||
| 658 | */ | ||
| 352 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, | 659 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, |
| 353 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, | 660 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, |
| 354 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) | 661 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) |
| @@ -391,12 +698,25 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig | |||
| 391 | } | 698 | } |
| 392 | ring->ptr_mask = (ring->ring_size / 4) - 1; | 699 | ring->ptr_mask = (ring->ring_size / 4) - 1; |
| 393 | ring->ring_free_dw = ring->ring_size / 4; | 700 | ring->ring_free_dw = ring->ring_size / 4; |
| 701 | if (rdev->wb.enabled) { | ||
| 702 | u32 index = RADEON_WB_RING0_NEXT_RPTR + (ring->idx * 4); | ||
| 703 | ring->next_rptr_gpu_addr = rdev->wb.gpu_addr + index; | ||
| 704 | ring->next_rptr_cpu_addr = &rdev->wb.wb[index/4]; | ||
| 705 | } | ||
| 394 | if (radeon_debugfs_ring_init(rdev, ring)) { | 706 | if (radeon_debugfs_ring_init(rdev, ring)) { |
| 395 | DRM_ERROR("Failed to register debugfs file for rings !\n"); | 707 | DRM_ERROR("Failed to register debugfs file for rings !\n"); |
| 396 | } | 708 | } |
| 397 | return 0; | 709 | return 0; |
| 398 | } | 710 | } |
| 399 | 711 | ||
| 712 | /** | ||
| 713 | * radeon_ring_fini - tear down the driver ring struct. | ||
| 714 | * | ||
| 715 | * @rdev: radeon_device pointer | ||
| 716 | * @ring: radeon_ring structure holding ring information | ||
| 717 | * | ||
| 718 | * Tear down the driver information for the selected ring (all asics). | ||
| 719 | */ | ||
| 400 | void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring) | 720 | void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring) |
| 401 | { | 721 | { |
| 402 | int r; | 722 | int r; |
| @@ -438,6 +758,10 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) | |||
| 438 | count = (ring->ring_size / 4) - ring->ring_free_dw; | 758 | count = (ring->ring_size / 4) - ring->ring_free_dw; |
| 439 | seq_printf(m, "wptr(0x%04x): 0x%08x\n", ring->wptr_reg, RREG32(ring->wptr_reg)); | 759 | seq_printf(m, "wptr(0x%04x): 0x%08x\n", ring->wptr_reg, RREG32(ring->wptr_reg)); |
| 440 | seq_printf(m, "rptr(0x%04x): 0x%08x\n", ring->rptr_reg, RREG32(ring->rptr_reg)); | 760 | seq_printf(m, "rptr(0x%04x): 0x%08x\n", ring->rptr_reg, RREG32(ring->rptr_reg)); |
| 761 | if (ring->rptr_save_reg) { | ||
| 762 | seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg, | ||
| 763 | RREG32(ring->rptr_save_reg)); | ||
| 764 | } | ||
| 441 | seq_printf(m, "driver's copy of the wptr: 0x%08x\n", ring->wptr); | 765 | seq_printf(m, "driver's copy of the wptr: 0x%08x\n", ring->wptr); |
| 442 | seq_printf(m, "driver's copy of the rptr: 0x%08x\n", ring->rptr); | 766 | seq_printf(m, "driver's copy of the rptr: 0x%08x\n", ring->rptr); |
| 443 | seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); | 767 | seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); |
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c index 32059b745728..4e771240fdd0 100644 --- a/drivers/gpu/drm/radeon/radeon_sa.c +++ b/drivers/gpu/drm/radeon/radeon_sa.c | |||
| @@ -54,7 +54,7 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev, | |||
| 54 | { | 54 | { |
| 55 | int i, r; | 55 | int i, r; |
| 56 | 56 | ||
| 57 | spin_lock_init(&sa_manager->lock); | 57 | init_waitqueue_head(&sa_manager->wq); |
| 58 | sa_manager->bo = NULL; | 58 | sa_manager->bo = NULL; |
| 59 | sa_manager->size = size; | 59 | sa_manager->size = size; |
| 60 | sa_manager->domain = domain; | 60 | sa_manager->domain = domain; |
| @@ -211,6 +211,39 @@ static bool radeon_sa_bo_try_alloc(struct radeon_sa_manager *sa_manager, | |||
| 211 | return false; | 211 | return false; |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | /** | ||
| 215 | * radeon_sa_event - Check if we can stop waiting | ||
| 216 | * | ||
| 217 | * @sa_manager: pointer to the sa_manager | ||
| 218 | * @size: number of bytes we want to allocate | ||
| 219 | * @align: alignment we need to match | ||
| 220 | * | ||
| 221 | * Check if either there is a fence we can wait for or | ||
| 222 | * enough free memory to satisfy the allocation directly | ||
| 223 | */ | ||
| 224 | static bool radeon_sa_event(struct radeon_sa_manager *sa_manager, | ||
| 225 | unsigned size, unsigned align) | ||
| 226 | { | ||
| 227 | unsigned soffset, eoffset, wasted; | ||
| 228 | int i; | ||
| 229 | |||
| 230 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 231 | if (!list_empty(&sa_manager->flist[i])) { | ||
| 232 | return true; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | soffset = radeon_sa_bo_hole_soffset(sa_manager); | ||
| 237 | eoffset = radeon_sa_bo_hole_eoffset(sa_manager); | ||
| 238 | wasted = (align - (soffset % align)) % align; | ||
| 239 | |||
| 240 | if ((eoffset - soffset) >= (size + wasted)) { | ||
| 241 | return true; | ||
| 242 | } | ||
| 243 | |||
| 244 | return false; | ||
| 245 | } | ||
| 246 | |||
| 214 | static bool radeon_sa_bo_next_hole(struct radeon_sa_manager *sa_manager, | 247 | static bool radeon_sa_bo_next_hole(struct radeon_sa_manager *sa_manager, |
| 215 | struct radeon_fence **fences, | 248 | struct radeon_fence **fences, |
| 216 | unsigned *tries) | 249 | unsigned *tries) |
| @@ -297,8 +330,8 @@ int radeon_sa_bo_new(struct radeon_device *rdev, | |||
| 297 | INIT_LIST_HEAD(&(*sa_bo)->olist); | 330 | INIT_LIST_HEAD(&(*sa_bo)->olist); |
| 298 | INIT_LIST_HEAD(&(*sa_bo)->flist); | 331 | INIT_LIST_HEAD(&(*sa_bo)->flist); |
| 299 | 332 | ||
| 300 | spin_lock(&sa_manager->lock); | 333 | spin_lock(&sa_manager->wq.lock); |
| 301 | do { | 334 | while(1) { |
| 302 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 335 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
| 303 | fences[i] = NULL; | 336 | fences[i] = NULL; |
| 304 | tries[i] = 0; | 337 | tries[i] = 0; |
| @@ -309,30 +342,34 @@ int radeon_sa_bo_new(struct radeon_device *rdev, | |||
| 309 | 342 | ||
| 310 | if (radeon_sa_bo_try_alloc(sa_manager, *sa_bo, | 343 | if (radeon_sa_bo_try_alloc(sa_manager, *sa_bo, |
| 311 | size, align)) { | 344 | size, align)) { |
| 312 | spin_unlock(&sa_manager->lock); | 345 | spin_unlock(&sa_manager->wq.lock); |
| 313 | return 0; | 346 | return 0; |
| 314 | } | 347 | } |
| 315 | 348 | ||
| 316 | /* see if we can skip over some allocations */ | 349 | /* see if we can skip over some allocations */ |
| 317 | } while (radeon_sa_bo_next_hole(sa_manager, fences, tries)); | 350 | } while (radeon_sa_bo_next_hole(sa_manager, fences, tries)); |
| 318 | 351 | ||
| 319 | if (block) { | 352 | if (!block) { |
| 320 | spin_unlock(&sa_manager->lock); | 353 | break; |
| 321 | r = radeon_fence_wait_any(rdev, fences, false); | 354 | } |
| 322 | spin_lock(&sa_manager->lock); | 355 | |
| 323 | if (r) { | 356 | spin_unlock(&sa_manager->wq.lock); |
| 324 | /* if we have nothing to wait for we | 357 | r = radeon_fence_wait_any(rdev, fences, false); |
| 325 | are practically out of memory */ | 358 | spin_lock(&sa_manager->wq.lock); |
| 326 | if (r == -ENOENT) { | 359 | /* if we have nothing to wait for block */ |
| 327 | r = -ENOMEM; | 360 | if (r == -ENOENT) { |
| 328 | } | 361 | r = wait_event_interruptible_locked( |
| 329 | goto out_err; | 362 | sa_manager->wq, |
| 330 | } | 363 | radeon_sa_event(sa_manager, size, align) |
| 364 | ); | ||
| 365 | } | ||
| 366 | if (r) { | ||
| 367 | goto out_err; | ||
| 331 | } | 368 | } |
| 332 | } while (block); | 369 | }; |
| 333 | 370 | ||
| 334 | out_err: | 371 | out_err: |
| 335 | spin_unlock(&sa_manager->lock); | 372 | spin_unlock(&sa_manager->wq.lock); |
| 336 | kfree(*sa_bo); | 373 | kfree(*sa_bo); |
| 337 | *sa_bo = NULL; | 374 | *sa_bo = NULL; |
| 338 | return r; | 375 | return r; |
| @@ -348,15 +385,16 @@ void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo, | |||
| 348 | } | 385 | } |
| 349 | 386 | ||
| 350 | sa_manager = (*sa_bo)->manager; | 387 | sa_manager = (*sa_bo)->manager; |
| 351 | spin_lock(&sa_manager->lock); | 388 | spin_lock(&sa_manager->wq.lock); |
| 352 | if (fence && fence->seq && fence->seq < RADEON_FENCE_NOTEMITED_SEQ) { | 389 | if (fence && !radeon_fence_signaled(fence)) { |
| 353 | (*sa_bo)->fence = radeon_fence_ref(fence); | 390 | (*sa_bo)->fence = radeon_fence_ref(fence); |
| 354 | list_add_tail(&(*sa_bo)->flist, | 391 | list_add_tail(&(*sa_bo)->flist, |
| 355 | &sa_manager->flist[fence->ring]); | 392 | &sa_manager->flist[fence->ring]); |
| 356 | } else { | 393 | } else { |
| 357 | radeon_sa_bo_remove_locked(*sa_bo); | 394 | radeon_sa_bo_remove_locked(*sa_bo); |
| 358 | } | 395 | } |
| 359 | spin_unlock(&sa_manager->lock); | 396 | wake_up_all_locked(&sa_manager->wq); |
| 397 | spin_unlock(&sa_manager->wq.lock); | ||
| 360 | *sa_bo = NULL; | 398 | *sa_bo = NULL; |
| 361 | } | 399 | } |
| 362 | 400 | ||
| @@ -366,7 +404,7 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, | |||
| 366 | { | 404 | { |
| 367 | struct radeon_sa_bo *i; | 405 | struct radeon_sa_bo *i; |
| 368 | 406 | ||
| 369 | spin_lock(&sa_manager->lock); | 407 | spin_lock(&sa_manager->wq.lock); |
| 370 | list_for_each_entry(i, &sa_manager->olist, olist) { | 408 | list_for_each_entry(i, &sa_manager->olist, olist) { |
| 371 | if (&i->olist == sa_manager->hole) { | 409 | if (&i->olist == sa_manager->hole) { |
| 372 | seq_printf(m, ">"); | 410 | seq_printf(m, ">"); |
| @@ -381,6 +419,6 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, | |||
| 381 | } | 419 | } |
| 382 | seq_printf(m, "\n"); | 420 | seq_printf(m, "\n"); |
| 383 | } | 421 | } |
| 384 | spin_unlock(&sa_manager->lock); | 422 | spin_unlock(&sa_manager->wq.lock); |
| 385 | } | 423 | } |
| 386 | #endif | 424 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index e2ace5dce117..7cc78de6ddc3 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c | |||
| @@ -68,70 +68,49 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, | |||
| 68 | radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); | 68 | radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | /* caller must hold ring lock */ | ||
| 71 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, | 72 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, |
| 72 | struct radeon_semaphore *semaphore, | 73 | struct radeon_semaphore *semaphore, |
| 73 | bool sync_to[RADEON_NUM_RINGS], | 74 | int signaler, int waiter) |
| 74 | int dst_ring) | ||
| 75 | { | 75 | { |
| 76 | int i = 0, r; | 76 | int r; |
| 77 | 77 | ||
| 78 | mutex_lock(&rdev->ring_lock); | 78 | /* no need to signal and wait on the same ring */ |
| 79 | r = radeon_ring_alloc(rdev, &rdev->ring[dst_ring], RADEON_NUM_RINGS * 8); | 79 | if (signaler == waiter) { |
| 80 | if (r) { | 80 | return 0; |
| 81 | goto error; | ||
| 82 | } | 81 | } |
| 83 | 82 | ||
| 84 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 83 | /* prevent GPU deadlocks */ |
| 85 | /* no need to sync to our own or unused rings */ | 84 | if (!rdev->ring[signaler].ready) { |
| 86 | if (!sync_to[i] || i == dst_ring) | 85 | dev_err(rdev->dev, "Trying to sync to a disabled ring!"); |
| 87 | continue; | 86 | return -EINVAL; |
| 88 | 87 | } | |
| 89 | /* prevent GPU deadlocks */ | ||
| 90 | if (!rdev->ring[i].ready) { | ||
| 91 | dev_err(rdev->dev, "Trying to sync to a disabled ring!"); | ||
| 92 | r = -EINVAL; | ||
| 93 | goto error; | ||
| 94 | } | ||
| 95 | |||
| 96 | r = radeon_ring_alloc(rdev, &rdev->ring[i], 8); | ||
| 97 | if (r) { | ||
| 98 | goto error; | ||
| 99 | } | ||
| 100 | |||
| 101 | radeon_semaphore_emit_signal(rdev, i, semaphore); | ||
| 102 | radeon_semaphore_emit_wait(rdev, dst_ring, semaphore); | ||
| 103 | 88 | ||
| 104 | radeon_ring_commit(rdev, &rdev->ring[i]); | 89 | r = radeon_ring_alloc(rdev, &rdev->ring[signaler], 8); |
| 90 | if (r) { | ||
| 91 | return r; | ||
| 105 | } | 92 | } |
| 93 | radeon_semaphore_emit_signal(rdev, signaler, semaphore); | ||
| 94 | radeon_ring_commit(rdev, &rdev->ring[signaler]); | ||
| 106 | 95 | ||
| 107 | radeon_ring_commit(rdev, &rdev->ring[dst_ring]); | 96 | /* we assume caller has already allocated space on waiters ring */ |
| 108 | mutex_unlock(&rdev->ring_lock); | 97 | radeon_semaphore_emit_wait(rdev, waiter, semaphore); |
| 109 | 98 | ||
| 110 | return 0; | 99 | return 0; |
| 111 | |||
| 112 | error: | ||
| 113 | /* unlock all locks taken so far */ | ||
| 114 | for (--i; i >= 0; --i) { | ||
| 115 | if (sync_to[i] || i == dst_ring) { | ||
| 116 | radeon_ring_undo(&rdev->ring[i]); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | radeon_ring_undo(&rdev->ring[dst_ring]); | ||
| 120 | mutex_unlock(&rdev->ring_lock); | ||
| 121 | return r; | ||
| 122 | } | 100 | } |
| 123 | 101 | ||
| 124 | void radeon_semaphore_free(struct radeon_device *rdev, | 102 | void radeon_semaphore_free(struct radeon_device *rdev, |
| 125 | struct radeon_semaphore *semaphore, | 103 | struct radeon_semaphore **semaphore, |
| 126 | struct radeon_fence *fence) | 104 | struct radeon_fence *fence) |
| 127 | { | 105 | { |
| 128 | if (semaphore == NULL) { | 106 | if (semaphore == NULL || *semaphore == NULL) { |
| 129 | return; | 107 | return; |
| 130 | } | 108 | } |
| 131 | if (semaphore->waiters > 0) { | 109 | if ((*semaphore)->waiters > 0) { |
| 132 | dev_err(rdev->dev, "semaphore %p has more waiters than signalers," | 110 | dev_err(rdev->dev, "semaphore %p has more waiters than signalers," |
| 133 | " hardware lockup imminent!\n", semaphore); | 111 | " hardware lockup imminent!\n", *semaphore); |
| 134 | } | 112 | } |
| 135 | radeon_sa_bo_free(rdev, &semaphore->sa_bo, fence); | 113 | radeon_sa_bo_free(rdev, &(*semaphore)->sa_bo, fence); |
| 136 | kfree(semaphore); | 114 | kfree(*semaphore); |
| 115 | *semaphore = NULL; | ||
| 137 | } | 116 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index efff929ea49d..7c16540c10ff 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c | |||
| @@ -106,13 +106,7 @@ void radeon_test_moves(struct radeon_device *rdev) | |||
| 106 | 106 | ||
| 107 | radeon_bo_kunmap(gtt_obj[i]); | 107 | radeon_bo_kunmap(gtt_obj[i]); |
| 108 | 108 | ||
| 109 | r = radeon_fence_create(rdev, &fence, RADEON_RING_TYPE_GFX_INDEX); | 109 | r = radeon_copy(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence); |
| 110 | if (r) { | ||
| 111 | DRM_ERROR("Failed to create GTT->VRAM fence %d\n", i); | ||
| 112 | goto out_cleanup; | ||
| 113 | } | ||
| 114 | |||
| 115 | r = radeon_copy(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, fence); | ||
| 116 | if (r) { | 110 | if (r) { |
| 117 | DRM_ERROR("Failed GTT->VRAM copy %d\n", i); | 111 | DRM_ERROR("Failed GTT->VRAM copy %d\n", i); |
| 118 | goto out_cleanup; | 112 | goto out_cleanup; |
| @@ -155,13 +149,7 @@ void radeon_test_moves(struct radeon_device *rdev) | |||
| 155 | 149 | ||
| 156 | radeon_bo_kunmap(vram_obj); | 150 | radeon_bo_kunmap(vram_obj); |
| 157 | 151 | ||
| 158 | r = radeon_fence_create(rdev, &fence, RADEON_RING_TYPE_GFX_INDEX); | 152 | r = radeon_copy(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence); |
| 159 | if (r) { | ||
| 160 | DRM_ERROR("Failed to create VRAM->GTT fence %d\n", i); | ||
| 161 | goto out_cleanup; | ||
| 162 | } | ||
| 163 | |||
| 164 | r = radeon_copy(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, fence); | ||
| 165 | if (r) { | 153 | if (r) { |
| 166 | DRM_ERROR("Failed VRAM->GTT copy %d\n", i); | 154 | DRM_ERROR("Failed VRAM->GTT copy %d\n", i); |
| 167 | goto out_cleanup; | 155 | goto out_cleanup; |
| @@ -241,36 +229,33 @@ void radeon_test_ring_sync(struct radeon_device *rdev, | |||
| 241 | { | 229 | { |
| 242 | struct radeon_fence *fence1 = NULL, *fence2 = NULL; | 230 | struct radeon_fence *fence1 = NULL, *fence2 = NULL; |
| 243 | struct radeon_semaphore *semaphore = NULL; | 231 | struct radeon_semaphore *semaphore = NULL; |
| 244 | int ridxA = radeon_ring_index(rdev, ringA); | ||
| 245 | int ridxB = radeon_ring_index(rdev, ringB); | ||
| 246 | int r; | 232 | int r; |
| 247 | 233 | ||
| 248 | r = radeon_fence_create(rdev, &fence1, ridxA); | 234 | r = radeon_semaphore_create(rdev, &semaphore); |
| 249 | if (r) { | 235 | if (r) { |
| 250 | DRM_ERROR("Failed to create sync fence 1\n"); | 236 | DRM_ERROR("Failed to create semaphore\n"); |
| 251 | goto out_cleanup; | 237 | goto out_cleanup; |
| 252 | } | 238 | } |
| 253 | r = radeon_fence_create(rdev, &fence2, ridxA); | 239 | |
| 240 | r = radeon_ring_lock(rdev, ringA, 64); | ||
| 254 | if (r) { | 241 | if (r) { |
| 255 | DRM_ERROR("Failed to create sync fence 2\n"); | 242 | DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); |
| 256 | goto out_cleanup; | 243 | goto out_cleanup; |
| 257 | } | 244 | } |
| 258 | 245 | radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); | |
| 259 | r = radeon_semaphore_create(rdev, &semaphore); | 246 | r = radeon_fence_emit(rdev, &fence1, ringA->idx); |
| 260 | if (r) { | 247 | if (r) { |
| 261 | DRM_ERROR("Failed to create semaphore\n"); | 248 | DRM_ERROR("Failed to emit fence 1\n"); |
| 249 | radeon_ring_unlock_undo(rdev, ringA); | ||
| 262 | goto out_cleanup; | 250 | goto out_cleanup; |
| 263 | } | 251 | } |
| 264 | 252 | radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); | |
| 265 | r = radeon_ring_lock(rdev, ringA, 64); | 253 | r = radeon_fence_emit(rdev, &fence2, ringA->idx); |
| 266 | if (r) { | 254 | if (r) { |
| 267 | DRM_ERROR("Failed to lock ring A %d\n", ridxA); | 255 | DRM_ERROR("Failed to emit fence 2\n"); |
| 256 | radeon_ring_unlock_undo(rdev, ringA); | ||
| 268 | goto out_cleanup; | 257 | goto out_cleanup; |
| 269 | } | 258 | } |
| 270 | radeon_semaphore_emit_wait(rdev, ridxA, semaphore); | ||
| 271 | radeon_fence_emit(rdev, fence1); | ||
| 272 | radeon_semaphore_emit_wait(rdev, ridxA, semaphore); | ||
| 273 | radeon_fence_emit(rdev, fence2); | ||
| 274 | radeon_ring_unlock_commit(rdev, ringA); | 259 | radeon_ring_unlock_commit(rdev, ringA); |
| 275 | 260 | ||
| 276 | mdelay(1000); | 261 | mdelay(1000); |
| @@ -285,7 +270,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev, | |||
| 285 | DRM_ERROR("Failed to lock ring B %p\n", ringB); | 270 | DRM_ERROR("Failed to lock ring B %p\n", ringB); |
| 286 | goto out_cleanup; | 271 | goto out_cleanup; |
| 287 | } | 272 | } |
| 288 | radeon_semaphore_emit_signal(rdev, ridxB, semaphore); | 273 | radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); |
| 289 | radeon_ring_unlock_commit(rdev, ringB); | 274 | radeon_ring_unlock_commit(rdev, ringB); |
| 290 | 275 | ||
| 291 | r = radeon_fence_wait(fence1, false); | 276 | r = radeon_fence_wait(fence1, false); |
| @@ -306,7 +291,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev, | |||
| 306 | DRM_ERROR("Failed to lock ring B %p\n", ringB); | 291 | DRM_ERROR("Failed to lock ring B %p\n", ringB); |
| 307 | goto out_cleanup; | 292 | goto out_cleanup; |
| 308 | } | 293 | } |
| 309 | radeon_semaphore_emit_signal(rdev, ridxB, semaphore); | 294 | radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); |
| 310 | radeon_ring_unlock_commit(rdev, ringB); | 295 | radeon_ring_unlock_commit(rdev, ringB); |
| 311 | 296 | ||
| 312 | r = radeon_fence_wait(fence2, false); | 297 | r = radeon_fence_wait(fence2, false); |
| @@ -316,8 +301,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev, | |||
| 316 | } | 301 | } |
| 317 | 302 | ||
| 318 | out_cleanup: | 303 | out_cleanup: |
| 319 | if (semaphore) | 304 | radeon_semaphore_free(rdev, &semaphore, NULL); |
| 320 | radeon_semaphore_free(rdev, semaphore, NULL); | ||
| 321 | 305 | ||
| 322 | if (fence1) | 306 | if (fence1) |
| 323 | radeon_fence_unref(&fence1); | 307 | radeon_fence_unref(&fence1); |
| @@ -336,23 +320,9 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, | |||
| 336 | { | 320 | { |
| 337 | struct radeon_fence *fenceA = NULL, *fenceB = NULL; | 321 | struct radeon_fence *fenceA = NULL, *fenceB = NULL; |
| 338 | struct radeon_semaphore *semaphore = NULL; | 322 | struct radeon_semaphore *semaphore = NULL; |
| 339 | int ridxA = radeon_ring_index(rdev, ringA); | ||
| 340 | int ridxB = radeon_ring_index(rdev, ringB); | ||
| 341 | int ridxC = radeon_ring_index(rdev, ringC); | ||
| 342 | bool sigA, sigB; | 323 | bool sigA, sigB; |
| 343 | int i, r; | 324 | int i, r; |
| 344 | 325 | ||
| 345 | r = radeon_fence_create(rdev, &fenceA, ridxA); | ||
| 346 | if (r) { | ||
| 347 | DRM_ERROR("Failed to create sync fence 1\n"); | ||
| 348 | goto out_cleanup; | ||
| 349 | } | ||
| 350 | r = radeon_fence_create(rdev, &fenceB, ridxB); | ||
| 351 | if (r) { | ||
| 352 | DRM_ERROR("Failed to create sync fence 2\n"); | ||
| 353 | goto out_cleanup; | ||
| 354 | } | ||
| 355 | |||
| 356 | r = radeon_semaphore_create(rdev, &semaphore); | 326 | r = radeon_semaphore_create(rdev, &semaphore); |
| 357 | if (r) { | 327 | if (r) { |
| 358 | DRM_ERROR("Failed to create semaphore\n"); | 328 | DRM_ERROR("Failed to create semaphore\n"); |
| @@ -361,20 +331,30 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, | |||
| 361 | 331 | ||
| 362 | r = radeon_ring_lock(rdev, ringA, 64); | 332 | r = radeon_ring_lock(rdev, ringA, 64); |
| 363 | if (r) { | 333 | if (r) { |
| 364 | DRM_ERROR("Failed to lock ring A %d\n", ridxA); | 334 | DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); |
| 335 | goto out_cleanup; | ||
| 336 | } | ||
| 337 | radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); | ||
| 338 | r = radeon_fence_emit(rdev, &fenceA, ringA->idx); | ||
| 339 | if (r) { | ||
| 340 | DRM_ERROR("Failed to emit sync fence 1\n"); | ||
| 341 | radeon_ring_unlock_undo(rdev, ringA); | ||
| 365 | goto out_cleanup; | 342 | goto out_cleanup; |
| 366 | } | 343 | } |
| 367 | radeon_semaphore_emit_wait(rdev, ridxA, semaphore); | ||
| 368 | radeon_fence_emit(rdev, fenceA); | ||
| 369 | radeon_ring_unlock_commit(rdev, ringA); | 344 | radeon_ring_unlock_commit(rdev, ringA); |
| 370 | 345 | ||
| 371 | r = radeon_ring_lock(rdev, ringB, 64); | 346 | r = radeon_ring_lock(rdev, ringB, 64); |
| 372 | if (r) { | 347 | if (r) { |
| 373 | DRM_ERROR("Failed to lock ring B %d\n", ridxB); | 348 | DRM_ERROR("Failed to lock ring B %d\n", ringB->idx); |
| 349 | goto out_cleanup; | ||
| 350 | } | ||
| 351 | radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore); | ||
| 352 | r = radeon_fence_emit(rdev, &fenceB, ringB->idx); | ||
| 353 | if (r) { | ||
| 354 | DRM_ERROR("Failed to create sync fence 2\n"); | ||
| 355 | radeon_ring_unlock_undo(rdev, ringB); | ||
| 374 | goto out_cleanup; | 356 | goto out_cleanup; |
| 375 | } | 357 | } |
| 376 | radeon_semaphore_emit_wait(rdev, ridxB, semaphore); | ||
| 377 | radeon_fence_emit(rdev, fenceB); | ||
| 378 | radeon_ring_unlock_commit(rdev, ringB); | 358 | radeon_ring_unlock_commit(rdev, ringB); |
| 379 | 359 | ||
| 380 | mdelay(1000); | 360 | mdelay(1000); |
| @@ -393,7 +373,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, | |||
| 393 | DRM_ERROR("Failed to lock ring B %p\n", ringC); | 373 | DRM_ERROR("Failed to lock ring B %p\n", ringC); |
| 394 | goto out_cleanup; | 374 | goto out_cleanup; |
| 395 | } | 375 | } |
| 396 | radeon_semaphore_emit_signal(rdev, ridxC, semaphore); | 376 | radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); |
| 397 | radeon_ring_unlock_commit(rdev, ringC); | 377 | radeon_ring_unlock_commit(rdev, ringC); |
| 398 | 378 | ||
| 399 | for (i = 0; i < 30; ++i) { | 379 | for (i = 0; i < 30; ++i) { |
| @@ -419,7 +399,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, | |||
| 419 | DRM_ERROR("Failed to lock ring B %p\n", ringC); | 399 | DRM_ERROR("Failed to lock ring B %p\n", ringC); |
| 420 | goto out_cleanup; | 400 | goto out_cleanup; |
| 421 | } | 401 | } |
| 422 | radeon_semaphore_emit_signal(rdev, ridxC, semaphore); | 402 | radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); |
| 423 | radeon_ring_unlock_commit(rdev, ringC); | 403 | radeon_ring_unlock_commit(rdev, ringC); |
| 424 | 404 | ||
| 425 | mdelay(1000); | 405 | mdelay(1000); |
| @@ -436,8 +416,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, | |||
| 436 | } | 416 | } |
| 437 | 417 | ||
| 438 | out_cleanup: | 418 | out_cleanup: |
| 439 | if (semaphore) | 419 | radeon_semaphore_free(rdev, &semaphore, NULL); |
| 440 | radeon_semaphore_free(rdev, semaphore, NULL); | ||
| 441 | 420 | ||
| 442 | if (fenceA) | 421 | if (fenceA) |
| 443 | radeon_fence_unref(&fenceA); | 422 | radeon_fence_unref(&fenceA); |
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index c94a2257761f..5b71c716d83f 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c | |||
| @@ -222,15 +222,11 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, | |||
| 222 | { | 222 | { |
| 223 | struct radeon_device *rdev; | 223 | struct radeon_device *rdev; |
| 224 | uint64_t old_start, new_start; | 224 | uint64_t old_start, new_start; |
| 225 | struct radeon_fence *fence, *old_fence; | 225 | struct radeon_fence *fence; |
| 226 | struct radeon_semaphore *sem = NULL; | 226 | int r, ridx; |
| 227 | int r; | ||
| 228 | 227 | ||
| 229 | rdev = radeon_get_rdev(bo->bdev); | 228 | rdev = radeon_get_rdev(bo->bdev); |
| 230 | r = radeon_fence_create(rdev, &fence, radeon_copy_ring_index(rdev)); | 229 | ridx = radeon_copy_ring_index(rdev); |
| 231 | if (unlikely(r)) { | ||
| 232 | return r; | ||
| 233 | } | ||
| 234 | old_start = old_mem->start << PAGE_SHIFT; | 230 | old_start = old_mem->start << PAGE_SHIFT; |
| 235 | new_start = new_mem->start << PAGE_SHIFT; | 231 | new_start = new_mem->start << PAGE_SHIFT; |
| 236 | 232 | ||
| @@ -243,7 +239,6 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, | |||
| 243 | break; | 239 | break; |
| 244 | default: | 240 | default: |
| 245 | DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); | 241 | DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); |
| 246 | radeon_fence_unref(&fence); | ||
| 247 | return -EINVAL; | 242 | return -EINVAL; |
| 248 | } | 243 | } |
| 249 | switch (new_mem->mem_type) { | 244 | switch (new_mem->mem_type) { |
| @@ -255,46 +250,23 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, | |||
| 255 | break; | 250 | break; |
| 256 | default: | 251 | default: |
| 257 | DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); | 252 | DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); |
| 258 | radeon_fence_unref(&fence); | ||
| 259 | return -EINVAL; | 253 | return -EINVAL; |
| 260 | } | 254 | } |
| 261 | if (!rdev->ring[radeon_copy_ring_index(rdev)].ready) { | 255 | if (!rdev->ring[ridx].ready) { |
| 262 | DRM_ERROR("Trying to move memory with ring turned off.\n"); | 256 | DRM_ERROR("Trying to move memory with ring turned off.\n"); |
| 263 | radeon_fence_unref(&fence); | ||
| 264 | return -EINVAL; | 257 | return -EINVAL; |
| 265 | } | 258 | } |
| 266 | 259 | ||
| 267 | BUILD_BUG_ON((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) != 0); | 260 | BUILD_BUG_ON((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) != 0); |
| 268 | 261 | ||
| 269 | /* sync other rings */ | 262 | /* sync other rings */ |
| 270 | old_fence = bo->sync_obj; | 263 | fence = bo->sync_obj; |
| 271 | if (old_fence && old_fence->ring != fence->ring | ||
| 272 | && !radeon_fence_signaled(old_fence)) { | ||
| 273 | bool sync_to_ring[RADEON_NUM_RINGS] = { }; | ||
| 274 | sync_to_ring[old_fence->ring] = true; | ||
| 275 | |||
| 276 | r = radeon_semaphore_create(rdev, &sem); | ||
| 277 | if (r) { | ||
| 278 | radeon_fence_unref(&fence); | ||
| 279 | return r; | ||
| 280 | } | ||
| 281 | |||
| 282 | r = radeon_semaphore_sync_rings(rdev, sem, | ||
| 283 | sync_to_ring, fence->ring); | ||
| 284 | if (r) { | ||
| 285 | radeon_semaphore_free(rdev, sem, NULL); | ||
| 286 | radeon_fence_unref(&fence); | ||
| 287 | return r; | ||
| 288 | } | ||
| 289 | } | ||
| 290 | |||
| 291 | r = radeon_copy(rdev, old_start, new_start, | 264 | r = radeon_copy(rdev, old_start, new_start, |
| 292 | new_mem->num_pages * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE), /* GPU pages */ | 265 | new_mem->num_pages * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE), /* GPU pages */ |
| 293 | fence); | 266 | &fence); |
| 294 | /* FIXME: handle copy error */ | 267 | /* FIXME: handle copy error */ |
| 295 | r = ttm_bo_move_accel_cleanup(bo, (void *)fence, NULL, | 268 | r = ttm_bo_move_accel_cleanup(bo, (void *)fence, NULL, |
| 296 | evict, no_wait_reserve, no_wait_gpu, new_mem); | 269 | evict, no_wait_reserve, no_wait_gpu, new_mem); |
| 297 | radeon_semaphore_free(rdev, sem, fence); | ||
| 298 | radeon_fence_unref(&fence); | 270 | radeon_fence_unref(&fence); |
| 299 | return r; | 271 | return r; |
| 300 | } | 272 | } |
| @@ -762,9 +734,7 @@ int radeon_ttm_init(struct radeon_device *rdev) | |||
| 762 | } | 734 | } |
| 763 | DRM_INFO("radeon: %uM of GTT memory ready.\n", | 735 | DRM_INFO("radeon: %uM of GTT memory ready.\n", |
| 764 | (unsigned)(rdev->mc.gtt_size / (1024 * 1024))); | 736 | (unsigned)(rdev->mc.gtt_size / (1024 * 1024))); |
| 765 | if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { | 737 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; |
| 766 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; | ||
| 767 | } | ||
| 768 | 738 | ||
| 769 | r = radeon_ttm_debugfs_init(rdev); | 739 | r = radeon_ttm_debugfs_init(rdev); |
| 770 | if (r) { | 740 | if (r) { |
| @@ -825,9 +795,9 @@ static int radeon_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 825 | return VM_FAULT_NOPAGE; | 795 | return VM_FAULT_NOPAGE; |
| 826 | } | 796 | } |
| 827 | rdev = radeon_get_rdev(bo->bdev); | 797 | rdev = radeon_get_rdev(bo->bdev); |
| 828 | mutex_lock(&rdev->vram_mutex); | 798 | down_read(&rdev->pm.mclk_lock); |
| 829 | r = ttm_vm_ops->fault(vma, vmf); | 799 | r = ttm_vm_ops->fault(vma, vmf); |
| 830 | mutex_unlock(&rdev->vram_mutex); | 800 | up_read(&rdev->pm.mclk_lock); |
| 831 | return r; | 801 | return r; |
| 832 | } | 802 | } |
| 833 | 803 | ||
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index a464eb5e2df2..2752f7f78237 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c | |||
| @@ -426,13 +426,11 @@ static int rs400_startup(struct radeon_device *rdev) | |||
| 426 | return r; | 426 | return r; |
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | r = radeon_ib_pool_start(rdev); | 429 | r = radeon_ib_pool_init(rdev); |
| 430 | if (r) | 430 | if (r) { |
| 431 | return r; | 431 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 432 | |||
| 433 | r = radeon_ib_ring_tests(rdev); | ||
| 434 | if (r) | ||
| 435 | return r; | 432 | return r; |
| 433 | } | ||
| 436 | 434 | ||
| 437 | return 0; | 435 | return 0; |
| 438 | } | 436 | } |
| @@ -470,7 +468,6 @@ int rs400_resume(struct radeon_device *rdev) | |||
| 470 | 468 | ||
| 471 | int rs400_suspend(struct radeon_device *rdev) | 469 | int rs400_suspend(struct radeon_device *rdev) |
| 472 | { | 470 | { |
| 473 | radeon_ib_pool_suspend(rdev); | ||
| 474 | r100_cp_disable(rdev); | 471 | r100_cp_disable(rdev); |
| 475 | radeon_wb_disable(rdev); | 472 | radeon_wb_disable(rdev); |
| 476 | r100_irq_disable(rdev); | 473 | r100_irq_disable(rdev); |
| @@ -482,7 +479,7 @@ void rs400_fini(struct radeon_device *rdev) | |||
| 482 | { | 479 | { |
| 483 | r100_cp_fini(rdev); | 480 | r100_cp_fini(rdev); |
| 484 | radeon_wb_fini(rdev); | 481 | radeon_wb_fini(rdev); |
| 485 | r100_ib_fini(rdev); | 482 | radeon_ib_pool_fini(rdev); |
| 486 | radeon_gem_fini(rdev); | 483 | radeon_gem_fini(rdev); |
| 487 | rs400_gart_fini(rdev); | 484 | rs400_gart_fini(rdev); |
| 488 | radeon_irq_kms_fini(rdev); | 485 | radeon_irq_kms_fini(rdev); |
| @@ -550,20 +547,14 @@ int rs400_init(struct radeon_device *rdev) | |||
| 550 | return r; | 547 | return r; |
| 551 | r300_set_reg_safe(rdev); | 548 | r300_set_reg_safe(rdev); |
| 552 | 549 | ||
| 553 | r = radeon_ib_pool_init(rdev); | ||
| 554 | rdev->accel_working = true; | 550 | rdev->accel_working = true; |
| 555 | if (r) { | ||
| 556 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 557 | rdev->accel_working = false; | ||
| 558 | } | ||
| 559 | |||
| 560 | r = rs400_startup(rdev); | 551 | r = rs400_startup(rdev); |
| 561 | if (r) { | 552 | if (r) { |
| 562 | /* Somethings want wront with the accel init stop accel */ | 553 | /* Somethings want wront with the accel init stop accel */ |
| 563 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 554 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 564 | r100_cp_fini(rdev); | 555 | r100_cp_fini(rdev); |
| 565 | radeon_wb_fini(rdev); | 556 | radeon_wb_fini(rdev); |
| 566 | r100_ib_fini(rdev); | 557 | radeon_ib_pool_fini(rdev); |
| 567 | rs400_gart_fini(rdev); | 558 | rs400_gart_fini(rdev); |
| 568 | radeon_irq_kms_fini(rdev); | 559 | radeon_irq_kms_fini(rdev); |
| 569 | rdev->accel_working = false; | 560 | rdev->accel_working = false; |
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index e95c5e61d4e2..5301b3df8466 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
| @@ -294,6 +294,7 @@ void rs600_hpd_init(struct radeon_device *rdev) | |||
| 294 | { | 294 | { |
| 295 | struct drm_device *dev = rdev->ddev; | 295 | struct drm_device *dev = rdev->ddev; |
| 296 | struct drm_connector *connector; | 296 | struct drm_connector *connector; |
| 297 | unsigned enable = 0; | ||
| 297 | 298 | ||
| 298 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 299 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 299 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 300 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| @@ -301,26 +302,25 @@ void rs600_hpd_init(struct radeon_device *rdev) | |||
| 301 | case RADEON_HPD_1: | 302 | case RADEON_HPD_1: |
| 302 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, | 303 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, |
| 303 | S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); | 304 | S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); |
| 304 | rdev->irq.hpd[0] = true; | ||
| 305 | break; | 305 | break; |
| 306 | case RADEON_HPD_2: | 306 | case RADEON_HPD_2: |
| 307 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, | 307 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, |
| 308 | S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); | 308 | S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); |
| 309 | rdev->irq.hpd[1] = true; | ||
| 310 | break; | 309 | break; |
| 311 | default: | 310 | default: |
| 312 | break; | 311 | break; |
| 313 | } | 312 | } |
| 313 | enable |= 1 << radeon_connector->hpd.hpd; | ||
| 314 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 314 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
| 315 | } | 315 | } |
| 316 | if (rdev->irq.installed) | 316 | radeon_irq_kms_enable_hpd(rdev, enable); |
| 317 | rs600_irq_set(rdev); | ||
| 318 | } | 317 | } |
| 319 | 318 | ||
| 320 | void rs600_hpd_fini(struct radeon_device *rdev) | 319 | void rs600_hpd_fini(struct radeon_device *rdev) |
| 321 | { | 320 | { |
| 322 | struct drm_device *dev = rdev->ddev; | 321 | struct drm_device *dev = rdev->ddev; |
| 323 | struct drm_connector *connector; | 322 | struct drm_connector *connector; |
| 323 | unsigned disable = 0; | ||
| 324 | 324 | ||
| 325 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 325 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 326 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 326 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| @@ -328,17 +328,17 @@ void rs600_hpd_fini(struct radeon_device *rdev) | |||
| 328 | case RADEON_HPD_1: | 328 | case RADEON_HPD_1: |
| 329 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, | 329 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, |
| 330 | S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); | 330 | S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); |
| 331 | rdev->irq.hpd[0] = false; | ||
| 332 | break; | 331 | break; |
| 333 | case RADEON_HPD_2: | 332 | case RADEON_HPD_2: |
| 334 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, | 333 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, |
| 335 | S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); | 334 | S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); |
| 336 | rdev->irq.hpd[1] = false; | ||
| 337 | break; | 335 | break; |
| 338 | default: | 336 | default: |
| 339 | break; | 337 | break; |
| 340 | } | 338 | } |
| 339 | disable |= 1 << radeon_connector->hpd.hpd; | ||
| 341 | } | 340 | } |
| 341 | radeon_irq_kms_disable_hpd(rdev, disable); | ||
| 342 | } | 342 | } |
| 343 | 343 | ||
| 344 | int rs600_asic_reset(struct radeon_device *rdev) | 344 | int rs600_asic_reset(struct radeon_device *rdev) |
| @@ -564,18 +564,18 @@ int rs600_irq_set(struct radeon_device *rdev) | |||
| 564 | WREG32(R_000040_GEN_INT_CNTL, 0); | 564 | WREG32(R_000040_GEN_INT_CNTL, 0); |
| 565 | return -EINVAL; | 565 | return -EINVAL; |
| 566 | } | 566 | } |
| 567 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 567 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 568 | tmp |= S_000040_SW_INT_EN(1); | 568 | tmp |= S_000040_SW_INT_EN(1); |
| 569 | } | 569 | } |
| 570 | if (rdev->irq.gui_idle) { | 570 | if (rdev->irq.gui_idle) { |
| 571 | tmp |= S_000040_GUI_IDLE(1); | 571 | tmp |= S_000040_GUI_IDLE(1); |
| 572 | } | 572 | } |
| 573 | if (rdev->irq.crtc_vblank_int[0] || | 573 | if (rdev->irq.crtc_vblank_int[0] || |
| 574 | rdev->irq.pflip[0]) { | 574 | atomic_read(&rdev->irq.pflip[0])) { |
| 575 | mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); | 575 | mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); |
| 576 | } | 576 | } |
| 577 | if (rdev->irq.crtc_vblank_int[1] || | 577 | if (rdev->irq.crtc_vblank_int[1] || |
| 578 | rdev->irq.pflip[1]) { | 578 | atomic_read(&rdev->irq.pflip[1])) { |
| 579 | mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); | 579 | mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); |
| 580 | } | 580 | } |
| 581 | if (rdev->irq.hpd[0]) { | 581 | if (rdev->irq.hpd[0]) { |
| @@ -686,7 +686,6 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
| 686 | /* GUI idle */ | 686 | /* GUI idle */ |
| 687 | if (G_000040_GUI_IDLE(status)) { | 687 | if (G_000040_GUI_IDLE(status)) { |
| 688 | rdev->irq.gui_idle_acked = true; | 688 | rdev->irq.gui_idle_acked = true; |
| 689 | rdev->pm.gui_idle = true; | ||
| 690 | wake_up(&rdev->irq.idle_queue); | 689 | wake_up(&rdev->irq.idle_queue); |
| 691 | } | 690 | } |
| 692 | /* Vertical blank interrupts */ | 691 | /* Vertical blank interrupts */ |
| @@ -696,7 +695,7 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
| 696 | rdev->pm.vblank_sync = true; | 695 | rdev->pm.vblank_sync = true; |
| 697 | wake_up(&rdev->irq.vblank_queue); | 696 | wake_up(&rdev->irq.vblank_queue); |
| 698 | } | 697 | } |
| 699 | if (rdev->irq.pflip[0]) | 698 | if (atomic_read(&rdev->irq.pflip[0])) |
| 700 | radeon_crtc_handle_flip(rdev, 0); | 699 | radeon_crtc_handle_flip(rdev, 0); |
| 701 | } | 700 | } |
| 702 | if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 701 | if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { |
| @@ -705,7 +704,7 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
| 705 | rdev->pm.vblank_sync = true; | 704 | rdev->pm.vblank_sync = true; |
| 706 | wake_up(&rdev->irq.vblank_queue); | 705 | wake_up(&rdev->irq.vblank_queue); |
| 707 | } | 706 | } |
| 708 | if (rdev->irq.pflip[1]) | 707 | if (atomic_read(&rdev->irq.pflip[1])) |
| 709 | radeon_crtc_handle_flip(rdev, 1); | 708 | radeon_crtc_handle_flip(rdev, 1); |
| 710 | } | 709 | } |
| 711 | if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 710 | if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { |
| @@ -908,13 +907,11 @@ static int rs600_startup(struct radeon_device *rdev) | |||
| 908 | return r; | 907 | return r; |
| 909 | } | 908 | } |
| 910 | 909 | ||
| 911 | r = radeon_ib_pool_start(rdev); | 910 | r = radeon_ib_pool_init(rdev); |
| 912 | if (r) | 911 | if (r) { |
| 913 | return r; | 912 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 914 | |||
| 915 | r = radeon_ib_ring_tests(rdev); | ||
| 916 | if (r) | ||
| 917 | return r; | 913 | return r; |
| 914 | } | ||
| 918 | 915 | ||
| 919 | r = r600_audio_init(rdev); | 916 | r = r600_audio_init(rdev); |
| 920 | if (r) { | 917 | if (r) { |
| @@ -956,7 +953,6 @@ int rs600_resume(struct radeon_device *rdev) | |||
| 956 | 953 | ||
| 957 | int rs600_suspend(struct radeon_device *rdev) | 954 | int rs600_suspend(struct radeon_device *rdev) |
| 958 | { | 955 | { |
| 959 | radeon_ib_pool_suspend(rdev); | ||
| 960 | r600_audio_fini(rdev); | 956 | r600_audio_fini(rdev); |
| 961 | r100_cp_disable(rdev); | 957 | r100_cp_disable(rdev); |
| 962 | radeon_wb_disable(rdev); | 958 | radeon_wb_disable(rdev); |
| @@ -970,7 +966,7 @@ void rs600_fini(struct radeon_device *rdev) | |||
| 970 | r600_audio_fini(rdev); | 966 | r600_audio_fini(rdev); |
| 971 | r100_cp_fini(rdev); | 967 | r100_cp_fini(rdev); |
| 972 | radeon_wb_fini(rdev); | 968 | radeon_wb_fini(rdev); |
| 973 | r100_ib_fini(rdev); | 969 | radeon_ib_pool_fini(rdev); |
| 974 | radeon_gem_fini(rdev); | 970 | radeon_gem_fini(rdev); |
| 975 | rs600_gart_fini(rdev); | 971 | rs600_gart_fini(rdev); |
| 976 | radeon_irq_kms_fini(rdev); | 972 | radeon_irq_kms_fini(rdev); |
| @@ -1038,20 +1034,14 @@ int rs600_init(struct radeon_device *rdev) | |||
| 1038 | return r; | 1034 | return r; |
| 1039 | rs600_set_safe_registers(rdev); | 1035 | rs600_set_safe_registers(rdev); |
| 1040 | 1036 | ||
| 1041 | r = radeon_ib_pool_init(rdev); | ||
| 1042 | rdev->accel_working = true; | 1037 | rdev->accel_working = true; |
| 1043 | if (r) { | ||
| 1044 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 1045 | rdev->accel_working = false; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | r = rs600_startup(rdev); | 1038 | r = rs600_startup(rdev); |
| 1049 | if (r) { | 1039 | if (r) { |
| 1050 | /* Somethings want wront with the accel init stop accel */ | 1040 | /* Somethings want wront with the accel init stop accel */ |
| 1051 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 1041 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 1052 | r100_cp_fini(rdev); | 1042 | r100_cp_fini(rdev); |
| 1053 | radeon_wb_fini(rdev); | 1043 | radeon_wb_fini(rdev); |
| 1054 | r100_ib_fini(rdev); | 1044 | radeon_ib_pool_fini(rdev); |
| 1055 | rs600_gart_fini(rdev); | 1045 | rs600_gart_fini(rdev); |
| 1056 | radeon_irq_kms_fini(rdev); | 1046 | radeon_irq_kms_fini(rdev); |
| 1057 | rdev->accel_working = false; | 1047 | rdev->accel_working = false; |
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 159b6a43fda0..3b663fcfe061 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c | |||
| @@ -637,13 +637,11 @@ static int rs690_startup(struct radeon_device *rdev) | |||
| 637 | return r; | 637 | return r; |
| 638 | } | 638 | } |
| 639 | 639 | ||
| 640 | r = radeon_ib_pool_start(rdev); | 640 | r = radeon_ib_pool_init(rdev); |
| 641 | if (r) | 641 | if (r) { |
| 642 | return r; | 642 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 643 | |||
| 644 | r = radeon_ib_ring_tests(rdev); | ||
| 645 | if (r) | ||
| 646 | return r; | 643 | return r; |
| 644 | } | ||
| 647 | 645 | ||
| 648 | r = r600_audio_init(rdev); | 646 | r = r600_audio_init(rdev); |
| 649 | if (r) { | 647 | if (r) { |
| @@ -685,7 +683,6 @@ int rs690_resume(struct radeon_device *rdev) | |||
| 685 | 683 | ||
| 686 | int rs690_suspend(struct radeon_device *rdev) | 684 | int rs690_suspend(struct radeon_device *rdev) |
| 687 | { | 685 | { |
| 688 | radeon_ib_pool_suspend(rdev); | ||
| 689 | r600_audio_fini(rdev); | 686 | r600_audio_fini(rdev); |
| 690 | r100_cp_disable(rdev); | 687 | r100_cp_disable(rdev); |
| 691 | radeon_wb_disable(rdev); | 688 | radeon_wb_disable(rdev); |
| @@ -699,7 +696,7 @@ void rs690_fini(struct radeon_device *rdev) | |||
| 699 | r600_audio_fini(rdev); | 696 | r600_audio_fini(rdev); |
| 700 | r100_cp_fini(rdev); | 697 | r100_cp_fini(rdev); |
| 701 | radeon_wb_fini(rdev); | 698 | radeon_wb_fini(rdev); |
| 702 | r100_ib_fini(rdev); | 699 | radeon_ib_pool_fini(rdev); |
| 703 | radeon_gem_fini(rdev); | 700 | radeon_gem_fini(rdev); |
| 704 | rs400_gart_fini(rdev); | 701 | rs400_gart_fini(rdev); |
| 705 | radeon_irq_kms_fini(rdev); | 702 | radeon_irq_kms_fini(rdev); |
| @@ -768,20 +765,14 @@ int rs690_init(struct radeon_device *rdev) | |||
| 768 | return r; | 765 | return r; |
| 769 | rs600_set_safe_registers(rdev); | 766 | rs600_set_safe_registers(rdev); |
| 770 | 767 | ||
| 771 | r = radeon_ib_pool_init(rdev); | ||
| 772 | rdev->accel_working = true; | 768 | rdev->accel_working = true; |
| 773 | if (r) { | ||
| 774 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 775 | rdev->accel_working = false; | ||
| 776 | } | ||
| 777 | |||
| 778 | r = rs690_startup(rdev); | 769 | r = rs690_startup(rdev); |
| 779 | if (r) { | 770 | if (r) { |
| 780 | /* Somethings want wront with the accel init stop accel */ | 771 | /* Somethings want wront with the accel init stop accel */ |
| 781 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 772 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 782 | r100_cp_fini(rdev); | 773 | r100_cp_fini(rdev); |
| 783 | radeon_wb_fini(rdev); | 774 | radeon_wb_fini(rdev); |
| 784 | r100_ib_fini(rdev); | 775 | radeon_ib_pool_fini(rdev); |
| 785 | rs400_gart_fini(rdev); | 776 | rs400_gart_fini(rdev); |
| 786 | radeon_irq_kms_fini(rdev); | 777 | radeon_irq_kms_fini(rdev); |
| 787 | rdev->accel_working = false; | 778 | rdev->accel_working = false; |
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 7f08cedb5333..a12fbcc8ccb6 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c | |||
| @@ -408,13 +408,11 @@ static int rv515_startup(struct radeon_device *rdev) | |||
| 408 | return r; | 408 | return r; |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | r = radeon_ib_pool_start(rdev); | 411 | r = radeon_ib_pool_init(rdev); |
| 412 | if (r) | 412 | if (r) { |
| 413 | return r; | 413 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 414 | |||
| 415 | r = radeon_ib_ring_tests(rdev); | ||
| 416 | if (r) | ||
| 417 | return r; | 414 | return r; |
| 415 | } | ||
| 418 | 416 | ||
| 419 | return 0; | 417 | return 0; |
| 420 | } | 418 | } |
| @@ -469,7 +467,7 @@ void rv515_fini(struct radeon_device *rdev) | |||
| 469 | { | 467 | { |
| 470 | r100_cp_fini(rdev); | 468 | r100_cp_fini(rdev); |
| 471 | radeon_wb_fini(rdev); | 469 | radeon_wb_fini(rdev); |
| 472 | r100_ib_fini(rdev); | 470 | radeon_ib_pool_fini(rdev); |
| 473 | radeon_gem_fini(rdev); | 471 | radeon_gem_fini(rdev); |
| 474 | rv370_pcie_gart_fini(rdev); | 472 | rv370_pcie_gart_fini(rdev); |
| 475 | radeon_agp_fini(rdev); | 473 | radeon_agp_fini(rdev); |
| @@ -543,20 +541,14 @@ int rv515_init(struct radeon_device *rdev) | |||
| 543 | return r; | 541 | return r; |
| 544 | rv515_set_safe_registers(rdev); | 542 | rv515_set_safe_registers(rdev); |
| 545 | 543 | ||
| 546 | r = radeon_ib_pool_init(rdev); | ||
| 547 | rdev->accel_working = true; | 544 | rdev->accel_working = true; |
| 548 | if (r) { | ||
| 549 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 550 | rdev->accel_working = false; | ||
| 551 | } | ||
| 552 | |||
| 553 | r = rv515_startup(rdev); | 545 | r = rv515_startup(rdev); |
| 554 | if (r) { | 546 | if (r) { |
| 555 | /* Somethings want wront with the accel init stop accel */ | 547 | /* Somethings want wront with the accel init stop accel */ |
| 556 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 548 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 557 | r100_cp_fini(rdev); | 549 | r100_cp_fini(rdev); |
| 558 | radeon_wb_fini(rdev); | 550 | radeon_wb_fini(rdev); |
| 559 | r100_ib_fini(rdev); | 551 | radeon_ib_pool_fini(rdev); |
| 560 | radeon_irq_kms_fini(rdev); | 552 | radeon_irq_kms_fini(rdev); |
| 561 | rv370_pcie_gart_fini(rdev); | 553 | rv370_pcie_gart_fini(rdev); |
| 562 | radeon_agp_fini(rdev); | 554 | radeon_agp_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index b4f51c569c36..ca8ffec10ff6 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
| @@ -358,8 +358,10 @@ static int rv770_cp_load_microcode(struct radeon_device *rdev) | |||
| 358 | 358 | ||
| 359 | void r700_cp_fini(struct radeon_device *rdev) | 359 | void r700_cp_fini(struct radeon_device *rdev) |
| 360 | { | 360 | { |
| 361 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | ||
| 361 | r700_cp_stop(rdev); | 362 | r700_cp_stop(rdev); |
| 362 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | 363 | radeon_ring_fini(rdev, ring); |
| 364 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 363 | } | 365 | } |
| 364 | 366 | ||
| 365 | /* | 367 | /* |
| @@ -951,13 +953,11 @@ static int rv770_startup(struct radeon_device *rdev) | |||
| 951 | if (r) | 953 | if (r) |
| 952 | return r; | 954 | return r; |
| 953 | 955 | ||
| 954 | r = radeon_ib_pool_start(rdev); | 956 | r = radeon_ib_pool_init(rdev); |
| 955 | if (r) | 957 | if (r) { |
| 956 | return r; | 958 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 957 | |||
| 958 | r = radeon_ib_ring_tests(rdev); | ||
| 959 | if (r) | ||
| 960 | return r; | 959 | return r; |
| 960 | } | ||
| 961 | 961 | ||
| 962 | r = r600_audio_init(rdev); | 962 | r = r600_audio_init(rdev); |
| 963 | if (r) { | 963 | if (r) { |
| @@ -994,9 +994,6 @@ int rv770_resume(struct radeon_device *rdev) | |||
| 994 | int rv770_suspend(struct radeon_device *rdev) | 994 | int rv770_suspend(struct radeon_device *rdev) |
| 995 | { | 995 | { |
| 996 | r600_audio_fini(rdev); | 996 | r600_audio_fini(rdev); |
| 997 | radeon_ib_pool_suspend(rdev); | ||
| 998 | r600_blit_suspend(rdev); | ||
| 999 | /* FIXME: we should wait for ring to be empty */ | ||
| 1000 | r700_cp_stop(rdev); | 997 | r700_cp_stop(rdev); |
| 1001 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 998 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
| 1002 | r600_irq_suspend(rdev); | 999 | r600_irq_suspend(rdev); |
| @@ -1076,20 +1073,14 @@ int rv770_init(struct radeon_device *rdev) | |||
| 1076 | if (r) | 1073 | if (r) |
| 1077 | return r; | 1074 | return r; |
| 1078 | 1075 | ||
| 1079 | r = radeon_ib_pool_init(rdev); | ||
| 1080 | rdev->accel_working = true; | 1076 | rdev->accel_working = true; |
| 1081 | if (r) { | ||
| 1082 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 1083 | rdev->accel_working = false; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | r = rv770_startup(rdev); | 1077 | r = rv770_startup(rdev); |
| 1087 | if (r) { | 1078 | if (r) { |
| 1088 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 1079 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
| 1089 | r700_cp_fini(rdev); | 1080 | r700_cp_fini(rdev); |
| 1090 | r600_irq_fini(rdev); | 1081 | r600_irq_fini(rdev); |
| 1091 | radeon_wb_fini(rdev); | 1082 | radeon_wb_fini(rdev); |
| 1092 | r100_ib_fini(rdev); | 1083 | radeon_ib_pool_fini(rdev); |
| 1093 | radeon_irq_kms_fini(rdev); | 1084 | radeon_irq_kms_fini(rdev); |
| 1094 | rv770_pcie_gart_fini(rdev); | 1085 | rv770_pcie_gart_fini(rdev); |
| 1095 | rdev->accel_working = false; | 1086 | rdev->accel_working = false; |
| @@ -1104,7 +1095,7 @@ void rv770_fini(struct radeon_device *rdev) | |||
| 1104 | r700_cp_fini(rdev); | 1095 | r700_cp_fini(rdev); |
| 1105 | r600_irq_fini(rdev); | 1096 | r600_irq_fini(rdev); |
| 1106 | radeon_wb_fini(rdev); | 1097 | radeon_wb_fini(rdev); |
| 1107 | r100_ib_fini(rdev); | 1098 | radeon_ib_pool_fini(rdev); |
| 1108 | radeon_irq_kms_fini(rdev); | 1099 | radeon_irq_kms_fini(rdev); |
| 1109 | rv770_pcie_gart_fini(rdev); | 1100 | rv770_pcie_gart_fini(rdev); |
| 1110 | r600_vram_scratch_fini(rdev); | 1101 | r600_vram_scratch_fini(rdev); |
| @@ -1121,6 +1112,8 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev) | |||
| 1121 | { | 1112 | { |
| 1122 | u32 link_width_cntl, lanes, speed_cntl, tmp; | 1113 | u32 link_width_cntl, lanes, speed_cntl, tmp; |
| 1123 | u16 link_cntl2; | 1114 | u16 link_cntl2; |
| 1115 | u32 mask; | ||
| 1116 | int ret; | ||
| 1124 | 1117 | ||
| 1125 | if (radeon_pcie_gen2 == 0) | 1118 | if (radeon_pcie_gen2 == 0) |
| 1126 | return; | 1119 | return; |
| @@ -1135,6 +1128,15 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev) | |||
| 1135 | if (ASIC_IS_X2(rdev)) | 1128 | if (ASIC_IS_X2(rdev)) |
| 1136 | return; | 1129 | return; |
| 1137 | 1130 | ||
| 1131 | ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); | ||
| 1132 | if (ret != 0) | ||
| 1133 | return; | ||
| 1134 | |||
| 1135 | if (!(mask & DRM_PCIE_SPEED_50)) | ||
| 1136 | return; | ||
| 1137 | |||
| 1138 | DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); | ||
| 1139 | |||
| 1138 | /* advertise upconfig capability */ | 1140 | /* advertise upconfig capability */ |
| 1139 | link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); | 1141 | link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); |
| 1140 | link_width_cntl &= ~LC_UPCONFIGURE_DIS; | 1142 | link_width_cntl &= ~LC_UPCONFIGURE_DIS; |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 0b0279291a73..c053f8193771 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -1762,13 +1762,34 @@ void si_fence_ring_emit(struct radeon_device *rdev, | |||
| 1762 | */ | 1762 | */ |
| 1763 | void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | 1763 | void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) |
| 1764 | { | 1764 | { |
| 1765 | struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; | 1765 | struct radeon_ring *ring = &rdev->ring[ib->ring]; |
| 1766 | u32 header; | 1766 | u32 header; |
| 1767 | 1767 | ||
| 1768 | if (ib->is_const_ib) | 1768 | if (ib->is_const_ib) { |
| 1769 | /* set switch buffer packet before const IB */ | ||
| 1770 | radeon_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); | ||
| 1771 | radeon_ring_write(ring, 0); | ||
| 1772 | |||
| 1769 | header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); | 1773 | header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); |
| 1770 | else | 1774 | } else { |
| 1775 | u32 next_rptr; | ||
| 1776 | if (ring->rptr_save_reg) { | ||
| 1777 | next_rptr = ring->wptr + 3 + 4 + 8; | ||
| 1778 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
| 1779 | radeon_ring_write(ring, ((ring->rptr_save_reg - | ||
| 1780 | PACKET3_SET_CONFIG_REG_START) >> 2)); | ||
| 1781 | radeon_ring_write(ring, next_rptr); | ||
| 1782 | } else if (rdev->wb.enabled) { | ||
| 1783 | next_rptr = ring->wptr + 5 + 4 + 8; | ||
| 1784 | radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); | ||
| 1785 | radeon_ring_write(ring, (1 << 8)); | ||
| 1786 | radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); | ||
| 1787 | radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); | ||
| 1788 | radeon_ring_write(ring, next_rptr); | ||
| 1789 | } | ||
| 1790 | |||
| 1771 | header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); | 1791 | header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); |
| 1792 | } | ||
| 1772 | 1793 | ||
| 1773 | radeon_ring_write(ring, header); | 1794 | radeon_ring_write(ring, header); |
| 1774 | radeon_ring_write(ring, | 1795 | radeon_ring_write(ring, |
| @@ -1779,18 +1800,20 @@ void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 1779 | radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); | 1800 | radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); |
| 1780 | radeon_ring_write(ring, ib->length_dw | (ib->vm_id << 24)); | 1801 | radeon_ring_write(ring, ib->length_dw | (ib->vm_id << 24)); |
| 1781 | 1802 | ||
| 1782 | /* flush read cache over gart for this vmid */ | 1803 | if (!ib->is_const_ib) { |
| 1783 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | 1804 | /* flush read cache over gart for this vmid */ |
| 1784 | radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); | 1805 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); |
| 1785 | radeon_ring_write(ring, ib->vm_id); | 1806 | radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); |
| 1786 | radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); | 1807 | radeon_ring_write(ring, ib->vm_id); |
| 1787 | radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA | | 1808 | radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); |
| 1788 | PACKET3_TC_ACTION_ENA | | 1809 | radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA | |
| 1789 | PACKET3_SH_KCACHE_ACTION_ENA | | 1810 | PACKET3_TC_ACTION_ENA | |
| 1790 | PACKET3_SH_ICACHE_ACTION_ENA); | 1811 | PACKET3_SH_KCACHE_ACTION_ENA | |
| 1791 | radeon_ring_write(ring, 0xFFFFFFFF); | 1812 | PACKET3_SH_ICACHE_ACTION_ENA); |
| 1792 | radeon_ring_write(ring, 0); | 1813 | radeon_ring_write(ring, 0xFFFFFFFF); |
| 1793 | radeon_ring_write(ring, 10); /* poll interval */ | 1814 | radeon_ring_write(ring, 0); |
| 1815 | radeon_ring_write(ring, 10); /* poll interval */ | ||
| 1816 | } | ||
| 1794 | } | 1817 | } |
| 1795 | 1818 | ||
| 1796 | /* | 1819 | /* |
| @@ -1917,10 +1940,20 @@ static int si_cp_start(struct radeon_device *rdev) | |||
| 1917 | 1940 | ||
| 1918 | static void si_cp_fini(struct radeon_device *rdev) | 1941 | static void si_cp_fini(struct radeon_device *rdev) |
| 1919 | { | 1942 | { |
| 1943 | struct radeon_ring *ring; | ||
| 1920 | si_cp_enable(rdev, false); | 1944 | si_cp_enable(rdev, false); |
| 1921 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | 1945 | |
| 1922 | radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); | 1946 | ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 1923 | radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); | 1947 | radeon_ring_fini(rdev, ring); |
| 1948 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 1949 | |||
| 1950 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; | ||
| 1951 | radeon_ring_fini(rdev, ring); | ||
| 1952 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 1953 | |||
| 1954 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; | ||
| 1955 | radeon_ring_fini(rdev, ring); | ||
| 1956 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 1924 | } | 1957 | } |
| 1925 | 1958 | ||
| 1926 | static int si_cp_resume(struct radeon_device *rdev) | 1959 | static int si_cp_resume(struct radeon_device *rdev) |
| @@ -2702,7 +2735,7 @@ int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 2702 | if (ib->is_const_ib) | 2735 | if (ib->is_const_ib) |
| 2703 | ret = si_vm_packet3_ce_check(rdev, ib->ptr, &pkt); | 2736 | ret = si_vm_packet3_ce_check(rdev, ib->ptr, &pkt); |
| 2704 | else { | 2737 | else { |
| 2705 | switch (ib->fence->ring) { | 2738 | switch (ib->ring) { |
| 2706 | case RADEON_RING_TYPE_GFX_INDEX: | 2739 | case RADEON_RING_TYPE_GFX_INDEX: |
| 2707 | ret = si_vm_packet3_gfx_check(rdev, ib->ptr, &pkt); | 2740 | ret = si_vm_packet3_gfx_check(rdev, ib->ptr, &pkt); |
| 2708 | break; | 2741 | break; |
| @@ -2711,7 +2744,7 @@ int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 2711 | ret = si_vm_packet3_compute_check(rdev, ib->ptr, &pkt); | 2744 | ret = si_vm_packet3_compute_check(rdev, ib->ptr, &pkt); |
| 2712 | break; | 2745 | break; |
| 2713 | default: | 2746 | default: |
| 2714 | dev_err(rdev->dev, "Non-PM4 ring %d !\n", ib->fence->ring); | 2747 | dev_err(rdev->dev, "Non-PM4 ring %d !\n", ib->ring); |
| 2715 | ret = -EINVAL; | 2748 | ret = -EINVAL; |
| 2716 | break; | 2749 | break; |
| 2717 | } | 2750 | } |
| @@ -2942,7 +2975,6 @@ static void si_disable_interrupts(struct radeon_device *rdev) | |||
| 2942 | WREG32(IH_RB_RPTR, 0); | 2975 | WREG32(IH_RB_RPTR, 0); |
| 2943 | WREG32(IH_RB_WPTR, 0); | 2976 | WREG32(IH_RB_WPTR, 0); |
| 2944 | rdev->ih.enabled = false; | 2977 | rdev->ih.enabled = false; |
| 2945 | rdev->ih.wptr = 0; | ||
| 2946 | rdev->ih.rptr = 0; | 2978 | rdev->ih.rptr = 0; |
| 2947 | } | 2979 | } |
| 2948 | 2980 | ||
| @@ -3093,45 +3125,45 @@ int si_irq_set(struct radeon_device *rdev) | |||
| 3093 | hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; | 3125 | hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; |
| 3094 | 3126 | ||
| 3095 | /* enable CP interrupts on all rings */ | 3127 | /* enable CP interrupts on all rings */ |
| 3096 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 3128 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 3097 | DRM_DEBUG("si_irq_set: sw int gfx\n"); | 3129 | DRM_DEBUG("si_irq_set: sw int gfx\n"); |
| 3098 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | 3130 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; |
| 3099 | } | 3131 | } |
| 3100 | if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP1_INDEX]) { | 3132 | if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) { |
| 3101 | DRM_DEBUG("si_irq_set: sw int cp1\n"); | 3133 | DRM_DEBUG("si_irq_set: sw int cp1\n"); |
| 3102 | cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; | 3134 | cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; |
| 3103 | } | 3135 | } |
| 3104 | if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP2_INDEX]) { | 3136 | if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) { |
| 3105 | DRM_DEBUG("si_irq_set: sw int cp2\n"); | 3137 | DRM_DEBUG("si_irq_set: sw int cp2\n"); |
| 3106 | cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; | 3138 | cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; |
| 3107 | } | 3139 | } |
| 3108 | if (rdev->irq.crtc_vblank_int[0] || | 3140 | if (rdev->irq.crtc_vblank_int[0] || |
| 3109 | rdev->irq.pflip[0]) { | 3141 | atomic_read(&rdev->irq.pflip[0])) { |
| 3110 | DRM_DEBUG("si_irq_set: vblank 0\n"); | 3142 | DRM_DEBUG("si_irq_set: vblank 0\n"); |
| 3111 | crtc1 |= VBLANK_INT_MASK; | 3143 | crtc1 |= VBLANK_INT_MASK; |
| 3112 | } | 3144 | } |
| 3113 | if (rdev->irq.crtc_vblank_int[1] || | 3145 | if (rdev->irq.crtc_vblank_int[1] || |
| 3114 | rdev->irq.pflip[1]) { | 3146 | atomic_read(&rdev->irq.pflip[1])) { |
| 3115 | DRM_DEBUG("si_irq_set: vblank 1\n"); | 3147 | DRM_DEBUG("si_irq_set: vblank 1\n"); |
| 3116 | crtc2 |= VBLANK_INT_MASK; | 3148 | crtc2 |= VBLANK_INT_MASK; |
| 3117 | } | 3149 | } |
| 3118 | if (rdev->irq.crtc_vblank_int[2] || | 3150 | if (rdev->irq.crtc_vblank_int[2] || |
| 3119 | rdev->irq.pflip[2]) { | 3151 | atomic_read(&rdev->irq.pflip[2])) { |
| 3120 | DRM_DEBUG("si_irq_set: vblank 2\n"); | 3152 | DRM_DEBUG("si_irq_set: vblank 2\n"); |
| 3121 | crtc3 |= VBLANK_INT_MASK; | 3153 | crtc3 |= VBLANK_INT_MASK; |
| 3122 | } | 3154 | } |
| 3123 | if (rdev->irq.crtc_vblank_int[3] || | 3155 | if (rdev->irq.crtc_vblank_int[3] || |
| 3124 | rdev->irq.pflip[3]) { | 3156 | atomic_read(&rdev->irq.pflip[3])) { |
| 3125 | DRM_DEBUG("si_irq_set: vblank 3\n"); | 3157 | DRM_DEBUG("si_irq_set: vblank 3\n"); |
| 3126 | crtc4 |= VBLANK_INT_MASK; | 3158 | crtc4 |= VBLANK_INT_MASK; |
| 3127 | } | 3159 | } |
| 3128 | if (rdev->irq.crtc_vblank_int[4] || | 3160 | if (rdev->irq.crtc_vblank_int[4] || |
| 3129 | rdev->irq.pflip[4]) { | 3161 | atomic_read(&rdev->irq.pflip[4])) { |
| 3130 | DRM_DEBUG("si_irq_set: vblank 4\n"); | 3162 | DRM_DEBUG("si_irq_set: vblank 4\n"); |
| 3131 | crtc5 |= VBLANK_INT_MASK; | 3163 | crtc5 |= VBLANK_INT_MASK; |
| 3132 | } | 3164 | } |
| 3133 | if (rdev->irq.crtc_vblank_int[5] || | 3165 | if (rdev->irq.crtc_vblank_int[5] || |
| 3134 | rdev->irq.pflip[5]) { | 3166 | atomic_read(&rdev->irq.pflip[5])) { |
| 3135 | DRM_DEBUG("si_irq_set: vblank 5\n"); | 3167 | DRM_DEBUG("si_irq_set: vblank 5\n"); |
| 3136 | crtc6 |= VBLANK_INT_MASK; | 3168 | crtc6 |= VBLANK_INT_MASK; |
| 3137 | } | 3169 | } |
| @@ -3359,29 +3391,27 @@ int si_irq_process(struct radeon_device *rdev) | |||
| 3359 | u32 rptr; | 3391 | u32 rptr; |
| 3360 | u32 src_id, src_data, ring_id; | 3392 | u32 src_id, src_data, ring_id; |
| 3361 | u32 ring_index; | 3393 | u32 ring_index; |
| 3362 | unsigned long flags; | ||
| 3363 | bool queue_hotplug = false; | 3394 | bool queue_hotplug = false; |
| 3364 | 3395 | ||
| 3365 | if (!rdev->ih.enabled || rdev->shutdown) | 3396 | if (!rdev->ih.enabled || rdev->shutdown) |
| 3366 | return IRQ_NONE; | 3397 | return IRQ_NONE; |
| 3367 | 3398 | ||
| 3368 | wptr = si_get_ih_wptr(rdev); | 3399 | wptr = si_get_ih_wptr(rdev); |
| 3400 | |||
| 3401 | restart_ih: | ||
| 3402 | /* is somebody else already processing irqs? */ | ||
| 3403 | if (atomic_xchg(&rdev->ih.lock, 1)) | ||
| 3404 | return IRQ_NONE; | ||
| 3405 | |||
| 3369 | rptr = rdev->ih.rptr; | 3406 | rptr = rdev->ih.rptr; |
| 3370 | DRM_DEBUG("si_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | 3407 | DRM_DEBUG("si_irq_process start: rptr %d, wptr %d\n", rptr, wptr); |
| 3371 | 3408 | ||
| 3372 | spin_lock_irqsave(&rdev->ih.lock, flags); | ||
| 3373 | if (rptr == wptr) { | ||
| 3374 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | ||
| 3375 | return IRQ_NONE; | ||
| 3376 | } | ||
| 3377 | restart_ih: | ||
| 3378 | /* Order reading of wptr vs. reading of IH ring data */ | 3409 | /* Order reading of wptr vs. reading of IH ring data */ |
| 3379 | rmb(); | 3410 | rmb(); |
| 3380 | 3411 | ||
| 3381 | /* display interrupts */ | 3412 | /* display interrupts */ |
| 3382 | si_irq_ack(rdev); | 3413 | si_irq_ack(rdev); |
| 3383 | 3414 | ||
| 3384 | rdev->ih.wptr = wptr; | ||
| 3385 | while (rptr != wptr) { | 3415 | while (rptr != wptr) { |
| 3386 | /* wptr/rptr are in bytes! */ | 3416 | /* wptr/rptr are in bytes! */ |
| 3387 | ring_index = rptr / 4; | 3417 | ring_index = rptr / 4; |
| @@ -3399,7 +3429,7 @@ restart_ih: | |||
| 3399 | rdev->pm.vblank_sync = true; | 3429 | rdev->pm.vblank_sync = true; |
| 3400 | wake_up(&rdev->irq.vblank_queue); | 3430 | wake_up(&rdev->irq.vblank_queue); |
| 3401 | } | 3431 | } |
| 3402 | if (rdev->irq.pflip[0]) | 3432 | if (atomic_read(&rdev->irq.pflip[0])) |
| 3403 | radeon_crtc_handle_flip(rdev, 0); | 3433 | radeon_crtc_handle_flip(rdev, 0); |
| 3404 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | 3434 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; |
| 3405 | DRM_DEBUG("IH: D1 vblank\n"); | 3435 | DRM_DEBUG("IH: D1 vblank\n"); |
| @@ -3425,7 +3455,7 @@ restart_ih: | |||
| 3425 | rdev->pm.vblank_sync = true; | 3455 | rdev->pm.vblank_sync = true; |
| 3426 | wake_up(&rdev->irq.vblank_queue); | 3456 | wake_up(&rdev->irq.vblank_queue); |
| 3427 | } | 3457 | } |
| 3428 | if (rdev->irq.pflip[1]) | 3458 | if (atomic_read(&rdev->irq.pflip[1])) |
| 3429 | radeon_crtc_handle_flip(rdev, 1); | 3459 | radeon_crtc_handle_flip(rdev, 1); |
| 3430 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; | 3460 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; |
| 3431 | DRM_DEBUG("IH: D2 vblank\n"); | 3461 | DRM_DEBUG("IH: D2 vblank\n"); |
| @@ -3451,7 +3481,7 @@ restart_ih: | |||
| 3451 | rdev->pm.vblank_sync = true; | 3481 | rdev->pm.vblank_sync = true; |
| 3452 | wake_up(&rdev->irq.vblank_queue); | 3482 | wake_up(&rdev->irq.vblank_queue); |
| 3453 | } | 3483 | } |
| 3454 | if (rdev->irq.pflip[2]) | 3484 | if (atomic_read(&rdev->irq.pflip[2])) |
| 3455 | radeon_crtc_handle_flip(rdev, 2); | 3485 | radeon_crtc_handle_flip(rdev, 2); |
| 3456 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; | 3486 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; |
| 3457 | DRM_DEBUG("IH: D3 vblank\n"); | 3487 | DRM_DEBUG("IH: D3 vblank\n"); |
| @@ -3477,7 +3507,7 @@ restart_ih: | |||
| 3477 | rdev->pm.vblank_sync = true; | 3507 | rdev->pm.vblank_sync = true; |
| 3478 | wake_up(&rdev->irq.vblank_queue); | 3508 | wake_up(&rdev->irq.vblank_queue); |
| 3479 | } | 3509 | } |
| 3480 | if (rdev->irq.pflip[3]) | 3510 | if (atomic_read(&rdev->irq.pflip[3])) |
| 3481 | radeon_crtc_handle_flip(rdev, 3); | 3511 | radeon_crtc_handle_flip(rdev, 3); |
| 3482 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; | 3512 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; |
| 3483 | DRM_DEBUG("IH: D4 vblank\n"); | 3513 | DRM_DEBUG("IH: D4 vblank\n"); |
| @@ -3503,7 +3533,7 @@ restart_ih: | |||
| 3503 | rdev->pm.vblank_sync = true; | 3533 | rdev->pm.vblank_sync = true; |
| 3504 | wake_up(&rdev->irq.vblank_queue); | 3534 | wake_up(&rdev->irq.vblank_queue); |
| 3505 | } | 3535 | } |
| 3506 | if (rdev->irq.pflip[4]) | 3536 | if (atomic_read(&rdev->irq.pflip[4])) |
| 3507 | radeon_crtc_handle_flip(rdev, 4); | 3537 | radeon_crtc_handle_flip(rdev, 4); |
| 3508 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; | 3538 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; |
| 3509 | DRM_DEBUG("IH: D5 vblank\n"); | 3539 | DRM_DEBUG("IH: D5 vblank\n"); |
| @@ -3529,7 +3559,7 @@ restart_ih: | |||
| 3529 | rdev->pm.vblank_sync = true; | 3559 | rdev->pm.vblank_sync = true; |
| 3530 | wake_up(&rdev->irq.vblank_queue); | 3560 | wake_up(&rdev->irq.vblank_queue); |
| 3531 | } | 3561 | } |
| 3532 | if (rdev->irq.pflip[5]) | 3562 | if (atomic_read(&rdev->irq.pflip[5])) |
| 3533 | radeon_crtc_handle_flip(rdev, 5); | 3563 | radeon_crtc_handle_flip(rdev, 5); |
| 3534 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; | 3564 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; |
| 3535 | DRM_DEBUG("IH: D6 vblank\n"); | 3565 | DRM_DEBUG("IH: D6 vblank\n"); |
| @@ -3620,7 +3650,6 @@ restart_ih: | |||
| 3620 | break; | 3650 | break; |
| 3621 | case 233: /* GUI IDLE */ | 3651 | case 233: /* GUI IDLE */ |
| 3622 | DRM_DEBUG("IH: GUI idle\n"); | 3652 | DRM_DEBUG("IH: GUI idle\n"); |
| 3623 | rdev->pm.gui_idle = true; | ||
| 3624 | wake_up(&rdev->irq.idle_queue); | 3653 | wake_up(&rdev->irq.idle_queue); |
| 3625 | break; | 3654 | break; |
| 3626 | default: | 3655 | default: |
| @@ -3632,15 +3661,17 @@ restart_ih: | |||
| 3632 | rptr += 16; | 3661 | rptr += 16; |
| 3633 | rptr &= rdev->ih.ptr_mask; | 3662 | rptr &= rdev->ih.ptr_mask; |
| 3634 | } | 3663 | } |
| 3635 | /* make sure wptr hasn't changed while processing */ | ||
| 3636 | wptr = si_get_ih_wptr(rdev); | ||
| 3637 | if (wptr != rdev->ih.wptr) | ||
| 3638 | goto restart_ih; | ||
| 3639 | if (queue_hotplug) | 3664 | if (queue_hotplug) |
| 3640 | schedule_work(&rdev->hotplug_work); | 3665 | schedule_work(&rdev->hotplug_work); |
| 3641 | rdev->ih.rptr = rptr; | 3666 | rdev->ih.rptr = rptr; |
| 3642 | WREG32(IH_RB_RPTR, rdev->ih.rptr); | 3667 | WREG32(IH_RB_RPTR, rdev->ih.rptr); |
| 3643 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | 3668 | atomic_set(&rdev->ih.lock, 0); |
| 3669 | |||
| 3670 | /* make sure wptr hasn't changed while processing */ | ||
| 3671 | wptr = si_get_ih_wptr(rdev); | ||
| 3672 | if (wptr != rptr) | ||
| 3673 | goto restart_ih; | ||
| 3674 | |||
| 3644 | return IRQ_HANDLED; | 3675 | return IRQ_HANDLED; |
| 3645 | } | 3676 | } |
| 3646 | 3677 | ||
| @@ -3752,35 +3783,18 @@ static int si_startup(struct radeon_device *rdev) | |||
| 3752 | if (r) | 3783 | if (r) |
| 3753 | return r; | 3784 | return r; |
| 3754 | 3785 | ||
| 3755 | r = radeon_ib_pool_start(rdev); | 3786 | r = radeon_ib_pool_init(rdev); |
| 3756 | if (r) | ||
| 3757 | return r; | ||
| 3758 | |||
| 3759 | r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | ||
| 3760 | if (r) { | ||
| 3761 | DRM_ERROR("radeon: failed testing IB (%d) on CP ring 0\n", r); | ||
| 3762 | rdev->accel_working = false; | ||
| 3763 | return r; | ||
| 3764 | } | ||
| 3765 | |||
| 3766 | r = radeon_ib_test(rdev, CAYMAN_RING_TYPE_CP1_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); | ||
| 3767 | if (r) { | 3787 | if (r) { |
| 3768 | DRM_ERROR("radeon: failed testing IB (%d) on CP ring 1\n", r); | 3788 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 3769 | rdev->accel_working = false; | ||
| 3770 | return r; | 3789 | return r; |
| 3771 | } | 3790 | } |
| 3772 | 3791 | ||
| 3773 | r = radeon_ib_test(rdev, CAYMAN_RING_TYPE_CP2_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); | 3792 | r = radeon_vm_manager_init(rdev); |
| 3774 | if (r) { | 3793 | if (r) { |
| 3775 | DRM_ERROR("radeon: failed testing IB (%d) on CP ring 2\n", r); | 3794 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); |
| 3776 | rdev->accel_working = false; | ||
| 3777 | return r; | 3795 | return r; |
| 3778 | } | 3796 | } |
| 3779 | 3797 | ||
| 3780 | r = radeon_vm_manager_start(rdev); | ||
| 3781 | if (r) | ||
| 3782 | return r; | ||
| 3783 | |||
| 3784 | return 0; | 3798 | return 0; |
| 3785 | } | 3799 | } |
| 3786 | 3800 | ||
| @@ -3809,12 +3823,6 @@ int si_resume(struct radeon_device *rdev) | |||
| 3809 | 3823 | ||
| 3810 | int si_suspend(struct radeon_device *rdev) | 3824 | int si_suspend(struct radeon_device *rdev) |
| 3811 | { | 3825 | { |
| 3812 | /* FIXME: we should wait for ring to be empty */ | ||
| 3813 | radeon_ib_pool_suspend(rdev); | ||
| 3814 | radeon_vm_manager_suspend(rdev); | ||
| 3815 | #if 0 | ||
| 3816 | r600_blit_suspend(rdev); | ||
| 3817 | #endif | ||
| 3818 | si_cp_enable(rdev, false); | 3826 | si_cp_enable(rdev, false); |
| 3819 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 3827 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
| 3820 | rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; | 3828 | rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; |
| @@ -3903,17 +3911,7 @@ int si_init(struct radeon_device *rdev) | |||
| 3903 | if (r) | 3911 | if (r) |
| 3904 | return r; | 3912 | return r; |
| 3905 | 3913 | ||
| 3906 | r = radeon_ib_pool_init(rdev); | ||
| 3907 | rdev->accel_working = true; | 3914 | rdev->accel_working = true; |
| 3908 | if (r) { | ||
| 3909 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 3910 | rdev->accel_working = false; | ||
| 3911 | } | ||
| 3912 | r = radeon_vm_manager_init(rdev); | ||
| 3913 | if (r) { | ||
| 3914 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
| 3915 | } | ||
| 3916 | |||
| 3917 | r = si_startup(rdev); | 3915 | r = si_startup(rdev); |
| 3918 | if (r) { | 3916 | if (r) { |
| 3919 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 3917 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
| @@ -3921,7 +3919,7 @@ int si_init(struct radeon_device *rdev) | |||
| 3921 | si_irq_fini(rdev); | 3919 | si_irq_fini(rdev); |
| 3922 | si_rlc_fini(rdev); | 3920 | si_rlc_fini(rdev); |
| 3923 | radeon_wb_fini(rdev); | 3921 | radeon_wb_fini(rdev); |
| 3924 | r100_ib_fini(rdev); | 3922 | radeon_ib_pool_fini(rdev); |
| 3925 | radeon_vm_manager_fini(rdev); | 3923 | radeon_vm_manager_fini(rdev); |
| 3926 | radeon_irq_kms_fini(rdev); | 3924 | radeon_irq_kms_fini(rdev); |
| 3927 | si_pcie_gart_fini(rdev); | 3925 | si_pcie_gart_fini(rdev); |
| @@ -3950,7 +3948,7 @@ void si_fini(struct radeon_device *rdev) | |||
| 3950 | si_rlc_fini(rdev); | 3948 | si_rlc_fini(rdev); |
| 3951 | radeon_wb_fini(rdev); | 3949 | radeon_wb_fini(rdev); |
| 3952 | radeon_vm_manager_fini(rdev); | 3950 | radeon_vm_manager_fini(rdev); |
| 3953 | r100_ib_fini(rdev); | 3951 | radeon_ib_pool_fini(rdev); |
| 3954 | radeon_irq_kms_fini(rdev); | 3952 | radeon_irq_kms_fini(rdev); |
| 3955 | si_pcie_gart_fini(rdev); | 3953 | si_pcie_gart_fini(rdev); |
| 3956 | r600_vram_scratch_fini(rdev); | 3954 | r600_vram_scratch_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index db4067962868..7869089e8761 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
| @@ -901,5 +901,6 @@ | |||
| 901 | #define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88 | 901 | #define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88 |
| 902 | #define PACKET3_SET_CE_DE_COUNTERS 0x89 | 902 | #define PACKET3_SET_CE_DE_COUNTERS 0x89 |
| 903 | #define PACKET3_WAIT_ON_AVAIL_BUFFER 0x8A | 903 | #define PACKET3_WAIT_ON_AVAIL_BUFFER 0x8A |
| 904 | #define PACKET3_SWITCH_BUFFER 0x8B | ||
| 904 | 905 | ||
| 905 | #endif | 906 | #endif |
diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index 6eb507a5d130..1efbb9075837 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c | |||
| @@ -1050,6 +1050,7 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) | |||
| 1050 | { | 1050 | { |
| 1051 | struct drm_device_dma *dma = dev->dma; | 1051 | struct drm_device_dma *dma = dev->dma; |
| 1052 | drm_savage_private_t *dev_priv = dev->dev_private; | 1052 | drm_savage_private_t *dev_priv = dev->dev_private; |
| 1053 | int release_idlelock = 0; | ||
| 1053 | int i; | 1054 | int i; |
| 1054 | 1055 | ||
| 1055 | if (!dma) | 1056 | if (!dma) |
| @@ -1059,7 +1060,10 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) | |||
| 1059 | if (!dma->buflist) | 1060 | if (!dma->buflist) |
| 1060 | return; | 1061 | return; |
| 1061 | 1062 | ||
| 1062 | /*i830_flush_queue(dev); */ | 1063 | if (file_priv->master && file_priv->master->lock.hw_lock) { |
| 1064 | drm_idlelock_take(&file_priv->master->lock); | ||
| 1065 | release_idlelock = 1; | ||
| 1066 | } | ||
| 1063 | 1067 | ||
| 1064 | for (i = 0; i < dma->buf_count; i++) { | 1068 | for (i = 0; i < dma->buf_count; i++) { |
| 1065 | struct drm_buf *buf = dma->buflist[i]; | 1069 | struct drm_buf *buf = dma->buflist[i]; |
| @@ -1075,7 +1079,8 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) | |||
| 1075 | } | 1079 | } |
| 1076 | } | 1080 | } |
| 1077 | 1081 | ||
| 1078 | drm_core_reclaim_buffers(dev, file_priv); | 1082 | if (release_idlelock) |
| 1083 | drm_idlelock_release(&file_priv->master->lock); | ||
| 1079 | } | 1084 | } |
| 1080 | 1085 | ||
| 1081 | struct drm_ioctl_desc savage_ioctls[] = { | 1086 | struct drm_ioctl_desc savage_ioctls[] = { |
diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index 89afe0b83643..d31d4cca9a4c 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c | |||
| @@ -52,9 +52,9 @@ static struct drm_driver driver = { | |||
| 52 | .dev_priv_size = sizeof(drm_savage_buf_priv_t), | 52 | .dev_priv_size = sizeof(drm_savage_buf_priv_t), |
| 53 | .load = savage_driver_load, | 53 | .load = savage_driver_load, |
| 54 | .firstopen = savage_driver_firstopen, | 54 | .firstopen = savage_driver_firstopen, |
| 55 | .preclose = savage_reclaim_buffers, | ||
| 55 | .lastclose = savage_driver_lastclose, | 56 | .lastclose = savage_driver_lastclose, |
| 56 | .unload = savage_driver_unload, | 57 | .unload = savage_driver_unload, |
| 57 | .reclaim_buffers = savage_reclaim_buffers, | ||
| 58 | .ioctls = savage_ioctls, | 58 | .ioctls = savage_ioctls, |
| 59 | .dma_ioctl = savage_bci_buffers, | 59 | .dma_ioctl = savage_bci_buffers, |
| 60 | .fops = &savage_driver_fops, | 60 | .fops = &savage_driver_fops, |
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index dd14cd1a0033..7f119870147c 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c | |||
| @@ -105,10 +105,9 @@ static struct drm_driver driver = { | |||
| 105 | .load = sis_driver_load, | 105 | .load = sis_driver_load, |
| 106 | .unload = sis_driver_unload, | 106 | .unload = sis_driver_unload, |
| 107 | .open = sis_driver_open, | 107 | .open = sis_driver_open, |
| 108 | .preclose = sis_reclaim_buffers_locked, | ||
| 108 | .postclose = sis_driver_postclose, | 109 | .postclose = sis_driver_postclose, |
| 109 | .dma_quiescent = sis_idle, | 110 | .dma_quiescent = sis_idle, |
| 110 | .reclaim_buffers = NULL, | ||
| 111 | .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked, | ||
| 112 | .lastclose = sis_lastclose, | 111 | .lastclose = sis_lastclose, |
| 113 | .ioctls = sis_ioctls, | 112 | .ioctls = sis_ioctls, |
| 114 | .fops = &sis_driver_fops, | 113 | .fops = &sis_driver_fops, |
diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c index dd4a316c3d74..2c231070d250 100644 --- a/drivers/gpu/drm/sis/sis_mm.c +++ b/drivers/gpu/drm/sis/sis_mm.c | |||
| @@ -74,7 +74,7 @@ static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file | |||
| 74 | dev_priv->vram_offset = fb->offset; | 74 | dev_priv->vram_offset = fb->offset; |
| 75 | 75 | ||
| 76 | mutex_unlock(&dev->struct_mutex); | 76 | mutex_unlock(&dev->struct_mutex); |
| 77 | DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size); | 77 | DRM_DEBUG("offset = %lu, size = %lu\n", fb->offset, fb->size); |
| 78 | 78 | ||
| 79 | return 0; | 79 | return 0; |
| 80 | } | 80 | } |
| @@ -161,7 +161,7 @@ fail_alloc: | |||
| 161 | mem->size = 0; | 161 | mem->size = 0; |
| 162 | mem->free = 0; | 162 | mem->free = 0; |
| 163 | 163 | ||
| 164 | DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size, | 164 | DRM_DEBUG("alloc %d, size = %ld, offset = %ld\n", pool, mem->size, |
| 165 | mem->offset); | 165 | mem->offset); |
| 166 | 166 | ||
| 167 | return retval; | 167 | return retval; |
| @@ -215,7 +215,7 @@ static int sis_ioctl_agp_init(struct drm_device *dev, void *data, | |||
| 215 | dev_priv->agp_offset = agp->offset; | 215 | dev_priv->agp_offset = agp->offset; |
| 216 | mutex_unlock(&dev->struct_mutex); | 216 | mutex_unlock(&dev->struct_mutex); |
| 217 | 217 | ||
| 218 | DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size); | 218 | DRM_DEBUG("offset = %lu, size = %lu\n", agp->offset, agp->size); |
| 219 | return 0; | 219 | return 0; |
| 220 | } | 220 | } |
| 221 | 221 | ||
| @@ -321,14 +321,20 @@ void sis_reclaim_buffers_locked(struct drm_device *dev, | |||
| 321 | struct sis_file_private *file_priv = file->driver_priv; | 321 | struct sis_file_private *file_priv = file->driver_priv; |
| 322 | struct sis_memblock *entry, *next; | 322 | struct sis_memblock *entry, *next; |
| 323 | 323 | ||
| 324 | if (!(file->minor->master && file->master->lock.hw_lock)) | ||
| 325 | return; | ||
| 326 | |||
| 327 | drm_idlelock_take(&file->master->lock); | ||
| 328 | |||
| 324 | mutex_lock(&dev->struct_mutex); | 329 | mutex_lock(&dev->struct_mutex); |
| 325 | if (list_empty(&file_priv->obj_list)) { | 330 | if (list_empty(&file_priv->obj_list)) { |
| 326 | mutex_unlock(&dev->struct_mutex); | 331 | mutex_unlock(&dev->struct_mutex); |
| 332 | drm_idlelock_release(&file->master->lock); | ||
| 333 | |||
| 327 | return; | 334 | return; |
| 328 | } | 335 | } |
| 329 | 336 | ||
| 330 | if (dev->driver->dma_quiescent) | 337 | sis_idle(dev); |
| 331 | dev->driver->dma_quiescent(dev); | ||
| 332 | 338 | ||
| 333 | 339 | ||
| 334 | list_for_each_entry_safe(entry, next, &file_priv->obj_list, | 340 | list_for_each_entry_safe(entry, next, &file_priv->obj_list, |
| @@ -343,6 +349,9 @@ void sis_reclaim_buffers_locked(struct drm_device *dev, | |||
| 343 | kfree(entry); | 349 | kfree(entry); |
| 344 | } | 350 | } |
| 345 | mutex_unlock(&dev->struct_mutex); | 351 | mutex_unlock(&dev->struct_mutex); |
| 352 | |||
| 353 | drm_idlelock_release(&file->master->lock); | ||
| 354 | |||
| 346 | return; | 355 | return; |
| 347 | } | 356 | } |
| 348 | 357 | ||
diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index 1613c78544c0..90f6b13acfac 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c | |||
| @@ -54,7 +54,6 @@ static const struct file_operations tdfx_driver_fops = { | |||
| 54 | 54 | ||
| 55 | static struct drm_driver driver = { | 55 | static struct drm_driver driver = { |
| 56 | .driver_features = DRIVER_USE_MTRR, | 56 | .driver_features = DRIVER_USE_MTRR, |
| 57 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 58 | .fops = &tdfx_driver_fops, | 57 | .fops = &tdfx_driver_fops, |
| 59 | .name = DRIVER_NAME, | 58 | .name = DRIVER_NAME, |
| 60 | .desc = DRIVER_DESC, | 59 | .desc = DRIVER_DESC, |
diff --git a/drivers/gpu/drm/udl/udl_encoder.c b/drivers/gpu/drm/udl/udl_encoder.c index 56e75f0f1df5..0731ab2e6c06 100644 --- a/drivers/gpu/drm/udl/udl_encoder.c +++ b/drivers/gpu/drm/udl/udl_encoder.c | |||
| @@ -27,7 +27,7 @@ static void udl_encoder_disable(struct drm_encoder *encoder) | |||
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | static bool udl_mode_fixup(struct drm_encoder *encoder, | 29 | static bool udl_mode_fixup(struct drm_encoder *encoder, |
| 30 | struct drm_display_mode *mode, | 30 | const struct drm_display_mode *mode, |
| 31 | struct drm_display_mode *adjusted_mode) | 31 | struct drm_display_mode *adjusted_mode) |
| 32 | { | 32 | { |
| 33 | return true; | 33 | return true; |
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 0d7816789da1..f5dd89e891de 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c | |||
| @@ -45,12 +45,25 @@ static char *udl_vidreg_unlock(char *buf) | |||
| 45 | * 0x01 H and V sync off (screen blank but powered) | 45 | * 0x01 H and V sync off (screen blank but powered) |
| 46 | * 0x07 DPMS powerdown (requires modeset to come back) | 46 | * 0x07 DPMS powerdown (requires modeset to come back) |
| 47 | */ | 47 | */ |
| 48 | static char *udl_enable_hvsync(char *buf, bool enable) | 48 | static char *udl_set_blank(char *buf, int dpms_mode) |
| 49 | { | 49 | { |
| 50 | if (enable) | 50 | u8 reg; |
| 51 | return udl_set_register(buf, 0x1F, 0x00); | 51 | switch (dpms_mode) { |
| 52 | else | 52 | case DRM_MODE_DPMS_OFF: |
| 53 | return udl_set_register(buf, 0x1F, 0x07); | 53 | reg = 0x07; |
| 54 | break; | ||
| 55 | case DRM_MODE_DPMS_STANDBY: | ||
| 56 | reg = 0x05; | ||
| 57 | break; | ||
| 58 | case DRM_MODE_DPMS_SUSPEND: | ||
| 59 | reg = 0x01; | ||
| 60 | break; | ||
| 61 | case DRM_MODE_DPMS_ON: | ||
| 62 | reg = 0x00; | ||
| 63 | break; | ||
| 64 | } | ||
| 65 | |||
| 66 | return udl_set_register(buf, 0x1f, reg); | ||
| 54 | } | 67 | } |
| 55 | 68 | ||
| 56 | static char *udl_set_color_depth(char *buf, u8 selection) | 69 | static char *udl_set_color_depth(char *buf, u8 selection) |
| @@ -199,6 +212,20 @@ static char *udl_set_vid_cmds(char *wrptr, struct drm_display_mode *mode) | |||
| 199 | return wrptr; | 212 | return wrptr; |
| 200 | } | 213 | } |
| 201 | 214 | ||
| 215 | static char *udl_dummy_render(char *wrptr) | ||
| 216 | { | ||
| 217 | *wrptr++ = 0xAF; | ||
| 218 | *wrptr++ = 0x6A; /* copy */ | ||
| 219 | *wrptr++ = 0x00; /* from addr */ | ||
| 220 | *wrptr++ = 0x00; | ||
| 221 | *wrptr++ = 0x00; | ||
| 222 | *wrptr++ = 0x01; /* one pixel */ | ||
| 223 | *wrptr++ = 0x00; /* to address */ | ||
| 224 | *wrptr++ = 0x00; | ||
| 225 | *wrptr++ = 0x00; | ||
| 226 | return wrptr; | ||
| 227 | } | ||
| 228 | |||
| 202 | static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc) | 229 | static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc) |
| 203 | { | 230 | { |
| 204 | struct drm_device *dev = crtc->dev; | 231 | struct drm_device *dev = crtc->dev; |
| @@ -235,9 +262,10 @@ static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 235 | 262 | ||
| 236 | buf = (char *)urb->transfer_buffer; | 263 | buf = (char *)urb->transfer_buffer; |
| 237 | buf = udl_vidreg_lock(buf); | 264 | buf = udl_vidreg_lock(buf); |
| 238 | buf = udl_enable_hvsync(buf, false); | 265 | buf = udl_set_blank(buf, mode); |
| 239 | buf = udl_vidreg_unlock(buf); | 266 | buf = udl_vidreg_unlock(buf); |
| 240 | 267 | ||
| 268 | buf = udl_dummy_render(buf); | ||
| 241 | retval = udl_submit_urb(dev, urb, buf - (char *) | 269 | retval = udl_submit_urb(dev, urb, buf - (char *) |
| 242 | urb->transfer_buffer); | 270 | urb->transfer_buffer); |
| 243 | } else { | 271 | } else { |
| @@ -251,7 +279,7 @@ static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 251 | } | 279 | } |
| 252 | 280 | ||
| 253 | static bool udl_crtc_mode_fixup(struct drm_crtc *crtc, | 281 | static bool udl_crtc_mode_fixup(struct drm_crtc *crtc, |
| 254 | struct drm_display_mode *mode, | 282 | const struct drm_display_mode *mode, |
| 255 | struct drm_display_mode *adjusted_mode) | 283 | struct drm_display_mode *adjusted_mode) |
| 256 | 284 | ||
| 257 | { | 285 | { |
| @@ -306,9 +334,11 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc, | |||
| 306 | wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay); | 334 | wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay); |
| 307 | 335 | ||
| 308 | wrptr = udl_set_vid_cmds(wrptr, adjusted_mode); | 336 | wrptr = udl_set_vid_cmds(wrptr, adjusted_mode); |
| 309 | wrptr = udl_enable_hvsync(wrptr, true); | 337 | wrptr = udl_set_blank(wrptr, DRM_MODE_DPMS_ON); |
| 310 | wrptr = udl_vidreg_unlock(wrptr); | 338 | wrptr = udl_vidreg_unlock(wrptr); |
| 311 | 339 | ||
| 340 | wrptr = udl_dummy_render(wrptr); | ||
| 341 | |||
| 312 | ufb->active_16 = true; | 342 | ufb->active_16 = true; |
| 313 | if (old_fb) { | 343 | if (old_fb) { |
| 314 | struct udl_framebuffer *uold_fb = to_udl_fb(old_fb); | 344 | struct udl_framebuffer *uold_fb = to_udl_fb(old_fb); |
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index 02661f35f7a0..e927b4c052f5 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c | |||
| @@ -75,6 +75,7 @@ static struct drm_driver driver = { | |||
| 75 | .load = via_driver_load, | 75 | .load = via_driver_load, |
| 76 | .unload = via_driver_unload, | 76 | .unload = via_driver_unload, |
| 77 | .open = via_driver_open, | 77 | .open = via_driver_open, |
| 78 | .preclose = via_reclaim_buffers_locked, | ||
| 78 | .postclose = via_driver_postclose, | 79 | .postclose = via_driver_postclose, |
| 79 | .context_dtor = via_final_context, | 80 | .context_dtor = via_final_context, |
| 80 | .get_vblank_counter = via_get_vblank_counter, | 81 | .get_vblank_counter = via_get_vblank_counter, |
| @@ -85,9 +86,6 @@ static struct drm_driver driver = { | |||
| 85 | .irq_uninstall = via_driver_irq_uninstall, | 86 | .irq_uninstall = via_driver_irq_uninstall, |
| 86 | .irq_handler = via_driver_irq_handler, | 87 | .irq_handler = via_driver_irq_handler, |
| 87 | .dma_quiescent = via_driver_dma_quiescent, | 88 | .dma_quiescent = via_driver_dma_quiescent, |
| 88 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 89 | .reclaim_buffers_locked = NULL, | ||
| 90 | .reclaim_buffers_idlelocked = via_reclaim_buffers_locked, | ||
| 91 | .lastclose = via_lastclose, | 89 | .lastclose = via_lastclose, |
| 92 | .ioctls = via_ioctls, | 90 | .ioctls = via_ioctls, |
| 93 | .fops = &via_driver_fops, | 91 | .fops = &via_driver_fops, |
diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c index a3574d09a07d..acfcb358e7b7 100644 --- a/drivers/gpu/drm/via/via_mm.c +++ b/drivers/gpu/drm/via/via_mm.c | |||
| @@ -215,14 +215,20 @@ void via_reclaim_buffers_locked(struct drm_device *dev, | |||
| 215 | struct via_file_private *file_priv = file->driver_priv; | 215 | struct via_file_private *file_priv = file->driver_priv; |
| 216 | struct via_memblock *entry, *next; | 216 | struct via_memblock *entry, *next; |
| 217 | 217 | ||
| 218 | if (!(file->minor->master && file->master->lock.hw_lock)) | ||
| 219 | return; | ||
| 220 | |||
| 221 | drm_idlelock_take(&file->master->lock); | ||
| 222 | |||
| 218 | mutex_lock(&dev->struct_mutex); | 223 | mutex_lock(&dev->struct_mutex); |
| 219 | if (list_empty(&file_priv->obj_list)) { | 224 | if (list_empty(&file_priv->obj_list)) { |
| 220 | mutex_unlock(&dev->struct_mutex); | 225 | mutex_unlock(&dev->struct_mutex); |
| 226 | drm_idlelock_release(&file->master->lock); | ||
| 227 | |||
| 221 | return; | 228 | return; |
| 222 | } | 229 | } |
| 223 | 230 | ||
| 224 | if (dev->driver->dma_quiescent) | 231 | via_driver_dma_quiescent(dev); |
| 225 | dev->driver->dma_quiescent(dev); | ||
| 226 | 232 | ||
| 227 | list_for_each_entry_safe(entry, next, &file_priv->obj_list, | 233 | list_for_each_entry_safe(entry, next, &file_priv->obj_list, |
| 228 | owner_list) { | 234 | owner_list) { |
| @@ -231,5 +237,8 @@ void via_reclaim_buffers_locked(struct drm_device *dev, | |||
| 231 | kfree(entry); | 237 | kfree(entry); |
| 232 | } | 238 | } |
| 233 | mutex_unlock(&dev->struct_mutex); | 239 | mutex_unlock(&dev->struct_mutex); |
| 240 | |||
| 241 | drm_idlelock_release(&file->master->lock); | ||
| 242 | |||
| 234 | return; | 243 | return; |
| 235 | } | 244 | } |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index ee24d216aa85..4d9edead01ac 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
| @@ -769,10 +769,7 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv) | |||
| 769 | goto out_no_tfile; | 769 | goto out_no_tfile; |
| 770 | 770 | ||
| 771 | file_priv->driver_priv = vmw_fp; | 771 | file_priv->driver_priv = vmw_fp; |
| 772 | 772 | dev_priv->bdev.dev_mapping = dev->dev_mapping; | |
| 773 | if (unlikely(dev_priv->bdev.dev_mapping == NULL)) | ||
| 774 | dev_priv->bdev.dev_mapping = | ||
| 775 | file_priv->filp->f_path.dentry->d_inode->i_mapping; | ||
| 776 | 773 | ||
| 777 | return 0; | 774 | return 0; |
| 778 | 775 | ||
| @@ -1147,7 +1144,6 @@ static struct drm_driver driver = { | |||
| 1147 | .get_vblank_counter = vmw_get_vblank_counter, | 1144 | .get_vblank_counter = vmw_get_vblank_counter, |
| 1148 | .enable_vblank = vmw_enable_vblank, | 1145 | .enable_vblank = vmw_enable_vblank, |
| 1149 | .disable_vblank = vmw_disable_vblank, | 1146 | .disable_vblank = vmw_disable_vblank, |
| 1150 | .reclaim_buffers_locked = NULL, | ||
| 1151 | .ioctls = vmw_ioctls, | 1147 | .ioctls = vmw_ioctls, |
| 1152 | .num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls), | 1148 | .num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls), |
| 1153 | .dma_quiescent = NULL, /*vmw_dma_quiescent, */ | 1149 | .dma_quiescent = NULL, /*vmw_dma_quiescent, */ |
diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index 8b864afb40b6..62e0022561bc 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c | |||
| @@ -60,7 +60,7 @@ static void omap_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | static bool omap_crtc_mode_fixup(struct drm_crtc *crtc, | 62 | static bool omap_crtc_mode_fixup(struct drm_crtc *crtc, |
| 63 | struct drm_display_mode *mode, | 63 | const struct drm_display_mode *mode, |
| 64 | struct drm_display_mode *adjusted_mode) | 64 | struct drm_display_mode *adjusted_mode) |
| 65 | { | 65 | { |
| 66 | return true; | 66 | return true; |
diff --git a/drivers/staging/omapdrm/omap_encoder.c b/drivers/staging/omapdrm/omap_encoder.c index 06c52cb62d2f..31c735d39217 100644 --- a/drivers/staging/omapdrm/omap_encoder.c +++ b/drivers/staging/omapdrm/omap_encoder.c | |||
| @@ -48,7 +48,7 @@ static void omap_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, | 50 | static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, |
| 51 | struct drm_display_mode *mode, | 51 | const struct drm_display_mode *mode, |
| 52 | struct drm_display_mode *adjusted_mode) | 52 | struct drm_display_mode *adjusted_mode) |
| 53 | { | 53 | { |
| 54 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | 54 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 31ad880ca2ef..d6b67bb9075f 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
| @@ -348,7 +348,6 @@ struct drm_buf { | |||
| 348 | struct drm_buf *next; /**< Kernel-only: used for free list */ | 348 | struct drm_buf *next; /**< Kernel-only: used for free list */ |
| 349 | __volatile__ int waiting; /**< On kernel DMA queue */ | 349 | __volatile__ int waiting; /**< On kernel DMA queue */ |
| 350 | __volatile__ int pending; /**< On hardware DMA queue */ | 350 | __volatile__ int pending; /**< On hardware DMA queue */ |
| 351 | wait_queue_head_t dma_wait; /**< Processes waiting */ | ||
| 352 | struct drm_file *file_priv; /**< Private of holding file descr */ | 351 | struct drm_file *file_priv; /**< Private of holding file descr */ |
| 353 | int context; /**< Kernel queue for this buffer */ | 352 | int context; /**< Kernel queue for this buffer */ |
| 354 | int while_locked; /**< Dispatch this buffer while locked */ | 353 | int while_locked; /**< Dispatch this buffer while locked */ |
| @@ -876,12 +875,6 @@ struct drm_driver { | |||
| 876 | void (*irq_preinstall) (struct drm_device *dev); | 875 | void (*irq_preinstall) (struct drm_device *dev); |
| 877 | int (*irq_postinstall) (struct drm_device *dev); | 876 | int (*irq_postinstall) (struct drm_device *dev); |
| 878 | void (*irq_uninstall) (struct drm_device *dev); | 877 | void (*irq_uninstall) (struct drm_device *dev); |
| 879 | void (*reclaim_buffers) (struct drm_device *dev, | ||
| 880 | struct drm_file * file_priv); | ||
| 881 | void (*reclaim_buffers_locked) (struct drm_device *dev, | ||
| 882 | struct drm_file *file_priv); | ||
| 883 | void (*reclaim_buffers_idlelocked) (struct drm_device *dev, | ||
| 884 | struct drm_file *file_priv); | ||
| 885 | void (*set_version) (struct drm_device *dev, | 878 | void (*set_version) (struct drm_device *dev, |
| 886 | struct drm_set_version *sv); | 879 | struct drm_set_version *sv); |
| 887 | 880 | ||
| @@ -1108,12 +1101,8 @@ struct drm_device { | |||
| 1108 | 1101 | ||
| 1109 | /*@} */ | 1102 | /*@} */ |
| 1110 | 1103 | ||
| 1111 | /** \name DMA queues (contexts) */ | 1104 | /** \name DMA support */ |
| 1112 | /*@{ */ | 1105 | /*@{ */ |
| 1113 | int queue_count; /**< Number of active DMA queues */ | ||
| 1114 | int queue_reserved; /**< Number of reserved DMA queues */ | ||
| 1115 | int queue_slots; /**< Actual length of queuelist */ | ||
| 1116 | struct drm_queue **queuelist; /**< Vector of pointers to DMA queues */ | ||
| 1117 | struct drm_device_dma *dma; /**< Optional pointer for DMA support */ | 1106 | struct drm_device_dma *dma; /**< Optional pointer for DMA support */ |
| 1118 | /*@} */ | 1107 | /*@} */ |
| 1119 | 1108 | ||
| @@ -1540,7 +1529,6 @@ extern int drm_debugfs_cleanup(struct drm_minor *minor); | |||
| 1540 | /* Info file support */ | 1529 | /* Info file support */ |
| 1541 | extern int drm_name_info(struct seq_file *m, void *data); | 1530 | extern int drm_name_info(struct seq_file *m, void *data); |
| 1542 | extern int drm_vm_info(struct seq_file *m, void *data); | 1531 | extern int drm_vm_info(struct seq_file *m, void *data); |
| 1543 | extern int drm_queues_info(struct seq_file *m, void *data); | ||
| 1544 | extern int drm_bufs_info(struct seq_file *m, void *data); | 1532 | extern int drm_bufs_info(struct seq_file *m, void *data); |
| 1545 | extern int drm_vblank_info(struct seq_file *m, void *data); | 1533 | extern int drm_vblank_info(struct seq_file *m, void *data); |
| 1546 | extern int drm_clients_info(struct seq_file *m, void* data); | 1534 | extern int drm_clients_info(struct seq_file *m, void* data); |
| @@ -1761,6 +1749,11 @@ extern int drm_get_pci_dev(struct pci_dev *pdev, | |||
| 1761 | const struct pci_device_id *ent, | 1749 | const struct pci_device_id *ent, |
| 1762 | struct drm_driver *driver); | 1750 | struct drm_driver *driver); |
| 1763 | 1751 | ||
| 1752 | #define DRM_PCIE_SPEED_25 1 | ||
| 1753 | #define DRM_PCIE_SPEED_50 2 | ||
| 1754 | #define DRM_PCIE_SPEED_80 4 | ||
| 1755 | |||
| 1756 | extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask); | ||
| 1764 | 1757 | ||
| 1765 | /* platform section */ | 1758 | /* platform section */ |
| 1766 | extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device); | 1759 | extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device); |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index bac55c215113..a1a0386e0160 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
| @@ -676,8 +676,6 @@ struct drm_plane { | |||
| 676 | * This is used to set modes. | 676 | * This is used to set modes. |
| 677 | */ | 677 | */ |
| 678 | struct drm_mode_set { | 678 | struct drm_mode_set { |
| 679 | struct list_head head; | ||
| 680 | |||
| 681 | struct drm_framebuffer *fb; | 679 | struct drm_framebuffer *fb; |
| 682 | struct drm_crtc *crtc; | 680 | struct drm_crtc *crtc; |
| 683 | struct drm_display_mode *mode; | 681 | struct drm_display_mode *mode; |
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 7988e55c98d0..e01cc80c9c30 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h | |||
| @@ -62,7 +62,7 @@ struct drm_crtc_helper_funcs { | |||
| 62 | 62 | ||
| 63 | /* Provider can fixup or change mode timings before modeset occurs */ | 63 | /* Provider can fixup or change mode timings before modeset occurs */ |
| 64 | bool (*mode_fixup)(struct drm_crtc *crtc, | 64 | bool (*mode_fixup)(struct drm_crtc *crtc, |
| 65 | struct drm_display_mode *mode, | 65 | const struct drm_display_mode *mode, |
| 66 | struct drm_display_mode *adjusted_mode); | 66 | struct drm_display_mode *adjusted_mode); |
| 67 | /* Actually set the mode */ | 67 | /* Actually set the mode */ |
| 68 | int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, | 68 | int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, |
| @@ -96,7 +96,7 @@ struct drm_encoder_helper_funcs { | |||
| 96 | void (*restore)(struct drm_encoder *encoder); | 96 | void (*restore)(struct drm_encoder *encoder); |
| 97 | 97 | ||
| 98 | bool (*mode_fixup)(struct drm_encoder *encoder, | 98 | bool (*mode_fixup)(struct drm_encoder *encoder, |
| 99 | struct drm_display_mode *mode, | 99 | const struct drm_display_mode *mode, |
| 100 | struct drm_display_mode *adjusted_mode); | 100 | struct drm_display_mode *adjusted_mode); |
| 101 | void (*prepare)(struct drm_encoder *encoder); | 101 | void (*prepare)(struct drm_encoder *encoder); |
| 102 | void (*commit)(struct drm_encoder *encoder); | 102 | void (*commit)(struct drm_encoder *encoder); |
diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h index 2f65633d28a7..7dc385233805 100644 --- a/include/drm/drm_encoder_slave.h +++ b/include/drm/drm_encoder_slave.h | |||
| @@ -54,7 +54,7 @@ struct drm_encoder_slave_funcs { | |||
| 54 | void (*save)(struct drm_encoder *encoder); | 54 | void (*save)(struct drm_encoder *encoder); |
| 55 | void (*restore)(struct drm_encoder *encoder); | 55 | void (*restore)(struct drm_encoder *encoder); |
| 56 | bool (*mode_fixup)(struct drm_encoder *encoder, | 56 | bool (*mode_fixup)(struct drm_encoder *encoder, |
| 57 | struct drm_display_mode *mode, | 57 | const struct drm_display_mode *mode, |
| 58 | struct drm_display_mode *adjusted_mode); | 58 | struct drm_display_mode *adjusted_mode); |
| 59 | int (*mode_valid)(struct drm_encoder *encoder, | 59 | int (*mode_valid)(struct drm_encoder *encoder, |
| 60 | struct drm_display_mode *mode); | 60 | struct drm_display_mode *mode); |
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 564b14aa7e16..06d7f798a08c 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h | |||
| @@ -50,6 +50,7 @@ struct drm_mm_node { | |||
| 50 | unsigned scanned_next_free : 1; | 50 | unsigned scanned_next_free : 1; |
| 51 | unsigned scanned_preceeds_hole : 1; | 51 | unsigned scanned_preceeds_hole : 1; |
| 52 | unsigned allocated : 1; | 52 | unsigned allocated : 1; |
| 53 | unsigned long color; | ||
| 53 | unsigned long start; | 54 | unsigned long start; |
| 54 | unsigned long size; | 55 | unsigned long size; |
| 55 | struct drm_mm *mm; | 56 | struct drm_mm *mm; |
| @@ -66,6 +67,7 @@ struct drm_mm { | |||
| 66 | spinlock_t unused_lock; | 67 | spinlock_t unused_lock; |
| 67 | unsigned int scan_check_range : 1; | 68 | unsigned int scan_check_range : 1; |
| 68 | unsigned scan_alignment; | 69 | unsigned scan_alignment; |
| 70 | unsigned long scan_color; | ||
| 69 | unsigned long scan_size; | 71 | unsigned long scan_size; |
| 70 | unsigned long scan_hit_start; | 72 | unsigned long scan_hit_start; |
| 71 | unsigned scan_hit_size; | 73 | unsigned scan_hit_size; |
| @@ -73,6 +75,9 @@ struct drm_mm { | |||
| 73 | unsigned long scan_start; | 75 | unsigned long scan_start; |
| 74 | unsigned long scan_end; | 76 | unsigned long scan_end; |
| 75 | struct drm_mm_node *prev_scanned_node; | 77 | struct drm_mm_node *prev_scanned_node; |
| 78 | |||
| 79 | void (*color_adjust)(struct drm_mm_node *node, unsigned long color, | ||
| 80 | unsigned long *start, unsigned long *end); | ||
| 76 | }; | 81 | }; |
| 77 | 82 | ||
| 78 | static inline bool drm_mm_node_allocated(struct drm_mm_node *node) | 83 | static inline bool drm_mm_node_allocated(struct drm_mm_node *node) |
| @@ -100,11 +105,13 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) | |||
| 100 | extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, | 105 | extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, |
| 101 | unsigned long size, | 106 | unsigned long size, |
| 102 | unsigned alignment, | 107 | unsigned alignment, |
| 108 | unsigned long color, | ||
| 103 | int atomic); | 109 | int atomic); |
| 104 | extern struct drm_mm_node *drm_mm_get_block_range_generic( | 110 | extern struct drm_mm_node *drm_mm_get_block_range_generic( |
| 105 | struct drm_mm_node *node, | 111 | struct drm_mm_node *node, |
| 106 | unsigned long size, | 112 | unsigned long size, |
| 107 | unsigned alignment, | 113 | unsigned alignment, |
| 114 | unsigned long color, | ||
| 108 | unsigned long start, | 115 | unsigned long start, |
| 109 | unsigned long end, | 116 | unsigned long end, |
| 110 | int atomic); | 117 | int atomic); |
| @@ -112,13 +119,13 @@ static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent, | |||
| 112 | unsigned long size, | 119 | unsigned long size, |
| 113 | unsigned alignment) | 120 | unsigned alignment) |
| 114 | { | 121 | { |
| 115 | return drm_mm_get_block_generic(parent, size, alignment, 0); | 122 | return drm_mm_get_block_generic(parent, size, alignment, 0, 0); |
| 116 | } | 123 | } |
| 117 | static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent, | 124 | static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent, |
| 118 | unsigned long size, | 125 | unsigned long size, |
| 119 | unsigned alignment) | 126 | unsigned alignment) |
| 120 | { | 127 | { |
| 121 | return drm_mm_get_block_generic(parent, size, alignment, 1); | 128 | return drm_mm_get_block_generic(parent, size, alignment, 0, 1); |
| 122 | } | 129 | } |
| 123 | static inline struct drm_mm_node *drm_mm_get_block_range( | 130 | static inline struct drm_mm_node *drm_mm_get_block_range( |
| 124 | struct drm_mm_node *parent, | 131 | struct drm_mm_node *parent, |
| @@ -127,8 +134,19 @@ static inline struct drm_mm_node *drm_mm_get_block_range( | |||
| 127 | unsigned long start, | 134 | unsigned long start, |
| 128 | unsigned long end) | 135 | unsigned long end) |
| 129 | { | 136 | { |
| 130 | return drm_mm_get_block_range_generic(parent, size, alignment, | 137 | return drm_mm_get_block_range_generic(parent, size, alignment, 0, |
| 131 | start, end, 0); | 138 | start, end, 0); |
| 139 | } | ||
| 140 | static inline struct drm_mm_node *drm_mm_get_color_block_range( | ||
| 141 | struct drm_mm_node *parent, | ||
| 142 | unsigned long size, | ||
| 143 | unsigned alignment, | ||
| 144 | unsigned long color, | ||
| 145 | unsigned long start, | ||
| 146 | unsigned long end) | ||
| 147 | { | ||
| 148 | return drm_mm_get_block_range_generic(parent, size, alignment, color, | ||
| 149 | start, end, 0); | ||
| 132 | } | 150 | } |
| 133 | static inline struct drm_mm_node *drm_mm_get_block_atomic_range( | 151 | static inline struct drm_mm_node *drm_mm_get_block_atomic_range( |
| 134 | struct drm_mm_node *parent, | 152 | struct drm_mm_node *parent, |
| @@ -137,7 +155,7 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic_range( | |||
| 137 | unsigned long start, | 155 | unsigned long start, |
| 138 | unsigned long end) | 156 | unsigned long end) |
| 139 | { | 157 | { |
| 140 | return drm_mm_get_block_range_generic(parent, size, alignment, | 158 | return drm_mm_get_block_range_generic(parent, size, alignment, 0, |
| 141 | start, end, 1); | 159 | start, end, 1); |
| 142 | } | 160 | } |
| 143 | extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, | 161 | extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, |
| @@ -149,18 +167,59 @@ extern int drm_mm_insert_node_in_range(struct drm_mm *mm, | |||
| 149 | extern void drm_mm_put_block(struct drm_mm_node *cur); | 167 | extern void drm_mm_put_block(struct drm_mm_node *cur); |
| 150 | extern void drm_mm_remove_node(struct drm_mm_node *node); | 168 | extern void drm_mm_remove_node(struct drm_mm_node *node); |
| 151 | extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); | 169 | extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); |
| 152 | extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | 170 | extern struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, |
| 153 | unsigned long size, | 171 | unsigned long size, |
| 154 | unsigned alignment, | 172 | unsigned alignment, |
| 155 | int best_match); | 173 | unsigned long color, |
| 156 | extern struct drm_mm_node *drm_mm_search_free_in_range( | 174 | bool best_match); |
| 175 | extern struct drm_mm_node *drm_mm_search_free_in_range_generic( | ||
| 176 | const struct drm_mm *mm, | ||
| 177 | unsigned long size, | ||
| 178 | unsigned alignment, | ||
| 179 | unsigned long color, | ||
| 180 | unsigned long start, | ||
| 181 | unsigned long end, | ||
| 182 | bool best_match); | ||
| 183 | static inline struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | ||
| 184 | unsigned long size, | ||
| 185 | unsigned alignment, | ||
| 186 | bool best_match) | ||
| 187 | { | ||
| 188 | return drm_mm_search_free_generic(mm,size, alignment, 0, best_match); | ||
| 189 | } | ||
| 190 | static inline struct drm_mm_node *drm_mm_search_free_in_range( | ||
| 157 | const struct drm_mm *mm, | 191 | const struct drm_mm *mm, |
| 158 | unsigned long size, | 192 | unsigned long size, |
| 159 | unsigned alignment, | 193 | unsigned alignment, |
| 160 | unsigned long start, | 194 | unsigned long start, |
| 161 | unsigned long end, | 195 | unsigned long end, |
| 162 | int best_match); | 196 | bool best_match) |
| 163 | extern int drm_mm_init(struct drm_mm *mm, unsigned long start, | 197 | { |
| 198 | return drm_mm_search_free_in_range_generic(mm, size, alignment, 0, | ||
| 199 | start, end, best_match); | ||
| 200 | } | ||
| 201 | static inline struct drm_mm_node *drm_mm_search_free_color(const struct drm_mm *mm, | ||
| 202 | unsigned long size, | ||
| 203 | unsigned alignment, | ||
| 204 | unsigned long color, | ||
| 205 | bool best_match) | ||
| 206 | { | ||
| 207 | return drm_mm_search_free_generic(mm,size, alignment, color, best_match); | ||
| 208 | } | ||
| 209 | static inline struct drm_mm_node *drm_mm_search_free_in_range_color( | ||
| 210 | const struct drm_mm *mm, | ||
| 211 | unsigned long size, | ||
| 212 | unsigned alignment, | ||
| 213 | unsigned long color, | ||
| 214 | unsigned long start, | ||
| 215 | unsigned long end, | ||
| 216 | bool best_match) | ||
| 217 | { | ||
| 218 | return drm_mm_search_free_in_range_generic(mm, size, alignment, color, | ||
| 219 | start, end, best_match); | ||
| 220 | } | ||
| 221 | extern int drm_mm_init(struct drm_mm *mm, | ||
| 222 | unsigned long start, | ||
| 164 | unsigned long size); | 223 | unsigned long size); |
| 165 | extern void drm_mm_takedown(struct drm_mm *mm); | 224 | extern void drm_mm_takedown(struct drm_mm *mm); |
| 166 | extern int drm_mm_clean(struct drm_mm *mm); | 225 | extern int drm_mm_clean(struct drm_mm *mm); |
| @@ -171,10 +230,14 @@ static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block) | |||
| 171 | return block->mm; | 230 | return block->mm; |
| 172 | } | 231 | } |
| 173 | 232 | ||
| 174 | void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, | 233 | void drm_mm_init_scan(struct drm_mm *mm, |
| 175 | unsigned alignment); | 234 | unsigned long size, |
| 176 | void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size, | 235 | unsigned alignment, |
| 236 | unsigned long color); | ||
| 237 | void drm_mm_init_scan_with_range(struct drm_mm *mm, | ||
| 238 | unsigned long size, | ||
| 177 | unsigned alignment, | 239 | unsigned alignment, |
| 240 | unsigned long color, | ||
| 178 | unsigned long start, | 241 | unsigned long start, |
| 179 | unsigned long end); | 242 | unsigned long end); |
| 180 | int drm_mm_scan_add_block(struct drm_mm_node *node); | 243 | int drm_mm_scan_add_block(struct drm_mm_node *node); |
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index a7aec391b7b7..7ff5c99b1638 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h | |||
| @@ -686,14 +686,6 @@ | |||
| 686 | {0x8086, 0x1132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 686 | {0x8086, 0x1132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 687 | {0, 0, 0} | 687 | {0, 0, 0} |
| 688 | 688 | ||
| 689 | #define i830_PCI_IDS \ | ||
| 690 | {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 691 | {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 692 | {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 693 | {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 694 | {0x8086, 0x358e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 695 | {0, 0, 0} | ||
| 696 | |||
| 697 | #define gamma_PCI_IDS \ | 689 | #define gamma_PCI_IDS \ |
| 698 | {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 690 | {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 699 | {0, 0, 0} | 691 | {0, 0, 0} |
| @@ -726,37 +718,3 @@ | |||
| 726 | 718 | ||
| 727 | #define ffb_PCI_IDS \ | 719 | #define ffb_PCI_IDS \ |
| 728 | {0, 0, 0} | 720 | {0, 0, 0} |
| 729 | |||
| 730 | #define i915_PCI_IDS \ | ||
| 731 | {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 732 | {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 733 | {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 734 | {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 735 | {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 736 | {0x8086, 0x258a, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 737 | {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 738 | {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 739 | {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 740 | {0x8086, 0x27ae, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 741 | {0x8086, 0x2972, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 742 | {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 743 | {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 744 | {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 745 | {0x8086, 0x29b2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 746 | {0x8086, 0x29c2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 747 | {0x8086, 0x29d2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 748 | {0x8086, 0x2a02, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 749 | {0x8086, 0x2a12, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 750 | {0x8086, 0x2a42, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 751 | {0x8086, 0x2e02, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 752 | {0x8086, 0x2e12, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 753 | {0x8086, 0x2e22, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 754 | {0x8086, 0x2e32, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 755 | {0x8086, 0x2e42, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 756 | {0x8086, 0xa001, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 757 | {0x8086, 0xa011, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 758 | {0x8086, 0x35e8, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 759 | {0x8086, 0x0042, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 760 | {0x8086, 0x0046, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 761 | {0x8086, 0x0102, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 762 | {0, 0, 0} | ||
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index f3f82242bf1d..8cc70837f929 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h | |||
| @@ -200,6 +200,9 @@ typedef struct _drm_i915_sarea { | |||
| 200 | #define DRM_I915_GEM_EXECBUFFER2 0x29 | 200 | #define DRM_I915_GEM_EXECBUFFER2 0x29 |
| 201 | #define DRM_I915_GET_SPRITE_COLORKEY 0x2a | 201 | #define DRM_I915_GET_SPRITE_COLORKEY 0x2a |
| 202 | #define DRM_I915_SET_SPRITE_COLORKEY 0x2b | 202 | #define DRM_I915_SET_SPRITE_COLORKEY 0x2b |
| 203 | #define DRM_I915_GEM_WAIT 0x2c | ||
| 204 | #define DRM_I915_GEM_CONTEXT_CREATE 0x2d | ||
| 205 | #define DRM_I915_GEM_CONTEXT_DESTROY 0x2e | ||
| 203 | 206 | ||
| 204 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) | 207 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) |
| 205 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) | 208 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) |
| @@ -243,6 +246,9 @@ typedef struct _drm_i915_sarea { | |||
| 243 | #define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) | 246 | #define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) |
| 244 | #define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) | 247 | #define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) |
| 245 | #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) | 248 | #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) |
| 249 | #define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait) | ||
| 250 | #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create) | ||
| 251 | #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy) | ||
| 246 | 252 | ||
| 247 | /* Allow drivers to submit batchbuffers directly to hardware, relying | 253 | /* Allow drivers to submit batchbuffers directly to hardware, relying |
| 248 | * on the security mechanisms provided by hardware. | 254 | * on the security mechanisms provided by hardware. |
| @@ -298,6 +304,7 @@ typedef struct drm_i915_irq_wait { | |||
| 298 | #define I915_PARAM_HAS_GEN7_SOL_RESET 16 | 304 | #define I915_PARAM_HAS_GEN7_SOL_RESET 16 |
| 299 | #define I915_PARAM_HAS_LLC 17 | 305 | #define I915_PARAM_HAS_LLC 17 |
| 300 | #define I915_PARAM_HAS_ALIASING_PPGTT 18 | 306 | #define I915_PARAM_HAS_ALIASING_PPGTT 18 |
| 307 | #define I915_PARAM_HAS_WAIT_TIMEOUT 19 | ||
| 301 | 308 | ||
| 302 | typedef struct drm_i915_getparam { | 309 | typedef struct drm_i915_getparam { |
| 303 | int param; | 310 | int param; |
| @@ -656,13 +663,19 @@ struct drm_i915_gem_execbuffer2 { | |||
| 656 | #define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) | 663 | #define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) |
| 657 | #define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ | 664 | #define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ |
| 658 | __u64 flags; | 665 | __u64 flags; |
| 659 | __u64 rsvd1; | 666 | __u64 rsvd1; /* now used for context info */ |
| 660 | __u64 rsvd2; | 667 | __u64 rsvd2; |
| 661 | }; | 668 | }; |
| 662 | 669 | ||
| 663 | /** Resets the SO write offset registers for transform feedback on gen7. */ | 670 | /** Resets the SO write offset registers for transform feedback on gen7. */ |
| 664 | #define I915_EXEC_GEN7_SOL_RESET (1<<8) | 671 | #define I915_EXEC_GEN7_SOL_RESET (1<<8) |
| 665 | 672 | ||
| 673 | #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) | ||
| 674 | #define i915_execbuffer2_set_context_id(eb2, context) \ | ||
| 675 | (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK | ||
| 676 | #define i915_execbuffer2_get_context_id(eb2) \ | ||
| 677 | ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK) | ||
| 678 | |||
| 666 | struct drm_i915_gem_pin { | 679 | struct drm_i915_gem_pin { |
| 667 | /** Handle of the buffer to be pinned. */ | 680 | /** Handle of the buffer to be pinned. */ |
| 668 | __u32 handle; | 681 | __u32 handle; |
| @@ -886,4 +899,23 @@ struct drm_intel_sprite_colorkey { | |||
| 886 | __u32 flags; | 899 | __u32 flags; |
| 887 | }; | 900 | }; |
| 888 | 901 | ||
| 902 | struct drm_i915_gem_wait { | ||
| 903 | /** Handle of BO we shall wait on */ | ||
| 904 | __u32 bo_handle; | ||
| 905 | __u32 flags; | ||
| 906 | /** Number of nanoseconds to wait, Returns time remaining. */ | ||
| 907 | __s64 timeout_ns; | ||
| 908 | }; | ||
| 909 | |||
| 910 | struct drm_i915_gem_context_create { | ||
| 911 | /* output: id of new context*/ | ||
| 912 | __u32 ctx_id; | ||
| 913 | __u32 pad; | ||
| 914 | }; | ||
| 915 | |||
| 916 | struct drm_i915_gem_context_destroy { | ||
| 917 | __u32 ctx_id; | ||
| 918 | __u32 pad; | ||
| 919 | }; | ||
| 920 | |||
| 889 | #endif /* _I915_DRM_H_ */ | 921 | #endif /* _I915_DRM_H_ */ |
diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 923afb5dcf0c..8e29d551bb3c 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h | |||
| @@ -19,8 +19,16 @@ const struct intel_gtt { | |||
| 19 | dma_addr_t scratch_page_dma; | 19 | dma_addr_t scratch_page_dma; |
| 20 | /* for ppgtt PDE access */ | 20 | /* for ppgtt PDE access */ |
| 21 | u32 __iomem *gtt; | 21 | u32 __iomem *gtt; |
| 22 | /* needed for ioremap in drm/i915 */ | ||
| 23 | phys_addr_t gma_bus_addr; | ||
| 22 | } *intel_gtt_get(void); | 24 | } *intel_gtt_get(void); |
| 23 | 25 | ||
| 26 | int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, | ||
| 27 | struct agp_bridge_data *bridge); | ||
| 28 | void intel_gmch_remove(void); | ||
| 29 | |||
| 30 | bool intel_enable_gtt(void); | ||
| 31 | |||
| 24 | void intel_gtt_chipset_flush(void); | 32 | void intel_gtt_chipset_flush(void); |
| 25 | void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg); | 33 | void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg); |
| 26 | void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries); | 34 | void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries); |
diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h index 5edd3a76fffa..2a5769fdf8ba 100644 --- a/include/drm/nouveau_drm.h +++ b/include/drm/nouveau_drm.h | |||
| @@ -25,70 +25,6 @@ | |||
| 25 | #ifndef __NOUVEAU_DRM_H__ | 25 | #ifndef __NOUVEAU_DRM_H__ |
| 26 | #define __NOUVEAU_DRM_H__ | 26 | #define __NOUVEAU_DRM_H__ |
| 27 | 27 | ||
| 28 | #define NOUVEAU_DRM_HEADER_PATCHLEVEL 16 | ||
| 29 | |||
| 30 | struct drm_nouveau_channel_alloc { | ||
| 31 | uint32_t fb_ctxdma_handle; | ||
| 32 | uint32_t tt_ctxdma_handle; | ||
| 33 | |||
| 34 | int channel; | ||
| 35 | uint32_t pushbuf_domains; | ||
| 36 | |||
| 37 | /* Notifier memory */ | ||
| 38 | uint32_t notifier_handle; | ||
| 39 | |||
| 40 | /* DRM-enforced subchannel assignments */ | ||
| 41 | struct { | ||
| 42 | uint32_t handle; | ||
| 43 | uint32_t grclass; | ||
| 44 | } subchan[8]; | ||
| 45 | uint32_t nr_subchan; | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct drm_nouveau_channel_free { | ||
| 49 | int channel; | ||
| 50 | }; | ||
| 51 | |||
| 52 | struct drm_nouveau_grobj_alloc { | ||
| 53 | int channel; | ||
| 54 | uint32_t handle; | ||
| 55 | int class; | ||
| 56 | }; | ||
| 57 | |||
| 58 | struct drm_nouveau_notifierobj_alloc { | ||
| 59 | uint32_t channel; | ||
| 60 | uint32_t handle; | ||
| 61 | uint32_t size; | ||
| 62 | uint32_t offset; | ||
| 63 | }; | ||
| 64 | |||
| 65 | struct drm_nouveau_gpuobj_free { | ||
| 66 | int channel; | ||
| 67 | uint32_t handle; | ||
| 68 | }; | ||
| 69 | |||
| 70 | /* FIXME : maybe unify {GET,SET}PARAMs */ | ||
| 71 | #define NOUVEAU_GETPARAM_PCI_VENDOR 3 | ||
| 72 | #define NOUVEAU_GETPARAM_PCI_DEVICE 4 | ||
| 73 | #define NOUVEAU_GETPARAM_BUS_TYPE 5 | ||
| 74 | #define NOUVEAU_GETPARAM_FB_SIZE 8 | ||
| 75 | #define NOUVEAU_GETPARAM_AGP_SIZE 9 | ||
| 76 | #define NOUVEAU_GETPARAM_CHIPSET_ID 11 | ||
| 77 | #define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 | ||
| 78 | #define NOUVEAU_GETPARAM_GRAPH_UNITS 13 | ||
| 79 | #define NOUVEAU_GETPARAM_PTIMER_TIME 14 | ||
| 80 | #define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 | ||
| 81 | #define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 | ||
| 82 | struct drm_nouveau_getparam { | ||
| 83 | uint64_t param; | ||
| 84 | uint64_t value; | ||
| 85 | }; | ||
| 86 | |||
| 87 | struct drm_nouveau_setparam { | ||
| 88 | uint64_t param; | ||
| 89 | uint64_t value; | ||
| 90 | }; | ||
| 91 | |||
| 92 | #define NOUVEAU_GEM_DOMAIN_CPU (1 << 0) | 28 | #define NOUVEAU_GEM_DOMAIN_CPU (1 << 0) |
| 93 | #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) | 29 | #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) |
| 94 | #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) | 30 | #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) |
| @@ -180,35 +116,19 @@ struct drm_nouveau_gem_cpu_fini { | |||
| 180 | uint32_t handle; | 116 | uint32_t handle; |
| 181 | }; | 117 | }; |
| 182 | 118 | ||
| 183 | enum nouveau_bus_type { | 119 | #define DRM_NOUVEAU_GETPARAM 0x00 /* deprecated */ |
| 184 | NV_AGP = 0, | 120 | #define DRM_NOUVEAU_SETPARAM 0x01 /* deprecated */ |
| 185 | NV_PCI = 1, | 121 | #define DRM_NOUVEAU_CHANNEL_ALLOC 0x02 /* deprecated */ |
| 186 | NV_PCIE = 2, | 122 | #define DRM_NOUVEAU_CHANNEL_FREE 0x03 /* deprecated */ |
| 187 | }; | 123 | #define DRM_NOUVEAU_GROBJ_ALLOC 0x04 /* deprecated */ |
| 188 | 124 | #define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x05 /* deprecated */ | |
| 189 | struct drm_nouveau_sarea { | 125 | #define DRM_NOUVEAU_GPUOBJ_FREE 0x06 /* deprecated */ |
| 190 | }; | ||
| 191 | |||
| 192 | #define DRM_NOUVEAU_GETPARAM 0x00 | ||
| 193 | #define DRM_NOUVEAU_SETPARAM 0x01 | ||
| 194 | #define DRM_NOUVEAU_CHANNEL_ALLOC 0x02 | ||
| 195 | #define DRM_NOUVEAU_CHANNEL_FREE 0x03 | ||
| 196 | #define DRM_NOUVEAU_GROBJ_ALLOC 0x04 | ||
| 197 | #define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x05 | ||
| 198 | #define DRM_NOUVEAU_GPUOBJ_FREE 0x06 | ||
| 199 | #define DRM_NOUVEAU_GEM_NEW 0x40 | 126 | #define DRM_NOUVEAU_GEM_NEW 0x40 |
| 200 | #define DRM_NOUVEAU_GEM_PUSHBUF 0x41 | 127 | #define DRM_NOUVEAU_GEM_PUSHBUF 0x41 |
| 201 | #define DRM_NOUVEAU_GEM_CPU_PREP 0x42 | 128 | #define DRM_NOUVEAU_GEM_CPU_PREP 0x42 |
| 202 | #define DRM_NOUVEAU_GEM_CPU_FINI 0x43 | 129 | #define DRM_NOUVEAU_GEM_CPU_FINI 0x43 |
| 203 | #define DRM_NOUVEAU_GEM_INFO 0x44 | 130 | #define DRM_NOUVEAU_GEM_INFO 0x44 |
| 204 | 131 | ||
| 205 | #define DRM_IOCTL_NOUVEAU_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GETPARAM, struct drm_nouveau_getparam) | ||
| 206 | #define DRM_IOCTL_NOUVEAU_SETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_SETPARAM, struct drm_nouveau_setparam) | ||
| 207 | #define DRM_IOCTL_NOUVEAU_CHANNEL_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_CHANNEL_ALLOC, struct drm_nouveau_channel_alloc) | ||
| 208 | #define DRM_IOCTL_NOUVEAU_CHANNEL_FREE DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_CHANNEL_FREE, struct drm_nouveau_channel_free) | ||
| 209 | #define DRM_IOCTL_NOUVEAU_GROBJ_ALLOC DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GROBJ_ALLOC, struct drm_nouveau_grobj_alloc) | ||
| 210 | #define DRM_IOCTL_NOUVEAU_NOTIFIEROBJ_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, struct drm_nouveau_notifierobj_alloc) | ||
| 211 | #define DRM_IOCTL_NOUVEAU_GPUOBJ_FREE DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GPUOBJ_FREE, struct drm_nouveau_gpuobj_free) | ||
| 212 | #define DRM_IOCTL_NOUVEAU_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_NEW, struct drm_nouveau_gem_new) | 132 | #define DRM_IOCTL_NOUVEAU_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_NEW, struct drm_nouveau_gem_new) |
| 213 | #define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_PUSHBUF, struct drm_nouveau_gem_pushbuf) | 133 | #define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_PUSHBUF, struct drm_nouveau_gem_pushbuf) |
| 214 | #define DRM_IOCTL_NOUVEAU_GEM_CPU_PREP DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_PREP, struct drm_nouveau_gem_cpu_prep) | 134 | #define DRM_IOCTL_NOUVEAU_GEM_CPU_PREP DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_PREP, struct drm_nouveau_gem_cpu_prep) |
diff --git a/include/drm/sis_drm.h b/include/drm/sis_drm.h index 035b804dda6d..df3763222d73 100644 --- a/include/drm/sis_drm.h +++ b/include/drm/sis_drm.h | |||
| @@ -51,17 +51,17 @@ | |||
| 51 | 51 | ||
| 52 | typedef struct { | 52 | typedef struct { |
| 53 | int context; | 53 | int context; |
| 54 | unsigned int offset; | 54 | unsigned long offset; |
| 55 | unsigned int size; | 55 | unsigned long size; |
| 56 | unsigned long free; | 56 | unsigned long free; |
| 57 | } drm_sis_mem_t; | 57 | } drm_sis_mem_t; |
| 58 | 58 | ||
| 59 | typedef struct { | 59 | typedef struct { |
| 60 | unsigned int offset, size; | 60 | unsigned long offset, size; |
| 61 | } drm_sis_agp_t; | 61 | } drm_sis_agp_t; |
| 62 | 62 | ||
| 63 | typedef struct { | 63 | typedef struct { |
| 64 | unsigned int offset, size; | 64 | unsigned long offset, size; |
| 65 | } drm_sis_fb_t; | 65 | } drm_sis_fb_t; |
| 66 | 66 | ||
| 67 | struct sis_file_private { | 67 | struct sis_file_private { |
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index a05f1b55714d..084e8989a6e1 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h | |||
| @@ -39,8 +39,6 @@ | |||
| 39 | #include "linux/fs.h" | 39 | #include "linux/fs.h" |
| 40 | #include "linux/spinlock.h" | 40 | #include "linux/spinlock.h" |
| 41 | 41 | ||
| 42 | struct ttm_backend; | ||
| 43 | |||
| 44 | struct ttm_backend_func { | 42 | struct ttm_backend_func { |
| 45 | /** | 43 | /** |
| 46 | * struct ttm_backend_func member bind | 44 | * struct ttm_backend_func member bind |
| @@ -119,7 +117,6 @@ struct ttm_tt { | |||
| 119 | unsigned long num_pages; | 117 | unsigned long num_pages; |
| 120 | struct sg_table *sg; /* for SG objects via dma-buf */ | 118 | struct sg_table *sg; /* for SG objects via dma-buf */ |
| 121 | struct ttm_bo_global *glob; | 119 | struct ttm_bo_global *glob; |
| 122 | struct ttm_backend *be; | ||
| 123 | struct file *swap_storage; | 120 | struct file *swap_storage; |
| 124 | enum ttm_caching_state caching_state; | 121 | enum ttm_caching_state caching_state; |
| 125 | enum { | 122 | enum { |
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index 53274bff5773..7fb75b143755 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h | |||
| @@ -543,6 +543,11 @@ | |||
| 543 | #define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */ | 543 | #define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */ |
| 544 | #define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ | 544 | #define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ |
| 545 | #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */ | 545 | #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */ |
| 546 | #define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */ | ||
| 547 | #define PCI_EXP_LNKCAP2_SLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */ | ||
| 548 | #define PCI_EXP_LNKCAP2_SLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */ | ||
| 549 | #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */ | ||
| 550 | #define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */ | ||
| 546 | #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ | 551 | #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ |
| 547 | #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ | 552 | #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ |
| 548 | 553 | ||
