drm/amdgpu: add new cgs interface to get display info (v2)
authorRex Zhu <Rex.Zhu@amd.com>
Thu, 17 Sep 2015 08:34:14 +0000 (16:34 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 21 Dec 2015 21:42:07 +0000 (16:42 -0500)
Add new CGS interfaces to query display info across modules.
This is nedded by the powerplay module for synchronizing with
the display module.

v2: (agd): fold in refresh rate fix, rebase

Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Reviewed-by: Jammy Zhou <Jammy.Zhou@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
drivers/gpu/drm/amd/include/cgs_common.h

index 19f46d0..8f758ea 100644 (file)
@@ -758,6 +758,45 @@ static int amdgpu_cgs_query_system_info(void *cgs_device,
        return 0;
 }
 
+static int amdgpu_cgs_get_active_displays_info(void *cgs_device,
+                                         struct cgs_display_info *info)
+{
+       CGS_FUNC_ADEV;
+       struct amdgpu_crtc *amdgpu_crtc;
+       struct drm_device *ddev = adev->ddev;
+       struct drm_crtc *crtc;
+       uint32_t line_time_us, vblank_lines;
+
+       if (info == NULL)
+               return -EINVAL;
+
+       if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
+               list_for_each_entry(crtc,
+                               &ddev->mode_config.crtc_list, head) {
+                       amdgpu_crtc = to_amdgpu_crtc(crtc);
+                       if (crtc->enabled) {
+                               info->active_display_mask |= (1 << amdgpu_crtc->crtc_id);
+                               info->display_count++;
+                       }
+                       if (info->mode_info != NULL &&
+                               crtc->enabled && amdgpu_crtc->enabled &&
+                               amdgpu_crtc->hw_mode.clock) {
+                               line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) /
+                                                       amdgpu_crtc->hw_mode.clock;
+                               vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end -
+                                                       amdgpu_crtc->hw_mode.crtc_vdisplay +
+                                                       (amdgpu_crtc->v_border * 2);
+                               info->mode_info->vblank_time_us = vblank_lines * line_time_us;
+                               info->mode_info->refresh_rate = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
+                               info->mode_info->ref_clock = adev->clock.spll.reference_freq;
+                               info->mode_info++;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 /** \brief evaluate acpi namespace object, handle or pathname must be valid
  *  \param cgs_device
  *  \param info input/output arguments for the control method
@@ -1006,6 +1045,7 @@ static const struct cgs_ops amdgpu_cgs_ops = {
        amdgpu_cgs_get_firmware_info,
        amdgpu_cgs_set_powergating_state,
        amdgpu_cgs_set_clockgating_state,
+       amdgpu_cgs_get_active_displays_info,
        amdgpu_cgs_call_acpi_method,
        amdgpu_cgs_query_system_info,
 };
index 5ea8db0..2bbffd1 100644 (file)
@@ -142,6 +142,18 @@ struct cgs_firmware_info {
        void                    *kptr;
 };
 
+struct cgs_mode_info {
+       uint32_t                refresh_rate;
+       uint32_t                ref_clock;
+       uint32_t                vblank_time_us;
+};
+
+struct cgs_display_info {
+       uint32_t                display_count;
+       uint32_t                active_display_mask;
+       struct cgs_mode_info *mode_info;
+};
+
 typedef unsigned long cgs_handle_t;
 
 #define CGS_ACPI_METHOD_ATCS          0x53435441
@@ -541,6 +553,10 @@ typedef int(*cgs_set_clockgating_state)(void *cgs_device,
                                  enum amd_ip_block_type block_type,
                                  enum amd_clockgating_state state);
 
+typedef int(*cgs_get_active_displays_info)(
+                                       void *cgs_device,
+                                       struct cgs_display_info *info);
+
 typedef int (*cgs_call_acpi_method)(void *cgs_device,
                                        uint32_t acpi_method,
                                        uint32_t acpi_function,
@@ -592,6 +608,8 @@ struct cgs_ops {
        /* cg pg interface*/
        cgs_set_powergating_state set_powergating_state;
        cgs_set_clockgating_state set_clockgating_state;
+       /* display manager */
+       cgs_get_active_displays_info get_active_displays_info;
        /* ACPI */
        cgs_call_acpi_method call_acpi_method;
        /* get system info */
@@ -682,6 +700,8 @@ struct cgs_device
        CGS_CALL(set_powergating_state, dev, block_type, state)
 #define cgs_set_clockgating_state(dev, block_type, state)      \
        CGS_CALL(set_clockgating_state, dev, block_type, state)
+#define cgs_get_active_displays_info(dev, info)        \
+       CGS_CALL(get_active_displays_info, dev, info)
 #define cgs_call_acpi_method(dev, acpi_method, acpi_function, pintput, poutput, output_count, input_size, output_size) \
        CGS_CALL(call_acpi_method, dev, acpi_method, acpi_function, pintput, poutput, output_count, input_size, output_size)
 #define cgs_query_system_info(dev, sys_info)   \