diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r600.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 561 |
1 files changed, 534 insertions, 27 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 |