drm/radeon: add a asic callback to get the xclk
authorAlex Deucher <alexander.deucher@amd.com>
Thu, 14 Feb 2013 15:04:02 +0000 (10:04 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 20 Feb 2013 13:51:20 +0000 (08:51 -0500)
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>
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/rv770d.h
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/sid.h

index dbcb075..37d81fd 100644 (file)
@@ -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)
 {
index 59bfbd3..e425b41 100644 (file)
@@ -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 */
index 67f008f..e1b4a68 100644 (file)
@@ -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,
index f4134a8..f15758c 100644 (file)
@@ -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
index 9c312f9..96f05cd 100644 (file)
@@ -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)
index 1b2444f..d63fe1d 100644 (file)
@@ -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];
index 20e29d2..c55f950 100644 (file)
 #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
index 719f03e..b5064fa 100644 (file)
@@ -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)
 {
index 07fc455..23fc08f 100644 (file)
 #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