diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 561 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600_blit_kms.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600d.h | 159 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_fence.c | 38 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_irq_kms.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770.c | 24 |
10 files changed, 754 insertions, 75 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 3dbd93e44345..5067ab7fdced 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -38,8 +38,10 @@ | |||
38 | 38 | ||
39 | #define PFP_UCODE_SIZE 576 | 39 | #define PFP_UCODE_SIZE 576 |
40 | #define PM4_UCODE_SIZE 1792 | 40 | #define PM4_UCODE_SIZE 1792 |
41 | #define RLC_UCODE_SIZE 768 | ||
41 | #define R700_PFP_UCODE_SIZE 848 | 42 | #define R700_PFP_UCODE_SIZE 848 |
42 | #define R700_PM4_UCODE_SIZE 1360 | 43 | #define R700_PM4_UCODE_SIZE 1360 |
44 | #define R700_RLC_UCODE_SIZE 1024 | ||
43 | 45 | ||
44 | /* Firmware Names */ | 46 | /* Firmware Names */ |
45 | MODULE_FIRMWARE("radeon/R600_pfp.bin"); | 47 | MODULE_FIRMWARE("radeon/R600_pfp.bin"); |
@@ -62,6 +64,8 @@ MODULE_FIRMWARE("radeon/RV730_pfp.bin"); | |||
62 | MODULE_FIRMWARE("radeon/RV730_me.bin"); | 64 | MODULE_FIRMWARE("radeon/RV730_me.bin"); |
63 | MODULE_FIRMWARE("radeon/RV710_pfp.bin"); | 65 | MODULE_FIRMWARE("radeon/RV710_pfp.bin"); |
64 | MODULE_FIRMWARE("radeon/RV710_me.bin"); | 66 | MODULE_FIRMWARE("radeon/RV710_me.bin"); |
67 | MODULE_FIRMWARE("radeon/R600_rlc.bin"); | ||
68 | MODULE_FIRMWARE("radeon/R700_rlc.bin"); | ||
65 | 69 | ||
66 | int r600_debugfs_mc_info_init(struct radeon_device *rdev); | 70 | int r600_debugfs_mc_info_init(struct radeon_device *rdev); |
67 | 71 | ||
@@ -1114,11 +1118,12 @@ void r600_cp_stop(struct radeon_device *rdev) | |||
1114 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); | 1118 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); |
1115 | } | 1119 | } |
1116 | 1120 | ||
1117 | int r600_cp_init_microcode(struct radeon_device *rdev) | 1121 | int r600_init_microcode(struct radeon_device *rdev) |
1118 | { | 1122 | { |
1119 | struct platform_device *pdev; | 1123 | struct platform_device *pdev; |
1120 | const char *chip_name; | 1124 | const char *chip_name; |
1121 | size_t pfp_req_size, me_req_size; | 1125 | const char *rlc_chip_name; |
1126 | size_t pfp_req_size, me_req_size, rlc_req_size; | ||
1122 | char fw_name[30]; | 1127 | char fw_name[30]; |
1123 | int err; | 1128 | int err; |
1124 | 1129 | ||
@@ -1132,30 +1137,62 @@ int r600_cp_init_microcode(struct radeon_device *rdev) | |||
1132 | } | 1137 | } |
1133 | 1138 | ||
1134 | switch (rdev->family) { | 1139 | switch (rdev->family) { |
1135 | case CHIP_R600: chip_name = "R600"; break; | 1140 | case CHIP_R600: |
1136 | case CHIP_RV610: chip_name = "RV610"; break; | 1141 | chip_name = "R600"; |
1137 | case CHIP_RV630: chip_name = "RV630"; break; | 1142 | rlc_chip_name = "R600"; |
1138 | case CHIP_RV620: chip_name = "RV620"; break; | 1143 | break; |
1139 | case CHIP_RV635: chip_name = "RV635"; break; | 1144 | case CHIP_RV610: |
1140 | case CHIP_RV670: chip_name = "RV670"; break; | 1145 | chip_name = "RV610"; |
1146 | rlc_chip_name = "R600"; | ||
1147 | break; | ||
1148 | case CHIP_RV630: | ||
1149 | chip_name = "RV630"; | ||
1150 | rlc_chip_name = "R600"; | ||
1151 | break; | ||
1152 | case CHIP_RV620: | ||
1153 | chip_name = "RV620"; | ||
1154 | rlc_chip_name = "R600"; | ||
1155 | break; | ||
1156 | case CHIP_RV635: | ||
1157 | chip_name = "RV635"; | ||
1158 | rlc_chip_name = "R600"; | ||
1159 | break; | ||
1160 | case CHIP_RV670: | ||
1161 | chip_name = "RV670"; | ||
1162 | rlc_chip_name = "R600"; | ||
1163 | break; | ||
1141 | case CHIP_RS780: | 1164 | case CHIP_RS780: |
1142 | case CHIP_RS880: chip_name = "RS780"; break; | 1165 | case CHIP_RS880: |
1143 | case CHIP_RV770: chip_name = "RV770"; break; | 1166 | chip_name = "RS780"; |
1167 | rlc_chip_name = "R600"; | ||
1168 | break; | ||
1169 | case CHIP_RV770: | ||
1170 | chip_name = "RV770"; | ||
1171 | rlc_chip_name = "R700"; | ||
1172 | break; | ||
1144 | case CHIP_RV730: | 1173 | case CHIP_RV730: |
1145 | case CHIP_RV740: chip_name = "RV730"; break; | 1174 | case CHIP_RV740: |
1146 | case CHIP_RV710: chip_name = "RV710"; break; | 1175 | chip_name = "RV730"; |
1176 | rlc_chip_name = "R700"; | ||
1177 | break; | ||
1178 | case CHIP_RV710: | ||
1179 | chip_name = "RV710"; | ||
1180 | rlc_chip_name = "R700"; | ||
1181 | break; | ||
1147 | default: BUG(); | 1182 | default: BUG(); |
1148 | } | 1183 | } |
1149 | 1184 | ||
1150 | if (rdev->family >= CHIP_RV770) { | 1185 | if (rdev->family >= CHIP_RV770) { |
1151 | pfp_req_size = R700_PFP_UCODE_SIZE * 4; | 1186 | pfp_req_size = R700_PFP_UCODE_SIZE * 4; |
1152 | me_req_size = R700_PM4_UCODE_SIZE * 4; | 1187 | me_req_size = R700_PM4_UCODE_SIZE * 4; |
1188 | rlc_req_size = R700_RLC_UCODE_SIZE * 4; | ||
1153 | } else { | 1189 | } else { |
1154 | pfp_req_size = PFP_UCODE_SIZE * 4; | 1190 | pfp_req_size = PFP_UCODE_SIZE * 4; |
1155 | me_req_size = PM4_UCODE_SIZE * 12; | 1191 | me_req_size = PM4_UCODE_SIZE * 12; |
1192 | rlc_req_size = RLC_UCODE_SIZE * 4; | ||
1156 | } | 1193 | } |
1157 | 1194 | ||
1158 | DRM_INFO("Loading %s CP Microcode\n", chip_name); | 1195 | DRM_INFO("Loading %s Microcode\n", chip_name); |
1159 | 1196 | ||
1160 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); | 1197 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); |
1161 | err = request_firmware(&rdev->pfp_fw, fw_name, &pdev->dev); | 1198 | err = request_firmware(&rdev->pfp_fw, fw_name, &pdev->dev); |
@@ -1179,6 +1216,18 @@ int r600_cp_init_microcode(struct radeon_device *rdev) | |||
1179 | rdev->me_fw->size, fw_name); | 1216 | rdev->me_fw->size, fw_name); |
1180 | err = -EINVAL; | 1217 | err = -EINVAL; |
1181 | } | 1218 | } |
1219 | |||
1220 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name); | ||
1221 | err = request_firmware(&rdev->rlc_fw, fw_name, &pdev->dev); | ||
1222 | if (err) | ||
1223 | goto out; | ||
1224 | if (rdev->rlc_fw->size != rlc_req_size) { | ||
1225 | printk(KERN_ERR | ||
1226 | "r600_rlc: Bogus length %zu in firmware \"%s\"\n", | ||
1227 | rdev->rlc_fw->size, fw_name); | ||
1228 | err = -EINVAL; | ||
1229 | } | ||
1230 | |||
1182 | out: | 1231 | out: |
1183 | platform_device_unregister(pdev); | 1232 | platform_device_unregister(pdev); |
1184 | 1233 | ||
@@ -1191,6 +1240,8 @@ out: | |||
1191 | rdev->pfp_fw = NULL; | 1240 | rdev->pfp_fw = NULL; |
1192 | release_firmware(rdev->me_fw); | 1241 | release_firmware(rdev->me_fw); |
1193 | rdev->me_fw = NULL; | 1242 | rdev->me_fw = NULL; |
1243 | release_firmware(rdev->rlc_fw); | ||
1244 | rdev->rlc_fw = NULL; | ||
1194 | } | 1245 | } |
1195 | return err; | 1246 | return err; |
1196 | } | 1247 | } |
@@ -1437,10 +1488,14 @@ int r600_wb_enable(struct radeon_device *rdev) | |||
1437 | void r600_fence_ring_emit(struct radeon_device *rdev, | 1488 | void r600_fence_ring_emit(struct radeon_device *rdev, |
1438 | struct radeon_fence *fence) | 1489 | struct radeon_fence *fence) |
1439 | { | 1490 | { |
1491 | /* Also consider EVENT_WRITE_EOP. it handles the interrupts + timestamps + events */ | ||
1440 | /* Emit fence sequence & fire IRQ */ | 1492 | /* Emit fence sequence & fire IRQ */ |
1441 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | 1493 | radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); |
1442 | radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); | 1494 | radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); |
1443 | radeon_ring_write(rdev, fence->seq); | 1495 | radeon_ring_write(rdev, fence->seq); |
1496 | /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */ | ||
1497 | radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0)); | ||
1498 | radeon_ring_write(rdev, RB_INT_STAT); | ||
1444 | } | 1499 | } |
1445 | 1500 | ||
1446 | int r600_copy_dma(struct radeon_device *rdev, | 1501 | int r600_copy_dma(struct radeon_device *rdev, |
@@ -1463,18 +1518,6 @@ int r600_copy_blit(struct radeon_device *rdev, | |||
1463 | return 0; | 1518 | return 0; |
1464 | } | 1519 | } |
1465 | 1520 | ||
1466 | int r600_irq_process(struct radeon_device *rdev) | ||
1467 | { | ||
1468 | /* FIXME: implement */ | ||
1469 | return 0; | ||
1470 | } | ||
1471 | |||
1472 | int r600_irq_set(struct radeon_device *rdev) | ||
1473 | { | ||
1474 | /* FIXME: implement */ | ||
1475 | return 0; | ||
1476 | } | ||
1477 | |||
1478 | int r600_set_surface_reg(struct radeon_device *rdev, int reg, | 1521 | int r600_set_surface_reg(struct radeon_device *rdev, int reg, |
1479 | uint32_t tiling_flags, uint32_t pitch, | 1522 | uint32_t tiling_flags, uint32_t pitch, |
1480 | uint32_t offset, uint32_t obj_size) | 1523 | uint32_t offset, uint32_t obj_size) |
@@ -1527,6 +1570,16 @@ int r600_startup(struct radeon_device *rdev) | |||
1527 | return r; | 1570 | return r; |
1528 | } | 1571 | } |
1529 | 1572 | ||
1573 | /* Enable IRQ */ | ||
1574 | rdev->irq.sw_int = true; | ||
1575 | r = r600_irq_init(rdev); | ||
1576 | if (r) { | ||
1577 | DRM_ERROR("radeon: IH init failed (%d).\n", r); | ||
1578 | radeon_irq_kms_fini(rdev); | ||
1579 | return r; | ||
1580 | } | ||
1581 | r600_irq_set(rdev); | ||
1582 | |||
1530 | r = radeon_ring_init(rdev, rdev->cp.ring_size); | 1583 | r = radeon_ring_init(rdev, rdev->cp.ring_size); |
1531 | if (r) | 1584 | if (r) |
1532 | return r; | 1585 | return r; |
@@ -1661,11 +1714,19 @@ int r600_init(struct radeon_device *rdev) | |||
1661 | r = radeon_object_init(rdev); | 1714 | r = radeon_object_init(rdev); |
1662 | if (r) | 1715 | if (r) |
1663 | return r; | 1716 | return r; |
1717 | |||
1718 | r = radeon_irq_kms_init(rdev); | ||
1719 | if (r) | ||
1720 | return r; | ||
1721 | |||
1664 | rdev->cp.ring_obj = NULL; | 1722 | rdev->cp.ring_obj = NULL; |
1665 | r600_ring_init(rdev, 1024 * 1024); | 1723 | r600_ring_init(rdev, 1024 * 1024); |
1666 | 1724 | ||
1667 | if (!rdev->me_fw || !rdev->pfp_fw) { | 1725 | rdev->ih.ring_obj = NULL; |
1668 | r = r600_cp_init_microcode(rdev); | 1726 | r600_ih_ring_init(rdev, 64 * 1024); |
1727 | |||
1728 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { | ||
1729 | r = r600_init_microcode(rdev); | ||
1669 | if (r) { | 1730 | if (r) { |
1670 | DRM_ERROR("Failed to load firmware!\n"); | 1731 | DRM_ERROR("Failed to load firmware!\n"); |
1671 | return r; | 1732 | return r; |
@@ -1712,6 +1773,8 @@ void r600_fini(struct radeon_device *rdev) | |||
1712 | r600_suspend(rdev); | 1773 | r600_suspend(rdev); |
1713 | 1774 | ||
1714 | r600_blit_fini(rdev); | 1775 | r600_blit_fini(rdev); |
1776 | r600_irq_fini(rdev); | ||
1777 | radeon_irq_kms_fini(rdev); | ||
1715 | radeon_ring_fini(rdev); | 1778 | radeon_ring_fini(rdev); |
1716 | r600_wb_fini(rdev); | 1779 | r600_wb_fini(rdev); |
1717 | r600_pcie_gart_fini(rdev); | 1780 | r600_pcie_gart_fini(rdev); |
@@ -1806,8 +1869,452 @@ int r600_ib_test(struct radeon_device *rdev) | |||
1806 | return r; | 1869 | return r; |
1807 | } | 1870 | } |
1808 | 1871 | ||
1872 | /* | ||
1873 | * Interrupts | ||
1874 | * | ||
1875 | * Interrupts use a ring buffer on r6xx/r7xx hardware. It works pretty | ||
1876 | * the same as the CP ring buffer, but in reverse. Rather than the CPU | ||
1877 | * writing to the ring and the GPU consuming, the GPU writes to the ring | ||
1878 | * and host consumes. As the host irq handler processes interrupts, it | ||
1879 | * increments the rptr. When the rptr catches up with the wptr, all the | ||
1880 | * current interrupts have been processed. | ||
1881 | */ | ||
1882 | |||
1883 | void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size) | ||
1884 | { | ||
1885 | u32 rb_bufsz; | ||
1886 | |||
1887 | /* Align ring size */ | ||
1888 | rb_bufsz = drm_order(ring_size / 4); | ||
1889 | ring_size = (1 << rb_bufsz) * 4; | ||
1890 | rdev->ih.ring_size = ring_size; | ||
1891 | rdev->ih.align_mask = 4 - 1; | ||
1892 | } | ||
1893 | |||
1894 | static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size) | ||
1895 | { | ||
1896 | int r; | ||
1897 | |||
1898 | rdev->ih.ring_size = ring_size; | ||
1899 | /* Allocate ring buffer */ | ||
1900 | if (rdev->ih.ring_obj == NULL) { | ||
1901 | r = radeon_object_create(rdev, NULL, rdev->ih.ring_size, | ||
1902 | true, | ||
1903 | RADEON_GEM_DOMAIN_GTT, | ||
1904 | false, | ||
1905 | &rdev->ih.ring_obj); | ||
1906 | if (r) { | ||
1907 | DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r); | ||
1908 | return r; | ||
1909 | } | ||
1910 | r = radeon_object_pin(rdev->ih.ring_obj, | ||
1911 | RADEON_GEM_DOMAIN_GTT, | ||
1912 | &rdev->ih.gpu_addr); | ||
1913 | if (r) { | ||
1914 | DRM_ERROR("radeon: failed to pin ih ring buffer (%d).\n", r); | ||
1915 | return r; | ||
1916 | } | ||
1917 | r = radeon_object_kmap(rdev->ih.ring_obj, | ||
1918 | (void **)&rdev->ih.ring); | ||
1919 | if (r) { | ||
1920 | DRM_ERROR("radeon: failed to map ih ring buffer (%d).\n", r); | ||
1921 | return r; | ||
1922 | } | ||
1923 | } | ||
1924 | rdev->ih.ptr_mask = (rdev->cp.ring_size / 4) - 1; | ||
1925 | rdev->ih.rptr = 0; | ||
1926 | |||
1927 | return 0; | ||
1928 | } | ||
1929 | |||
1930 | static void r600_ih_ring_fini(struct radeon_device *rdev) | ||
1931 | { | ||
1932 | if (rdev->ih.ring_obj) { | ||
1933 | radeon_object_kunmap(rdev->ih.ring_obj); | ||
1934 | radeon_object_unpin(rdev->ih.ring_obj); | ||
1935 | radeon_object_unref(&rdev->ih.ring_obj); | ||
1936 | rdev->ih.ring = NULL; | ||
1937 | rdev->ih.ring_obj = NULL; | ||
1938 | } | ||
1939 | } | ||
1940 | |||
1941 | static void r600_rlc_stop(struct radeon_device *rdev) | ||
1942 | { | ||
1943 | |||
1944 | if (rdev->family >= CHIP_RV770) { | ||
1945 | /* r7xx asics need to soft reset RLC before halting */ | ||
1946 | WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC); | ||
1947 | RREG32(SRBM_SOFT_RESET); | ||
1948 | udelay(15000); | ||
1949 | WREG32(SRBM_SOFT_RESET, 0); | ||
1950 | RREG32(SRBM_SOFT_RESET); | ||
1951 | } | ||
1952 | |||
1953 | WREG32(RLC_CNTL, 0); | ||
1954 | } | ||
1955 | |||
1956 | static void r600_rlc_start(struct radeon_device *rdev) | ||
1957 | { | ||
1958 | WREG32(RLC_CNTL, RLC_ENABLE); | ||
1959 | } | ||
1960 | |||
1961 | static int r600_rlc_init(struct radeon_device *rdev) | ||
1962 | { | ||
1963 | u32 i; | ||
1964 | const __be32 *fw_data; | ||
1965 | |||
1966 | if (!rdev->rlc_fw) | ||
1967 | return -EINVAL; | ||
1968 | |||
1969 | r600_rlc_stop(rdev); | ||
1970 | |||
1971 | WREG32(RLC_HB_BASE, 0); | ||
1972 | WREG32(RLC_HB_CNTL, 0); | ||
1973 | WREG32(RLC_HB_RPTR, 0); | ||
1974 | WREG32(RLC_HB_WPTR, 0); | ||
1975 | WREG32(RLC_HB_WPTR_LSB_ADDR, 0); | ||
1976 | WREG32(RLC_HB_WPTR_MSB_ADDR, 0); | ||
1977 | WREG32(RLC_MC_CNTL, 0); | ||
1978 | WREG32(RLC_UCODE_CNTL, 0); | ||
1979 | |||
1980 | fw_data = (const __be32 *)rdev->rlc_fw->data; | ||
1981 | if (rdev->family >= CHIP_RV770) { | ||
1982 | for (i = 0; i < R700_RLC_UCODE_SIZE; i++) { | ||
1983 | WREG32(RLC_UCODE_ADDR, i); | ||
1984 | WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); | ||
1985 | } | ||
1986 | } else { | ||
1987 | for (i = 0; i < RLC_UCODE_SIZE; i++) { | ||
1988 | WREG32(RLC_UCODE_ADDR, i); | ||
1989 | WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); | ||
1990 | } | ||
1991 | } | ||
1992 | WREG32(RLC_UCODE_ADDR, 0); | ||
1993 | |||
1994 | r600_rlc_start(rdev); | ||
1995 | |||
1996 | return 0; | ||
1997 | } | ||
1998 | |||
1999 | static void r600_enable_interrupts(struct radeon_device *rdev) | ||
2000 | { | ||
2001 | u32 ih_cntl = RREG32(IH_CNTL); | ||
2002 | u32 ih_rb_cntl = RREG32(IH_RB_CNTL); | ||
2003 | |||
2004 | ih_cntl |= ENABLE_INTR; | ||
2005 | ih_rb_cntl |= IH_RB_ENABLE; | ||
2006 | WREG32(IH_CNTL, ih_cntl); | ||
2007 | WREG32(IH_RB_CNTL, ih_rb_cntl); | ||
2008 | rdev->ih.enabled = true; | ||
2009 | } | ||
2010 | |||
2011 | static void r600_disable_interrupts(struct radeon_device *rdev) | ||
2012 | { | ||
2013 | u32 ih_rb_cntl = RREG32(IH_RB_CNTL); | ||
2014 | u32 ih_cntl = RREG32(IH_CNTL); | ||
2015 | |||
2016 | ih_rb_cntl &= ~IH_RB_ENABLE; | ||
2017 | ih_cntl &= ~ENABLE_INTR; | ||
2018 | WREG32(IH_RB_CNTL, ih_rb_cntl); | ||
2019 | WREG32(IH_CNTL, ih_cntl); | ||
2020 | /* set rptr, wptr to 0 */ | ||
2021 | WREG32(IH_RB_RPTR, 0); | ||
2022 | WREG32(IH_RB_WPTR, 0); | ||
2023 | rdev->ih.enabled = false; | ||
2024 | rdev->ih.wptr = 0; | ||
2025 | rdev->ih.rptr = 0; | ||
2026 | } | ||
2027 | |||
2028 | int r600_irq_init(struct radeon_device *rdev) | ||
2029 | { | ||
2030 | int ret = 0; | ||
2031 | int rb_bufsz; | ||
2032 | u32 interrupt_cntl, ih_cntl, ih_rb_cntl; | ||
2033 | |||
2034 | /* allocate ring */ | ||
2035 | ret = r600_ih_ring_alloc(rdev, rdev->ih.ring_size); | ||
2036 | if (ret) | ||
2037 | return ret; | ||
2038 | |||
2039 | /* disable irqs */ | ||
2040 | r600_disable_interrupts(rdev); | ||
2041 | |||
2042 | /* init rlc */ | ||
2043 | ret = r600_rlc_init(rdev); | ||
2044 | if (ret) { | ||
2045 | r600_ih_ring_fini(rdev); | ||
2046 | return ret; | ||
2047 | } | ||
2048 | |||
2049 | /* setup interrupt control */ | ||
2050 | /* set dummy read address to ring address */ | ||
2051 | WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8); | ||
2052 | interrupt_cntl = RREG32(INTERRUPT_CNTL); | ||
2053 | /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi | ||
2054 | * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN | ||
2055 | */ | ||
2056 | interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE; | ||
2057 | /* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */ | ||
2058 | interrupt_cntl &= ~IH_REQ_NONSNOOP_EN; | ||
2059 | WREG32(INTERRUPT_CNTL, interrupt_cntl); | ||
2060 | |||
2061 | WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8); | ||
2062 | rb_bufsz = drm_order(rdev->ih.ring_size / 4); | ||
2063 | |||
2064 | ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | | ||
2065 | IH_WPTR_OVERFLOW_CLEAR | | ||
2066 | (rb_bufsz << 1)); | ||
2067 | /* WPTR writeback, not yet */ | ||
2068 | /*ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE;*/ | ||
2069 | WREG32(IH_RB_WPTR_ADDR_LO, 0); | ||
2070 | WREG32(IH_RB_WPTR_ADDR_HI, 0); | ||
2071 | |||
2072 | WREG32(IH_RB_CNTL, ih_rb_cntl); | ||
2073 | |||
2074 | /* set rptr, wptr to 0 */ | ||
2075 | WREG32(IH_RB_RPTR, 0); | ||
2076 | WREG32(IH_RB_WPTR, 0); | ||
2077 | |||
2078 | /* Default settings for IH_CNTL (disabled at first) */ | ||
2079 | ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10); | ||
2080 | /* RPTR_REARM only works if msi's are enabled */ | ||
2081 | if (rdev->msi_enabled) | ||
2082 | ih_cntl |= RPTR_REARM; | ||
2083 | |||
2084 | #ifdef __BIG_ENDIAN | ||
2085 | ih_cntl |= IH_MC_SWAP(IH_MC_SWAP_32BIT); | ||
2086 | #endif | ||
2087 | WREG32(IH_CNTL, ih_cntl); | ||
2088 | |||
2089 | /* force the active interrupt state to all disabled */ | ||
2090 | WREG32(CP_INT_CNTL, 0); | ||
2091 | WREG32(GRBM_INT_CNTL, 0); | ||
2092 | WREG32(DxMODE_INT_MASK, 0); | ||
2093 | |||
2094 | /* enable irqs */ | ||
2095 | r600_enable_interrupts(rdev); | ||
2096 | |||
2097 | return ret; | ||
2098 | } | ||
2099 | |||
2100 | void r600_irq_fini(struct radeon_device *rdev) | ||
2101 | { | ||
2102 | r600_disable_interrupts(rdev); | ||
2103 | r600_rlc_stop(rdev); | ||
2104 | r600_ih_ring_fini(rdev); | ||
2105 | } | ||
2106 | |||
2107 | int r600_irq_set(struct radeon_device *rdev) | ||
2108 | { | ||
2109 | uint32_t cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; | ||
2110 | uint32_t mode_int = 0; | ||
2111 | |||
2112 | /* don't enable anything if the ih is disabled */ | ||
2113 | if (!rdev->ih.enabled) | ||
2114 | return 0; | ||
2115 | |||
2116 | if (rdev->irq.sw_int) { | ||
2117 | DRM_DEBUG("r600_irq_set: sw int\n"); | ||
2118 | cp_int_cntl |= RB_INT_ENABLE; | ||
2119 | } | ||
2120 | if (rdev->irq.crtc_vblank_int[0]) { | ||
2121 | DRM_DEBUG("r600_irq_set: vblank 0\n"); | ||
2122 | mode_int |= D1MODE_VBLANK_INT_MASK; | ||
2123 | } | ||
2124 | if (rdev->irq.crtc_vblank_int[1]) { | ||
2125 | DRM_DEBUG("r600_irq_set: vblank 1\n"); | ||
2126 | mode_int |= D2MODE_VBLANK_INT_MASK; | ||
2127 | } | ||
2128 | |||
2129 | WREG32(CP_INT_CNTL, cp_int_cntl); | ||
2130 | WREG32(DxMODE_INT_MASK, mode_int); | ||
2131 | |||
2132 | return 0; | ||
2133 | } | ||
2134 | |||
2135 | static inline void r600_irq_ack(struct radeon_device *rdev, u32 disp_int) | ||
2136 | { | ||
2137 | |||
2138 | if (disp_int & LB_D1_VBLANK_INTERRUPT) | ||
2139 | WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); | ||
2140 | if (disp_int & LB_D1_VLINE_INTERRUPT) | ||
2141 | WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK); | ||
2142 | if (disp_int & LB_D2_VBLANK_INTERRUPT) | ||
2143 | WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); | ||
2144 | if (disp_int & LB_D2_VLINE_INTERRUPT) | ||
2145 | WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK); | ||
2146 | |||
2147 | } | ||
2148 | |||
2149 | void r600_irq_disable(struct radeon_device *rdev) | ||
2150 | { | ||
2151 | u32 disp_int; | ||
2152 | |||
2153 | r600_disable_interrupts(rdev); | ||
2154 | /* Wait and acknowledge irq */ | ||
2155 | mdelay(1); | ||
2156 | if (ASIC_IS_DCE3(rdev)) | ||
2157 | disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); | ||
2158 | else | ||
2159 | disp_int = RREG32(DISP_INTERRUPT_STATUS); | ||
2160 | r600_irq_ack(rdev, disp_int); | ||
2161 | } | ||
2162 | |||
2163 | static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) | ||
2164 | { | ||
2165 | u32 wptr, tmp; | ||
2166 | |||
2167 | /* XXX use writeback */ | ||
2168 | wptr = RREG32(IH_RB_WPTR); | ||
2169 | |||
2170 | if (wptr & RB_OVERFLOW) { | ||
2171 | WARN_ON(1); | ||
2172 | /* XXX deal with overflow */ | ||
2173 | DRM_ERROR("IH RB overflow\n"); | ||
2174 | tmp = RREG32(IH_RB_CNTL); | ||
2175 | tmp |= IH_WPTR_OVERFLOW_CLEAR; | ||
2176 | WREG32(IH_RB_CNTL, tmp); | ||
2177 | } | ||
2178 | wptr = wptr & WPTR_OFFSET_MASK; | ||
1809 | 2179 | ||
2180 | return wptr; | ||
2181 | } | ||
1810 | 2182 | ||
2183 | /* r600 IV Ring | ||
2184 | * Each IV ring entry is 128 bits: | ||
2185 | * [7:0] - interrupt source id | ||
2186 | * [31:8] - reserved | ||
2187 | * [59:32] - interrupt source data | ||
2188 | * [127:60] - reserved | ||
2189 | * | ||
2190 | * The basic interrupt vector entries | ||
2191 | * are decoded as follows: | ||
2192 | * src_id src_data description | ||
2193 | * 1 0 D1 Vblank | ||
2194 | * 1 1 D1 Vline | ||
2195 | * 5 0 D2 Vblank | ||
2196 | * 5 1 D2 Vline | ||
2197 | * 19 0 FP Hot plug detection A | ||
2198 | * 19 1 FP Hot plug detection B | ||
2199 | * 19 2 DAC A auto-detection | ||
2200 | * 19 3 DAC B auto-detection | ||
2201 | * 176 - CP_INT RB | ||
2202 | * 177 - CP_INT IB1 | ||
2203 | * 178 - CP_INT IB2 | ||
2204 | * 181 - EOP Interrupt | ||
2205 | * 233 - GUI Idle | ||
2206 | * | ||
2207 | * Note, these are based on r600 and may need to be | ||
2208 | * adjusted or added to on newer asics | ||
2209 | */ | ||
2210 | |||
2211 | int r600_irq_process(struct radeon_device *rdev) | ||
2212 | { | ||
2213 | u32 wptr = r600_get_ih_wptr(rdev); | ||
2214 | u32 rptr = rdev->ih.rptr; | ||
2215 | u32 src_id, src_data; | ||
2216 | u32 last_entry = rdev->ih.ring_size - 16; | ||
2217 | u32 ring_index, disp_int; | ||
2218 | unsigned long flags; | ||
2219 | |||
2220 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | ||
2221 | |||
2222 | spin_lock_irqsave(&rdev->ih.lock, flags); | ||
2223 | |||
2224 | if (rptr == wptr) { | ||
2225 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | ||
2226 | return IRQ_NONE; | ||
2227 | } | ||
2228 | if (rdev->shutdown) { | ||
2229 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | ||
2230 | return IRQ_NONE; | ||
2231 | } | ||
2232 | |||
2233 | restart_ih: | ||
2234 | /* display interrupts */ | ||
2235 | if (ASIC_IS_DCE3(rdev)) | ||
2236 | disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); | ||
2237 | else | ||
2238 | disp_int = RREG32(DISP_INTERRUPT_STATUS); | ||
2239 | r600_irq_ack(rdev, disp_int); | ||
2240 | |||
2241 | rdev->ih.wptr = wptr; | ||
2242 | while (rptr != wptr) { | ||
2243 | /* wptr/rptr are in bytes! */ | ||
2244 | ring_index = rptr / 4; | ||
2245 | src_id = rdev->ih.ring[ring_index] & 0xff; | ||
2246 | src_data = rdev->ih.ring[ring_index + 1] & 0xfffffff; | ||
2247 | |||
2248 | switch (src_id) { | ||
2249 | case 1: /* D1 vblank/vline */ | ||
2250 | switch (src_data) { | ||
2251 | case 0: /* D1 vblank */ | ||
2252 | if (disp_int & LB_D1_VBLANK_INTERRUPT) { | ||
2253 | drm_handle_vblank(rdev->ddev, 0); | ||
2254 | disp_int &= ~LB_D1_VBLANK_INTERRUPT; | ||
2255 | DRM_DEBUG("IH: D1 vblank\n"); | ||
2256 | } | ||
2257 | break; | ||
2258 | case 1: /* D1 vline */ | ||
2259 | if (disp_int & LB_D1_VLINE_INTERRUPT) { | ||
2260 | disp_int &= ~LB_D1_VLINE_INTERRUPT; | ||
2261 | DRM_DEBUG("IH: D1 vline\n"); | ||
2262 | } | ||
2263 | break; | ||
2264 | default: | ||
2265 | DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); | ||
2266 | break; | ||
2267 | } | ||
2268 | break; | ||
2269 | case 5: /* D2 vblank/vline */ | ||
2270 | switch (src_data) { | ||
2271 | case 0: /* D2 vblank */ | ||
2272 | if (disp_int & LB_D2_VBLANK_INTERRUPT) { | ||
2273 | drm_handle_vblank(rdev->ddev, 1); | ||
2274 | disp_int &= ~LB_D2_VBLANK_INTERRUPT; | ||
2275 | DRM_DEBUG("IH: D2 vblank\n"); | ||
2276 | } | ||
2277 | break; | ||
2278 | case 1: /* D1 vline */ | ||
2279 | if (disp_int & LB_D2_VLINE_INTERRUPT) { | ||
2280 | disp_int &= ~LB_D2_VLINE_INTERRUPT; | ||
2281 | DRM_DEBUG("IH: D2 vline\n"); | ||
2282 | } | ||
2283 | break; | ||
2284 | default: | ||
2285 | DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); | ||
2286 | break; | ||
2287 | } | ||
2288 | break; | ||
2289 | case 176: /* CP_INT in ring buffer */ | ||
2290 | case 177: /* CP_INT in IB1 */ | ||
2291 | case 178: /* CP_INT in IB2 */ | ||
2292 | DRM_DEBUG("IH: CP int: 0x%08x\n", src_data); | ||
2293 | radeon_fence_process(rdev); | ||
2294 | break; | ||
2295 | case 181: /* CP EOP event */ | ||
2296 | DRM_DEBUG("IH: CP EOP\n"); | ||
2297 | break; | ||
2298 | default: | ||
2299 | DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); | ||
2300 | break; | ||
2301 | } | ||
2302 | |||
2303 | /* wptr/rptr are in bytes! */ | ||
2304 | if (rptr == last_entry) | ||
2305 | rptr = 0; | ||
2306 | else | ||
2307 | rptr += 16; | ||
2308 | } | ||
2309 | /* make sure wptr hasn't changed while processing */ | ||
2310 | wptr = r600_get_ih_wptr(rdev); | ||
2311 | if (wptr != rdev->ih.wptr) | ||
2312 | goto restart_ih; | ||
2313 | rdev->ih.rptr = rptr; | ||
2314 | WREG32(IH_RB_RPTR, rdev->ih.rptr); | ||
2315 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | ||
2316 | return IRQ_HANDLED; | ||
2317 | } | ||
1811 | 2318 | ||
1812 | /* | 2319 | /* |
1813 | * Debugfs info | 2320 | * Debugfs info |
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index dbf716e1fbf3..c20909c34e8a 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
@@ -569,9 +569,9 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes) | |||
569 | ring_size = num_loops * dwords_per_loop; | 569 | ring_size = num_loops * dwords_per_loop; |
570 | /* set default + shaders */ | 570 | /* set default + shaders */ |
571 | ring_size += 40; /* shaders + def state */ | 571 | ring_size += 40; /* shaders + def state */ |
572 | ring_size += 3; /* fence emit for VB IB */ | 572 | ring_size += 5; /* fence emit for VB IB */ |
573 | ring_size += 5; /* done copy */ | 573 | ring_size += 5; /* done copy */ |
574 | ring_size += 3; /* fence emit for done copy */ | 574 | ring_size += 5; /* fence emit for done copy */ |
575 | r = radeon_ring_lock(rdev, ring_size); | 575 | r = radeon_ring_lock(rdev, ring_size); |
576 | WARN_ON(r); | 576 | WARN_ON(r); |
577 | 577 | ||
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index b7f4ce2270bc..61ccde5637d7 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
@@ -456,7 +456,163 @@ | |||
456 | #define WAIT_2D_IDLECLEAN_bit (1 << 16) | 456 | #define WAIT_2D_IDLECLEAN_bit (1 << 16) |
457 | #define WAIT_3D_IDLECLEAN_bit (1 << 17) | 457 | #define WAIT_3D_IDLECLEAN_bit (1 << 17) |
458 | 458 | ||
459 | 459 | #define IH_RB_CNTL 0x3e00 | |
460 | # define IH_RB_ENABLE (1 << 0) | ||
461 | # define IH_IB_SIZE(x) ((x) << 1) /* log2 */ | ||
462 | # define IH_RB_FULL_DRAIN_ENABLE (1 << 6) | ||
463 | # define IH_WPTR_WRITEBACK_ENABLE (1 << 8) | ||
464 | # define IH_WPTR_WRITEBACK_TIMER(x) ((x) << 9) /* log2 */ | ||
465 | # define IH_WPTR_OVERFLOW_ENABLE (1 << 16) | ||
466 | # define IH_WPTR_OVERFLOW_CLEAR (1 << 31) | ||
467 | #define IH_RB_BASE 0x3e04 | ||
468 | #define IH_RB_RPTR 0x3e08 | ||
469 | #define IH_RB_WPTR 0x3e0c | ||
470 | # define RB_OVERFLOW (1 << 0) | ||
471 | # define WPTR_OFFSET_MASK 0x3fffc | ||
472 | #define IH_RB_WPTR_ADDR_HI 0x3e10 | ||
473 | #define IH_RB_WPTR_ADDR_LO 0x3e14 | ||
474 | #define IH_CNTL 0x3e18 | ||
475 | # define ENABLE_INTR (1 << 0) | ||
476 | # define IH_MC_SWAP(x) ((x) << 2) | ||
477 | # define IH_MC_SWAP_NONE 0 | ||
478 | # define IH_MC_SWAP_16BIT 1 | ||
479 | # define IH_MC_SWAP_32BIT 2 | ||
480 | # define IH_MC_SWAP_64BIT 3 | ||
481 | # define RPTR_REARM (1 << 4) | ||
482 | # define MC_WRREQ_CREDIT(x) ((x) << 15) | ||
483 | # define MC_WR_CLEAN_CNT(x) ((x) << 20) | ||
484 | |||
485 | #define RLC_CNTL 0x3f00 | ||
486 | # define RLC_ENABLE (1 << 0) | ||
487 | #define RLC_HB_BASE 0x3f10 | ||
488 | #define RLC_HB_CNTL 0x3f0c | ||
489 | #define RLC_HB_RPTR 0x3f20 | ||
490 | #define RLC_HB_WPTR 0x3f1c | ||
491 | #define RLC_HB_WPTR_LSB_ADDR 0x3f14 | ||
492 | #define RLC_HB_WPTR_MSB_ADDR 0x3f18 | ||
493 | #define RLC_MC_CNTL 0x3f44 | ||
494 | #define RLC_UCODE_CNTL 0x3f48 | ||
495 | #define RLC_UCODE_ADDR 0x3f2c | ||
496 | #define RLC_UCODE_DATA 0x3f30 | ||
497 | |||
498 | #define SRBM_SOFT_RESET 0xe60 | ||
499 | # define SOFT_RESET_RLC (1 << 13) | ||
500 | |||
501 | #define CP_INT_CNTL 0xc124 | ||
502 | # define CNTX_BUSY_INT_ENABLE (1 << 19) | ||
503 | # define CNTX_EMPTY_INT_ENABLE (1 << 20) | ||
504 | # define SCRATCH_INT_ENABLE (1 << 25) | ||
505 | # define TIME_STAMP_INT_ENABLE (1 << 26) | ||
506 | # define IB2_INT_ENABLE (1 << 29) | ||
507 | # define IB1_INT_ENABLE (1 << 30) | ||
508 | # define RB_INT_ENABLE (1 << 31) | ||
509 | #define CP_INT_STATUS 0xc128 | ||
510 | # define SCRATCH_INT_STAT (1 << 25) | ||
511 | # define TIME_STAMP_INT_STAT (1 << 26) | ||
512 | # define IB2_INT_STAT (1 << 29) | ||
513 | # define IB1_INT_STAT (1 << 30) | ||
514 | # define RB_INT_STAT (1 << 31) | ||
515 | |||
516 | #define GRBM_INT_CNTL 0x8060 | ||
517 | # define RDERR_INT_ENABLE (1 << 0) | ||
518 | # define WAIT_COUNT_TIMEOUT_INT_ENABLE (1 << 1) | ||
519 | # define GUI_IDLE_INT_ENABLE (1 << 19) | ||
520 | |||
521 | #define INTERRUPT_CNTL 0x5468 | ||
522 | # define IH_DUMMY_RD_OVERRIDE (1 << 0) | ||
523 | # define IH_DUMMY_RD_EN (1 << 1) | ||
524 | # define IH_REQ_NONSNOOP_EN (1 << 3) | ||
525 | # define GEN_IH_INT_EN (1 << 8) | ||
526 | #define INTERRUPT_CNTL2 0x546c | ||
527 | |||
528 | #define D1MODE_VBLANK_STATUS 0x6534 | ||
529 | #define D2MODE_VBLANK_STATUS 0x6d34 | ||
530 | # define DxMODE_VBLANK_OCCURRED (1 << 0) | ||
531 | # define DxMODE_VBLANK_ACK (1 << 4) | ||
532 | # define DxMODE_VBLANK_STAT (1 << 12) | ||
533 | # define DxMODE_VBLANK_INTERRUPT (1 << 16) | ||
534 | # define DxMODE_VBLANK_INTERRUPT_TYPE (1 << 17) | ||
535 | #define D1MODE_VLINE_STATUS 0x653c | ||
536 | #define D2MODE_VLINE_STATUS 0x6d3c | ||
537 | # define DxMODE_VLINE_OCCURRED (1 << 0) | ||
538 | # define DxMODE_VLINE_ACK (1 << 4) | ||
539 | # define DxMODE_VLINE_STAT (1 << 12) | ||
540 | # define DxMODE_VLINE_INTERRUPT (1 << 16) | ||
541 | # define DxMODE_VLINE_INTERRUPT_TYPE (1 << 17) | ||
542 | #define DxMODE_INT_MASK 0x6540 | ||
543 | # define D1MODE_VBLANK_INT_MASK (1 << 0) | ||
544 | # define D1MODE_VLINE_INT_MASK (1 << 4) | ||
545 | # define D2MODE_VBLANK_INT_MASK (1 << 8) | ||
546 | # define D2MODE_VLINE_INT_MASK (1 << 12) | ||
547 | #define DCE3_DISP_INTERRUPT_STATUS 0x7ddc | ||
548 | # define DC_HPD1_INTERRUPT (1 << 18) | ||
549 | # define DC_HPD2_INTERRUPT (1 << 19) | ||
550 | #define DISP_INTERRUPT_STATUS 0x7edc | ||
551 | # define LB_D1_VLINE_INTERRUPT (1 << 2) | ||
552 | # define LB_D2_VLINE_INTERRUPT (1 << 3) | ||
553 | # define LB_D1_VBLANK_INTERRUPT (1 << 4) | ||
554 | # define LB_D2_VBLANK_INTERRUPT (1 << 5) | ||
555 | # define DACA_AUTODETECT_INTERRUPT (1 << 16) | ||
556 | # define DACB_AUTODETECT_INTERRUPT (1 << 17) | ||
557 | # define DC_HOT_PLUG_DETECT1_INTERRUPT (1 << 18) | ||
558 | # define DC_HOT_PLUG_DETECT2_INTERRUPT (1 << 19) | ||
559 | # define DC_I2C_SW_DONE_INTERRUPT (1 << 20) | ||
560 | # define DC_I2C_HW_DONE_INTERRUPT (1 << 21) | ||
561 | #define DCE3_DISP_INTERRUPT_STATUS_CONTINUE 0x7de8 | ||
562 | # define DC_HPD4_INTERRUPT (1 << 14) | ||
563 | # define DC_HPD4_RX_INTERRUPT (1 << 15) | ||
564 | # define DC_HPD3_INTERRUPT (1 << 28) | ||
565 | # define DC_HPD1_RX_INTERRUPT (1 << 29) | ||
566 | # define DC_HPD2_RX_INTERRUPT (1 << 30) | ||
567 | #define DCE3_DISP_INTERRUPT_STATUS_CONTINUE2 0x7dec | ||
568 | # define DC_HPD3_RX_INTERRUPT (1 << 0) | ||
569 | # define DIGA_DP_VID_STREAM_DISABLE_INTERRUPT (1 << 1) | ||
570 | # define DIGA_DP_STEER_FIFO_OVERFLOW_INTERRUPT (1 << 2) | ||
571 | # define DIGB_DP_VID_STREAM_DISABLE_INTERRUPT (1 << 3) | ||
572 | # define DIGB_DP_STEER_FIFO_OVERFLOW_INTERRUPT (1 << 4) | ||
573 | # define AUX1_SW_DONE_INTERRUPT (1 << 5) | ||
574 | # define AUX1_LS_DONE_INTERRUPT (1 << 6) | ||
575 | # define AUX2_SW_DONE_INTERRUPT (1 << 7) | ||
576 | # define AUX2_LS_DONE_INTERRUPT (1 << 8) | ||
577 | # define AUX3_SW_DONE_INTERRUPT (1 << 9) | ||
578 | # define AUX3_LS_DONE_INTERRUPT (1 << 10) | ||
579 | # define AUX4_SW_DONE_INTERRUPT (1 << 11) | ||
580 | # define AUX4_LS_DONE_INTERRUPT (1 << 12) | ||
581 | # define DIGA_DP_FAST_TRAINING_COMPLETE_INTERRUPT (1 << 13) | ||
582 | # define DIGB_DP_FAST_TRAINING_COMPLETE_INTERRUPT (1 << 14) | ||
583 | /* DCE 3.2 */ | ||
584 | # define AUX5_SW_DONE_INTERRUPT (1 << 15) | ||
585 | # define AUX5_LS_DONE_INTERRUPT (1 << 16) | ||
586 | # define AUX6_SW_DONE_INTERRUPT (1 << 17) | ||
587 | # define AUX6_LS_DONE_INTERRUPT (1 << 18) | ||
588 | # define DC_HPD5_INTERRUPT (1 << 19) | ||
589 | # define DC_HPD5_RX_INTERRUPT (1 << 20) | ||
590 | # define DC_HPD6_INTERRUPT (1 << 21) | ||
591 | # define DC_HPD6_RX_INTERRUPT (1 << 22) | ||
592 | |||
593 | #define DCE3_DACA_AUTODETECT_INT_CONTROL 0x7038 | ||
594 | #define DCE3_DACB_AUTODETECT_INT_CONTROL 0x7138 | ||
595 | #define DACA_AUTODETECT_INT_CONTROL 0x7838 | ||
596 | #define DACB_AUTODETECT_INT_CONTROL 0x7a38 | ||
597 | # define DACx_AUTODETECT_ACK (1 << 0) | ||
598 | # define DACx_AUTODETECT_INT_ENABLE (1 << 16) | ||
599 | |||
600 | #define DC_HOT_PLUG_DETECT1_INT_CONTROL 0x7d08 | ||
601 | #define DC_HOT_PLUG_DETECT2_INT_CONTROL 0x7d18 | ||
602 | #define DC_HOT_PLUG_DETECT3_INT_CONTROL 0x7d2c | ||
603 | # define DC_HOT_PLUG_DETECTx_INT_ACK (1 << 0) | ||
604 | # define DC_HOT_PLUG_DETECTx_INT_POLARITY (1 << 8) | ||
605 | # define DC_HOT_PLUG_DETECTx_INT_EN (1 << 16) | ||
606 | /* DCE 3.2 */ | ||
607 | #define DC_HPD1_INT_CONTROL 0x7d04 | ||
608 | #define DC_HPD2_INT_CONTROL 0x7d10 | ||
609 | #define DC_HPD3_INT_CONTROL 0x7d1c | ||
610 | #define DC_HPD4_INT_CONTROL 0x7d28 | ||
611 | # define DC_HPDx_INT_ACK (1 << 0) | ||
612 | # define DC_HPDx_INT_POLARITY (1 << 8) | ||
613 | # define DC_HPDx_INT_EN (1 << 16) | ||
614 | # define DC_HPDx_RX_INT_ACK (1 << 20) | ||
615 | # define DC_HPDx_RX_INT_EN (1 << 24) | ||
460 | 616 | ||
461 | /* | 617 | /* |
462 | * PM4 | 618 | * PM4 |
@@ -500,7 +656,6 @@ | |||
500 | #define PACKET3_WAIT_REG_MEM 0x3C | 656 | #define PACKET3_WAIT_REG_MEM 0x3C |
501 | #define PACKET3_MEM_WRITE 0x3D | 657 | #define PACKET3_MEM_WRITE 0x3D |
502 | #define PACKET3_INDIRECT_BUFFER 0x32 | 658 | #define PACKET3_INDIRECT_BUFFER 0x32 |
503 | #define PACKET3_CP_INTERRUPT 0x40 | ||
504 | #define PACKET3_SURFACE_SYNC 0x43 | 659 | #define PACKET3_SURFACE_SYNC 0x43 |
505 | # define PACKET3_CB0_DEST_BASE_ENA (1 << 6) | 660 | # define PACKET3_CB0_DEST_BASE_ENA (1 << 6) |
506 | # define PACKET3_TC_ACTION_ENA (1 << 23) | 661 | # define PACKET3_TC_ACTION_ENA (1 << 23) |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 15b9e03bb589..0b8dad604ad8 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -399,6 +399,23 @@ struct radeon_cp { | |||
399 | bool ready; | 399 | bool ready; |
400 | }; | 400 | }; |
401 | 401 | ||
402 | /* | ||
403 | * R6xx+ IH ring | ||
404 | */ | ||
405 | struct r600_ih { | ||
406 | struct radeon_object *ring_obj; | ||
407 | volatile uint32_t *ring; | ||
408 | unsigned rptr; | ||
409 | unsigned wptr; | ||
410 | unsigned wptr_old; | ||
411 | unsigned ring_size; | ||
412 | uint64_t gpu_addr; | ||
413 | uint32_t align_mask; | ||
414 | uint32_t ptr_mask; | ||
415 | spinlock_t lock; | ||
416 | bool enabled; | ||
417 | }; | ||
418 | |||
402 | struct r600_blit { | 419 | struct r600_blit { |
403 | struct radeon_object *shader_obj; | 420 | struct radeon_object *shader_obj; |
404 | u64 shader_gpu_addr; | 421 | u64 shader_gpu_addr; |
@@ -792,8 +809,10 @@ struct radeon_device { | |||
792 | struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES]; | 809 | struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES]; |
793 | const struct firmware *me_fw; /* all family ME firmware */ | 810 | const struct firmware *me_fw; /* all family ME firmware */ |
794 | const struct firmware *pfp_fw; /* r6/700 PFP firmware */ | 811 | const struct firmware *pfp_fw; /* r6/700 PFP firmware */ |
812 | const struct firmware *rlc_fw; /* r6/700 RLC firmware */ | ||
795 | struct r600_blit r600_blit; | 813 | struct r600_blit r600_blit; |
796 | int msi_enabled; /* msi enabled */ | 814 | int msi_enabled; /* msi enabled */ |
815 | struct r600_ih ih; /* r6/700 interrupt ring */ | ||
797 | }; | 816 | }; |
798 | 817 | ||
799 | int radeon_device_init(struct radeon_device *rdev, | 818 | int radeon_device_init(struct radeon_device *rdev, |
@@ -1108,7 +1127,12 @@ extern void r600_wb_disable(struct radeon_device *rdev); | |||
1108 | extern void r600_scratch_init(struct radeon_device *rdev); | 1127 | extern void r600_scratch_init(struct radeon_device *rdev); |
1109 | extern int r600_blit_init(struct radeon_device *rdev); | 1128 | extern int r600_blit_init(struct radeon_device *rdev); |
1110 | extern void r600_blit_fini(struct radeon_device *rdev); | 1129 | extern void r600_blit_fini(struct radeon_device *rdev); |
1111 | extern int r600_cp_init_microcode(struct radeon_device *rdev); | 1130 | extern int r600_init_microcode(struct radeon_device *rdev); |
1112 | extern int r600_gpu_reset(struct radeon_device *rdev); | 1131 | extern int r600_gpu_reset(struct radeon_device *rdev); |
1132 | /* r600 irq */ | ||
1133 | extern int r600_irq_init(struct radeon_device *rdev); | ||
1134 | extern void r600_irq_fini(struct radeon_device *rdev); | ||
1135 | extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size); | ||
1136 | extern int r600_irq_set(struct radeon_device *rdev); | ||
1113 | 1137 | ||
1114 | #endif | 1138 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index c7a7f84fe3ec..755f50555c3d 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
@@ -480,6 +480,7 @@ static struct radeon_asic r600_asic = { | |||
480 | .ring_ib_execute = &r600_ring_ib_execute, | 480 | .ring_ib_execute = &r600_ring_ib_execute, |
481 | .irq_set = &r600_irq_set, | 481 | .irq_set = &r600_irq_set, |
482 | .irq_process = &r600_irq_process, | 482 | .irq_process = &r600_irq_process, |
483 | .get_vblank_counter = &rs600_get_vblank_counter, | ||
483 | .fence_ring_emit = &r600_fence_ring_emit, | 484 | .fence_ring_emit = &r600_fence_ring_emit, |
484 | .cs_parse = &r600_cs_parse, | 485 | .cs_parse = &r600_cs_parse, |
485 | .copy_blit = &r600_copy_blit, | 486 | .copy_blit = &r600_copy_blit, |
@@ -520,6 +521,7 @@ static struct radeon_asic rv770_asic = { | |||
520 | .ring_ib_execute = &r600_ring_ib_execute, | 521 | .ring_ib_execute = &r600_ring_ib_execute, |
521 | .irq_set = &r600_irq_set, | 522 | .irq_set = &r600_irq_set, |
522 | .irq_process = &r600_irq_process, | 523 | .irq_process = &r600_irq_process, |
524 | .get_vblank_counter = &rs600_get_vblank_counter, | ||
523 | .fence_ring_emit = &r600_fence_ring_emit, | 525 | .fence_ring_emit = &r600_fence_ring_emit, |
524 | .cs_parse = &r600_cs_parse, | 526 | .cs_parse = &r600_cs_parse, |
525 | .copy_blit = &r600_copy_blit, | 527 | .copy_blit = &r600_copy_blit, |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index c43a690aedc6..c962f34c92af 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -562,6 +562,8 @@ int radeon_device_init(struct radeon_device *rdev, | |||
562 | mutex_init(&rdev->cs_mutex); | 562 | mutex_init(&rdev->cs_mutex); |
563 | mutex_init(&rdev->ib_pool.mutex); | 563 | mutex_init(&rdev->ib_pool.mutex); |
564 | mutex_init(&rdev->cp.mutex); | 564 | mutex_init(&rdev->cp.mutex); |
565 | if (rdev->family >= CHIP_R600) | ||
566 | spin_lock_init(&rdev->ih.lock); | ||
565 | rwlock_init(&rdev->fence_drv.lock); | 567 | rwlock_init(&rdev->fence_drv.lock); |
566 | INIT_LIST_HEAD(&rdev->gem.objects); | 568 | INIT_LIST_HEAD(&rdev->gem.objects); |
567 | 569 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 350962e0f346..e13785282a82 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h | |||
@@ -1104,7 +1104,6 @@ extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index); | |||
1104 | # define R600_IT_WAIT_REG_MEM 0x00003C00 | 1104 | # define R600_IT_WAIT_REG_MEM 0x00003C00 |
1105 | # define R600_IT_MEM_WRITE 0x00003D00 | 1105 | # define R600_IT_MEM_WRITE 0x00003D00 |
1106 | # define R600_IT_INDIRECT_BUFFER 0x00003200 | 1106 | # define R600_IT_INDIRECT_BUFFER 0x00003200 |
1107 | # define R600_IT_CP_INTERRUPT 0x00004000 | ||
1108 | # define R600_IT_SURFACE_SYNC 0x00004300 | 1107 | # define R600_IT_SURFACE_SYNC 0x00004300 |
1109 | # define R600_CB0_DEST_BASE_ENA (1 << 6) | 1108 | # define R600_CB0_DEST_BASE_ENA (1 << 6) |
1110 | # define R600_TC_ACTION_ENA (1 << 23) | 1109 | # define R600_TC_ACTION_ENA (1 << 23) |
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 3beb26d74719..ab2a8b16836c 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
@@ -168,37 +168,6 @@ bool radeon_fence_signaled(struct radeon_fence *fence) | |||
168 | return signaled; | 168 | return signaled; |
169 | } | 169 | } |
170 | 170 | ||
171 | int r600_fence_wait(struct radeon_fence *fence, bool intr, bool lazy) | ||
172 | { | ||
173 | struct radeon_device *rdev; | ||
174 | int ret = 0; | ||
175 | |||
176 | rdev = fence->rdev; | ||
177 | |||
178 | __set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); | ||
179 | |||
180 | while (1) { | ||
181 | if (radeon_fence_signaled(fence)) | ||
182 | break; | ||
183 | |||
184 | if (time_after_eq(jiffies, fence->timeout)) { | ||
185 | ret = -EBUSY; | ||
186 | break; | ||
187 | } | ||
188 | |||
189 | if (lazy) | ||
190 | schedule_timeout(1); | ||
191 | |||
192 | if (intr && signal_pending(current)) { | ||
193 | ret = -ERESTARTSYS; | ||
194 | break; | ||
195 | } | ||
196 | } | ||
197 | __set_current_state(TASK_RUNNING); | ||
198 | return ret; | ||
199 | } | ||
200 | |||
201 | |||
202 | int radeon_fence_wait(struct radeon_fence *fence, bool intr) | 171 | int radeon_fence_wait(struct radeon_fence *fence, bool intr) |
203 | { | 172 | { |
204 | struct radeon_device *rdev; | 173 | struct radeon_device *rdev; |
@@ -216,13 +185,6 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr) | |||
216 | return 0; | 185 | return 0; |
217 | } | 186 | } |
218 | 187 | ||
219 | if (rdev->family >= CHIP_R600) { | ||
220 | r = r600_fence_wait(fence, intr, 0); | ||
221 | if (r == -ERESTARTSYS) | ||
222 | return -EBUSY; | ||
223 | return r; | ||
224 | } | ||
225 | |||
226 | retry: | 188 | retry: |
227 | cur_jiffies = jiffies; | 189 | cur_jiffies = jiffies; |
228 | timeout = HZ / 100; | 190 | timeout = HZ / 100; |
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index a0fe6232dcb6..84f8a6fb0da3 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |||
@@ -94,10 +94,18 @@ int radeon_irq_kms_init(struct radeon_device *rdev) | |||
94 | } | 94 | } |
95 | /* enable msi */ | 95 | /* enable msi */ |
96 | rdev->msi_enabled = 0; | 96 | rdev->msi_enabled = 0; |
97 | if (rdev->family >= CHIP_RV380) { | 97 | /* MSIs don't seem to work on my rs780; |
98 | * not sure about rs880 or other rs780s. | ||
99 | * Needs more investigation. | ||
100 | */ | ||
101 | if ((rdev->family >= CHIP_RV380) && | ||
102 | (rdev->family != CHIP_RS780) && | ||
103 | (rdev->family != CHIP_RS880)) { | ||
98 | int ret = pci_enable_msi(rdev->pdev); | 104 | int ret = pci_enable_msi(rdev->pdev); |
99 | if (!ret) | 105 | if (!ret) { |
100 | rdev->msi_enabled = 1; | 106 | rdev->msi_enabled = 1; |
107 | DRM_INFO("radeon: using MSI.\n"); | ||
108 | } | ||
101 | } | 109 | } |
102 | drm_irq_install(rdev->ddev); | 110 | drm_irq_install(rdev->ddev); |
103 | rdev->irq.installed = true; | 111 | rdev->irq.installed = true; |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index f54628475456..479684bda7e2 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -887,6 +887,16 @@ static int rv770_startup(struct radeon_device *rdev) | |||
887 | return r; | 887 | return r; |
888 | } | 888 | } |
889 | 889 | ||
890 | /* Enable IRQ */ | ||
891 | rdev->irq.sw_int = true; | ||
892 | r = r600_irq_init(rdev); | ||
893 | if (r) { | ||
894 | DRM_ERROR("radeon: IH init failed (%d).\n", r); | ||
895 | radeon_irq_kms_fini(rdev); | ||
896 | return r; | ||
897 | } | ||
898 | r600_irq_set(rdev); | ||
899 | |||
890 | r = radeon_ring_init(rdev, rdev->cp.ring_size); | 900 | r = radeon_ring_init(rdev, rdev->cp.ring_size); |
891 | if (r) | 901 | if (r) |
892 | return r; | 902 | return r; |
@@ -1005,11 +1015,19 @@ int rv770_init(struct radeon_device *rdev) | |||
1005 | r = radeon_object_init(rdev); | 1015 | r = radeon_object_init(rdev); |
1006 | if (r) | 1016 | if (r) |
1007 | return r; | 1017 | return r; |
1018 | |||
1019 | r = radeon_irq_kms_init(rdev); | ||
1020 | if (r) | ||
1021 | return r; | ||
1022 | |||
1008 | rdev->cp.ring_obj = NULL; | 1023 | rdev->cp.ring_obj = NULL; |
1009 | r600_ring_init(rdev, 1024 * 1024); | 1024 | r600_ring_init(rdev, 1024 * 1024); |
1010 | 1025 | ||
1011 | if (!rdev->me_fw || !rdev->pfp_fw) { | 1026 | rdev->ih.ring_obj = NULL; |
1012 | r = r600_cp_init_microcode(rdev); | 1027 | r600_ih_ring_init(rdev, 64 * 1024); |
1028 | |||
1029 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { | ||
1030 | r = r600_init_microcode(rdev); | ||
1013 | if (r) { | 1031 | if (r) { |
1014 | DRM_ERROR("Failed to load firmware!\n"); | 1032 | DRM_ERROR("Failed to load firmware!\n"); |
1015 | return r; | 1033 | return r; |
@@ -1055,6 +1073,8 @@ void rv770_fini(struct radeon_device *rdev) | |||
1055 | rv770_suspend(rdev); | 1073 | rv770_suspend(rdev); |
1056 | 1074 | ||
1057 | r600_blit_fini(rdev); | 1075 | r600_blit_fini(rdev); |
1076 | r600_irq_fini(rdev); | ||
1077 | radeon_irq_kms_fini(rdev); | ||
1058 | radeon_ring_fini(rdev); | 1078 | radeon_ring_fini(rdev); |
1059 | r600_wb_fini(rdev); | 1079 | r600_wb_fini(rdev); |
1060 | rv770_pcie_gart_fini(rdev); | 1080 | rv770_pcie_gart_fini(rdev); |