diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-02-14 10:04:02 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-02-20 08:51:20 -0500 |
commit | 454d2e2a32f02a4f8e0364ba0e8ce4f8dbe9810c (patch) | |
tree | c9727360424260a40aba4b037bbca4457efe4c1d | |
parent | 0e34d0945ed16aeb72c863be4efe4cd0c62f9c53 (diff) |
drm/radeon: add a asic callback to get the xclk
This is required to get the reference clock used
by the gfx engine for things like timestamps. Fixes
support for GL extensions the use timestamps on
certain boards.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_kms.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770d.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/si.c | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/sid.h | 5 |
9 files changed, 93 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index dbcb0752f08..37d81fd0955 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -109,6 +109,19 @@ void r600_fini(struct radeon_device *rdev); void r600_irq_disable(struct radeon_device *rdev); static void r600_pcie_gen2_enable(struct radeon_device *rdev); +/** + * r600_get_xclk - get the xclk + * + * @rdev: radeon_device pointer + * + * Returns the reference clock used by the gfx engine + * (r6xx, IGPs, APUs). + */ +u32 r600_get_xclk(struct radeon_device *rdev) +{ + return rdev->clock.spll.reference_freq; +} + /* get temperature in millidegrees */ int rv6xx_get_temp(struct radeon_device *rdev) { diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 59bfbd3868c..e425b412f24 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1179,6 +1179,8 @@ struct radeon_asic { bool (*gui_idle)(struct radeon_device *rdev); /* wait for mc_idle */ int (*mc_wait_for_idle)(struct radeon_device *rdev); + /* get the reference clock */ + u32 (*get_xclk)(struct radeon_device *rdev); /* gart */ struct { void (*tlb_flush)(struct radeon_device *rdev); @@ -1860,6 +1862,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_post_page_flip(rdev, crtc) (rdev)->asic->pflip.post_page_flip((rdev), (crtc)) #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev)) +#define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev)) /* Common functions */ /* AGP */ diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 67f008febec..e1b4a683231 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -934,6 +934,7 @@ static struct radeon_asic r600_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &r600_mc_wait_for_idle, + .get_xclk = &r600_get_xclk, .gart = { .tlb_flush = &r600_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1018,6 +1019,7 @@ static struct radeon_asic rs780_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &r600_mc_wait_for_idle, + .get_xclk = &r600_get_xclk, .gart = { .tlb_flush = &r600_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1102,6 +1104,7 @@ static struct radeon_asic rv770_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &r600_mc_wait_for_idle, + .get_xclk = &rv770_get_xclk, .gart = { .tlb_flush = &r600_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1186,6 +1189,7 @@ static struct radeon_asic evergreen_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .get_xclk = &rv770_get_xclk, .gart = { .tlb_flush = &evergreen_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1270,6 +1274,7 @@ static struct radeon_asic sumo_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .get_xclk = &r600_get_xclk, .gart = { .tlb_flush = &evergreen_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1354,6 +1359,7 @@ static struct radeon_asic btc_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .get_xclk = &rv770_get_xclk, .gart = { .tlb_flush = &evergreen_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1438,6 +1444,7 @@ static struct radeon_asic cayman_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .get_xclk = &rv770_get_xclk, .gart = { .tlb_flush = &cayman_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1565,6 +1572,7 @@ static struct radeon_asic trinity_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .get_xclk = &r600_get_xclk, .gart = { .tlb_flush = &cayman_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1692,6 +1700,7 @@ static struct radeon_asic si_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, + .get_xclk = &si_get_xclk, .gart = { .tlb_flush = &si_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index f4134a82395..f15758c7a26 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -390,6 +390,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev, struct radeon_sa_bo *vb); int r600_mc_wait_for_idle(struct radeon_device *rdev); uint64_t r600_get_gpu_clock(struct radeon_device *rdev); +u32 r600_get_xclk(struct radeon_device *rdev); /* * rv770,rv730,rv710,rv740 @@ -407,6 +408,7 @@ int rv770_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, struct radeon_fence **fence); +u32 rv770_get_xclk(struct radeon_device *rdev); /* * evergreen @@ -521,5 +523,6 @@ int si_copy_dma(struct radeon_device *rdev, unsigned num_gpu_pages, struct radeon_fence **fence); void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm); +u32 si_get_xclk(struct radeon_device *rdev); #endif diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 9c312f9afb6..96f05cde116 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -282,7 +282,10 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) break; case RADEON_INFO_CLOCK_CRYSTAL_FREQ: /* return clock value in KHz */ - value = rdev->clock.spll.reference_freq * 10; + if (rdev->asic->get_xclk) + value = radeon_get_xclk(rdev) * 10; + else + value = rdev->clock.spll.reference_freq * 10; break; case RADEON_INFO_NUM_BACKENDS: if (rdev->family >= CHIP_TAHITI) diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 1b2444f4d8f..d63fe1d0f53 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -43,6 +43,31 @@ static void rv770_gpu_init(struct radeon_device *rdev); void rv770_fini(struct radeon_device *rdev); static void rv770_pcie_gen2_enable(struct radeon_device *rdev); +#define PCIE_BUS_CLK 10000 +#define TCLK (PCIE_BUS_CLK / 10) + +/** + * rv770_get_xclk - get the xclk + * + * @rdev: radeon_device pointer + * + * Returns the reference clock used by the gfx engine + * (r7xx-cayman). + */ +u32 rv770_get_xclk(struct radeon_device *rdev) +{ + u32 reference_clock = rdev->clock.spll.reference_freq; + u32 tmp = RREG32(CG_CLKPIN_CNTL); + + if (tmp & MUX_TCLK_TO_XCLK) + return TCLK; + + if (tmp & XTALIN_DIVIDE) + return reference_clock / 4; + + return reference_clock; +} + u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h index 20e29d23d34..c55f950a4af 100644 --- a/drivers/gpu/drm/radeon/rv770d.h +++ b/drivers/gpu/drm/radeon/rv770d.h @@ -128,6 +128,10 @@ #define GUI_ACTIVE (1<<31) #define GRBM_STATUS2 0x8014 +#define CG_CLKPIN_CNTL 0x660 +# define MUX_TCLK_TO_XCLK (1 << 8) +# define XTALIN_DIVIDE (1 << 9) + #define CG_MULT_THERMAL_STATUS 0x740 #define ASIC_T(x) ((x) << 16) #define ASIC_T_MASK 0x3FF0000 diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 719f03e061d..b5064fae072 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -70,6 +70,33 @@ extern u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev); extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev); extern bool evergreen_is_display_hung(struct radeon_device *rdev); +#define PCIE_BUS_CLK 10000 +#define TCLK (PCIE_BUS_CLK / 10) + +/** + * si_get_xclk - get the xclk + * + * @rdev: radeon_device pointer + * + * Returns the reference clock used by the gfx engine + * (SI). + */ +u32 si_get_xclk(struct radeon_device *rdev) +{ + u32 reference_clock = rdev->clock.spll.reference_freq; + u32 tmp; + + tmp = RREG32(CG_CLKPIN_CNTL_2); + if (tmp & MUX_TCLK_TO_XCLK) + return TCLK; + + tmp = RREG32(CG_CLKPIN_CNTL); + if (tmp & XTALIN_DIVIDE) + return reference_clock / 4; + + return reference_clock; +} + /* get temperature in millidegrees */ int si_get_temp(struct radeon_device *rdev) { diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 07fc455e35a..23fc08fc8e7 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -58,6 +58,11 @@ #define VGA_HDP_CONTROL 0x328 #define VGA_MEMORY_DISABLE (1 << 4) +#define CG_CLKPIN_CNTL 0x660 +# define XTALIN_DIVIDE (1 << 1) +#define CG_CLKPIN_CNTL_2 0x664 +# define MUX_TCLK_TO_XCLK (1 << 8) + #define DMIF_ADDR_CONFIG 0xBD4 #define SRBM_STATUS 0xE50 |