Em Qua, 2017-06-21 às 13:40 +0530, Lohith BS escreveu:
> Idleness DRRS:
>       By default the DRRS state will be at DRRS_HIGH_RR. When a
> Display
>       content is Idle for more than 1Sec Idleness will be declared
> and
>       DRRS_LOW_RR will be invoked, changing the refresh rate to the
>       lower most refresh rate supported by the panel. As soon as
> there
>       is a display content change there will be a DRRS state
> transition
>       as DRRS_LOW_RR--> DRRS_HIGH_RR, changing the refresh rate to
> the
>       highest refresh rate supported by the panel.
> 
> To test this, Idleness DRRS IGT will probe the DRRS state at below
> instances and compare with the expected state.
> 
>       Instance                                        Expected State
> 1. Immediately after rendering the still image                DRRS_HI
> GH_RR
> 2. After a delay of 1.2Sec                            DRRS_LOW_RR
> 3. After changing the frame buffer                    DRRS_HIGH_R
> R
> 4. After a delay of 1.2Sec                            DRRS_LOW_RR
> 5. After changing the frame buffer                    DRRS_HIGH_R
> R
> 6. After a delay of 1.2Sec                            DRRS_LOW_RR
> 
> The test checks the driver DRRS state from the debugfs entry. To
> check the
> actual refresh-rate, the number of vblanks received per sec.
> The refresh-rate calculated is checked against the expected refresh-
> rate
> with a tolerance value of 2.
> 
> This patch is a continuation of the earlier work
> https://patchwork.freedesktop.org/patch/45472/ towards igt for
> idleness
> 
> DRRS. The code is tested on Broxton BXT_T platform.
> 
> v2: Addressed the comments and suggestions from Vlad, Marius.
> The signoff details from the earlier work are also included.
> 
> v3: Modified vblank rate calculation by using reply-sequence,
> provided by
> drmWaitVBlank, as suggested by Chris Wilson.
> 
> v4: As suggested from Chris Wilson and Daniel Vetter
>       1) Avoided using pthread for calculating vblank refresh rate,
>          instead used drmWaitVBlank reply sequence.
>       2) Avoided using kernel-specific info like transitional delays,
>          instead polling mechanism with timeout is used.
>       3) Included edp-DRRS as a subtest in
> kms_frontbuffer_tracking.c,
>          instead of having a separate test.

I completely disagree with the way this part was implemented. The code
added to kms_frontbuffer_tracking.c uses pretty much zero of the
infrastructure provided by the file. This patch adds a completely
unrelated set of functions to kms_frontbuffer_tracking.c. If we're not
going to use the current subtests & infrastructure, please make it a
separate test.


> 
> This is in continuation of last patch "https://patchwork.freedesktop.
> org/patch/117149/"
> 
> Signed-off-by: Lohith BS <[email protected]>
> Signed-off-by: Ramalingam C <[email protected]>
> Signed-off-by: Vandana Kannan <[email protected]>
> Signed-off-by: aknautiy <[email protected]>
> ---
>  tests/kms_frontbuffer_tracking.c | 453
> ++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 452 insertions(+), 1 deletion(-)
> 
> diff --git a/tests/kms_frontbuffer_tracking.c
> b/tests/kms_frontbuffer_tracking.c
> index c24e4a8..4d46e1e 100644
> --- a/tests/kms_frontbuffer_tracking.c
> +++ b/tests/kms_frontbuffer_tracking.c
> @@ -32,9 +32,18 @@
>  #include <poll.h>
>  #include <pthread.h>
>  
> +#include "drmtest.h"
> +#include "igt_debugfs.h"
> +#include "igt_kms.h"
> +#include "intel_chipset.h"
> +#include "intel_batchbuffer.h"
> +#include "ioctl_wrappers.h"
> +#include <time.h>
> +#include <stdlib.h>
> +#include <sys/time.h>
>  
>  IGT_TEST_DESCRIPTION("Test the Kernel's frontbuffer tracking
> mechanism and "
> -                  "its related features: FBC and PSR");
> +                  "its related features: DRRS, FBC and PSR");
>  
>  /*
>   * One of the aspects of this test is that, for every subtest, we
> try different
> @@ -327,6 +336,41 @@ drmModeModeInfo std_1024_mode = {
>       .name = "Custom 1024x768",
>  };
>  
> +#define DRRS_TOLERANCE_THRESHOLD 2
> +#define DRRS_POLL_TIMEOUT_PERIOD_MS 5000
> +#define DRRS_STATUS_BYTES_CNT 1000
> +#define DRRS_MAX_ITERATION 3
> +
> +/*
> + * Struct to hold drrs test related data
> + */
> +typedef struct {
> +     uint32_t devid;
> +     uint32_t handle[2];
> +     igt_display_t display;
> +     igt_output_t *output;
> +     enum pipe pipe;
> +     igt_plane_t *primary;
> +     struct igt_fb fb[2];
> +     uint32_t fb_id[2];
> +} drrs_data_t;
> +
> +/*
> + * Structure to count vblank and note the starting time of the
> counter
> + */
> +typedef struct {
> +     unsigned int vbl_count;
> +     struct timeval start;
> +} vbl_info;
> +
> +/*
> + * Structure for refresh rate type
> + */
> +typedef struct{
> +     int rate;
> +     const char *name;
> +} refresh_rate_t;
> +
>  static drmModeModeInfoPtr
> get_connector_smallest_mode(drmModeConnectorPtr c)
>  {
>       int i;
> @@ -3415,6 +3459,410 @@ static const char *flip_str(enum flip_type
> flip)
>  
>  #define TEST_MODE_ITER_END } } } } } }
>  
> +static inline uint32_t pipe_select(int pipe)
> +{
> +     if (pipe > 1)
> +             return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
> +     else if (pipe > 0)
> +             return DRM_VBLANK_SECONDARY;
> +     else
> +             return DRM_VBLANK_ABSOLUTE;
> +}
> +
> +/*
> + * Calculates the total no. of millisec elapsed since timeval start
> + */
> +static double igt_millisec_elapsed(const struct timeval *start)
> +{
> +     struct timeval curr;
> +
> +     gettimeofday(&curr, NULL);
> +     return (1e3*(curr.tv_sec - start->tv_sec) +
> +                             (curr.tv_usec - start-
> >tv_usec)/1000.00);
> +}
> +
> +/*
> + * Func to read the DRRS status from debugfs
> + */
> +static bool read_drrs_status(char *str)
> +{
> +     FILE *fp;
> +     int fd;
> +     int cnt;
> +
> +     fd = igt_debugfs_open(drm.fd, "i915_drrs_status", O_RDONLY);
> +     igt_assert(fd);
> +     fp = fdopen(fd, "r");
> +     igt_require(fp);
> +     cnt = fread(str, DRRS_STATUS_BYTES_CNT - 1, 1, fp);
> +
> +     if (!cnt) {
> +             if (!feof(fp)) {
> +                     igt_critical("Failed to read
> i915_drrs_status:%d \n",
> +                             ferror(fp));
> +                     return false;
> +             }
> +             clearerr(fp);
> +     }
> +     fclose(fp);
> +
> +     return true;
> +}
> +
> +/*
> + * Func to check for DRRS support
> + */
> +static bool is_drrs_supported(void)
> +{
> +     char str[DRRS_STATUS_BYTES_CNT] = {};
> +
> +     if (!read_drrs_status(str))
> +             return false;
> +
> +     return strstr(str, "DRRS Supported: Yes") != NULL;
> +}
> +
> +/*
> + * Func to check if DRRS is enabled by driver.
> + */
> +static bool is_drrs_enabled(void)
> +{
> +     char str[DRRS_STATUS_BYTES_CNT] = {};
> +
> +     if (!read_drrs_status(str))
> +             return false;
> +
> +     return strstr(str, "Idleness DRRS: Disabled") == NULL;
> +}
> +
> +
> +/*
> + * vbl_rate = vbl_count/time taken
> + */
> +static double vbl_rate(const union drm_wait_vblank *start,
> +                             const union drm_wait_vblank *end)
> +{
> +     double s, e;
> +
> +     s = start->reply.tval_sec + 1e-6 * start->reply.tval_usec;
> +     e = end->reply.tval_sec + 1e-6 * end->reply.tval_usec;
> +     return ((end->reply.sequence - start->reply.sequence) / (e -
> s));
> +}
> +
> +/*
> + * refresh_rate = (20 vblanks) /(time for 20vblanks)
> + */
> +int calculate_refresh_rate(drrs_data_t *data)
> +{
> +     union drm_wait_vblank start, end;
> +     struct timeval start_tv;
> +     int refresh_rate;
> +
> +     memset(&start, 0, sizeof(start));
> +     start.request.type = DRM_VBLANK_RELATIVE | pipe_select(data-
> >pipe);
> +
> +     if (drmWaitVBlank(drm.fd, &start) != 0) {
> +             igt_critical("drmWaitVBlank Failed!\n");
> +             return -1;
> +     }
> +     gettimeofday(&start_tv, NULL);
> +     memset(&end, 0, sizeof(end));
> +     end.request.type = DRM_VBLANK_RELATIVE | pipe_select(data-
> >pipe);
> +
> +     /* Configured to wait for 20 vblank events*/
> +     end.request.sequence = 20;
> +
> +     if (drmWaitVBlank(drm.fd, &end) != 0) {
> +             igt_critical("drmWaitVBlank Failed!\n");
> +             return -1;
> +     }
> +     refresh_rate = vbl_rate(&start, &end);
> +
> +     return refresh_rate;
> +}
> +
> +/*
> + * Poll for DRRS transition from high to low with 5 seconds time
> out.
> + */
> +int wait_for_drrs_switch_to_low(drrs_data_t *data)
> +{
> +     char drrs_status[DRRS_STATUS_BYTES_CNT] = {};
> +     const char *drrs_low_name = "DRRS_LOW_RR";
> +     int status = 1;
> +     struct timeval start_tv;
> +
> +     gettimeofday(&start_tv, NULL);
> +
> +     while (igt_millisec_elapsed(&start_tv) <
> DRRS_POLL_TIMEOUT_PERIOD_MS) {
> +
> +             if (!read_drrs_status(drrs_status)) {
> +                     status = -1;
> +                     break;
> +             }
> +
> +             if (strstr(drrs_status, drrs_low_name) != NULL)
> +                     break;
> +     }
> +
> +     if (igt_millisec_elapsed(&start_tv) >
> DRRS_POLL_TIMEOUT_PERIOD_MS) {
> +
> +             igt_critical("DRRS failed to switch refresh rate
> from "
> +                     "higher to lower\n");
> +
> +             status = -1;
> +     }
> +
> +     return status;
> +}
> +
> +/*
> + * Check if calulated refresh rate is same as expected refresh rate
> + * Returns 0 in case of pass , 1 in case of failure, and -1 for
> error.
> + */
> +static int check_refresh_rate(drrs_data_t *data, refresh_rate_t
> *expected_rr)
> +{
> +     int refresh_rate = -1;
> +     char drrs_status[DRRS_STATUS_BYTES_CNT] = {};
> +
> +     /* Get the DRRS Status from the debugfs entry */
> +     if (!read_drrs_status(drrs_status))
> +             return -1;
> +
> +     refresh_rate = calculate_refresh_rate(data);
> +
> +     if (refresh_rate < 0) {
> +             igt_critical("Refresh rate calculation FAILED\n");
> +             return -1;
> +     }
> +
> +     /* Compare with Expected Refresh Rate */
> +     if (strstr(drrs_status, expected_rr->name) != NULL
> +     && abs(refresh_rate - expected_rr->rate) <=
> DRRS_TOLERANCE_THRESHOLD) {
> +             return 0;
> +     }
> +     igt_critical("Expected %s : FAILED.\n", expected_rr->name);
> +
> +     return 1;
> +}
> +
> +/*
> + * This function
> + * 1. Creates framebuffers
> + * 2. Apply framebuffers alternatively and count the vblank refresh
> rate
> + *    which should be equal to highest refresh rate supported.
> + * 3. Poll for DRRS to toggle from DRRS_HIGH_RR -> DRRS_LOW_RR with
> 5sec
> + *    timeout using kernel debugfs entry(i915_drrs_status).
> + * 4. Once DRRS switches to LOW we count the vblank refresh rate
> which
> + *    should be equal to lowest refresh rate supported.
> + * 5. The above calculated vblank refresh rates can have a tolerance
> of 2.
> + */
> +static int execute_test(drrs_data_t *data)
> +{
> +     igt_display_t *display = &data->display;
> +     igt_output_t *output = data->output;
> +     drmModeModeInfo *mode, *supported_modes;
> +     int test_failed = 0;
> +     int ret, i, i_mod, count_modes;
> +     refresh_rate_t high_rr, low_rr;
> +
> +     high_rr.name = "DRRS_HIGH_RR";
> +     high_rr.rate = 0;
> +     low_rr.name = "DRRS_LOW_RR";
> +     low_rr.rate = 0;
> +
> +     /* get the max and min supported refresh rates for the
> display */
> +     supported_modes = output->config.connector->modes;
> +     count_modes = output->config.connector->count_modes;
> +
> +     /* minimum 2 modes are required for DRRS */
> +     igt_assert_f(count_modes >= 2, "Minimum 2 modes required for
> DRRS\n");
> +
> +     for (i = 0; i < count_modes; i++) {
> +             int rr = supported_modes[i].vrefresh;
> +
> +             if (i == 0) {
> +                     high_rr.rate = low_rr.rate = rr;
> +                     continue;
> +             }
> +
> +             if (high_rr.rate < rr)
> +                     high_rr.rate = rr;
> +
> +             if (low_rr.rate > rr)
> +                     low_rr.rate = rr;
> +     }
> +
> +     igt_output_set_pipe(output, data->pipe);
> +     data->primary = igt_output_get_plane(data->output,
> +                             DRM_PLANE_TYPE_OVERLAY);
> +     mode = igt_output_get_mode(data->output);
> +     data->fb_id[0] = igt_create_color_fb(drm.fd, mode->hdisplay,
> +                                             mode->vdisplay,
> +                                             DRM_FORMAT_XRGB8888,
> +                                             LOCAL_DRM_FORMAT_MOD
> _NONE,
> +                                             0.0, 100.1, 0.0,
> &data->fb[0]);
> +
> +     igt_assert(data->fb_id[0]);
> +     data->fb_id[1] = igt_create_color_fb(drm.fd, mode->hdisplay,
> +                                             mode->vdisplay,
> +                                             DRM_FORMAT_XRGB8888,
> +                                             LOCAL_DRM_FORMAT_MOD
> _NONE,
> +                                             100.1, 0.0, 0.0,
> +                                             &data->fb[1]);
> +
> +     igt_assert(data->fb_id[1]);
> +     data->handle[0] = data->fb[0].gem_handle;
> +     data->handle[1] = data->fb[1].gem_handle;
> +
> +     for (i = 1; i <= DRRS_MAX_ITERATION; i++) {
> +             i_mod = i % 2;
> +             igt_plane_set_fb(data->primary, &data->fb[i_mod]);
> +             igt_display_commit(display);
> +
> +             if (!is_drrs_enabled()) {
> +                     igt_critical("DRRS not enabled\n");
> +                     igt_plane_set_fb(data->primary, NULL);
> +                     igt_output_set_pipe(output, PIPE_ANY);
> +                     igt_display_commit(display);
> +                     igt_remove_fb(drm.fd, &data->fb[0]);
> +                     igt_remove_fb(drm.fd, &data->fb[1]);
> +                     return -1;
> +             }
> +
> +             /* expecting High RR */
> +             ret =  check_refresh_rate(data, &high_rr);
> +
> +             if (ret == -1)
> +                     return -1;
> +
> +             if (ret == 1)
> +                     test_failed = 1;
> +
> +             /*
> +              * Poll kernel debugfs entry for DRRS
> +              * transition from High to Low
> +              */
> +             ret = wait_for_drrs_switch_to_low(data);
> +
> +             if (ret == -1)
> +                     return 1;
> +
> +             /* expecting Low RR */
> +             ret = check_refresh_rate(data, &low_rr);
> +
> +             if (ret == -1)
> +                     return -1;
> +
> +             if (ret == 1)
> +                     test_failed = 1;
> +     }
> +
> +     return test_failed;
> +}
> +
> +/*
> + * Func to free the framebuffers after the test completion.
> + */
> +static void finish_crtc(drrs_data_t *data)
> +{
> +     igt_plane_set_fb(data->primary, NULL);
> +     igt_output_set_pipe(data->output, PIPE_ANY);
> +     igt_display_commit(&data->display);
> +
> +     igt_remove_fb(drm.fd, &data->fb[0]);
> +     igt_remove_fb(drm.fd, &data->fb[1]);
> +}
> +
> +/*
> + * Func to reset the display structures after the test completion.
> + */
> +static void reset_display(drrs_data_t *data)
> +{
> +     igt_display_t *display = &data->display;
> +     enum pipe pipe_id;
> +
> +     for_each_pipe(display, pipe_id) {
> +             igt_pipe_t *pipe = &display->pipes[pipe_id];
> +             igt_plane_t *plane = igt_pipe_get_plane_type(pipe,
> +                                     DRM_PLANE_TYPE_PRIMARY);
> +
> +             if (plane->fb)
> +                     igt_plane_set_fb(plane, NULL);
> +     }
> +
> +     for_each_connected_output(display, data->output)
> +             igt_output_set_pipe(data->output, PIPE_ANY);
> +}
> +
> +/*
> + * Func to run the drrs test for the eDP display.
> + */
> +static void run_test(drrs_data_t *data)
> +{
> +     int ret;
> +     igt_display_t *display = &data->display;
> +
> +     reset_display(data);
> +
> +     for_each_pipe_with_valid_output(display, data->pipe, data-
> >output) {
> +             drmModeConnectorPtr c = data->output-
> >config.connector;
> +
> +             if (c->connector_type != DRM_MODE_CONNECTOR_eDP ||
> +                     c->connection != DRM_MODE_CONNECTED)
> +                     continue;
> +
> +             ret = execute_test(data);
> +
> +             igt_skip_on_f(ret == -1,
> +                             "%s on pipe %s, connector
> %s:SKIPPED\n",
> +                                     igt_subtest_name(),
> +                                     kmstest_pipe_name(data-
> >pipe),
> +                                     igt_output_name(data-
> >output));
> +
> +             igt_fail_on_f(ret == 1,
> +                             "%s on pipe %s, connector
> %s:FAILED\n",
> +                                     igt_subtest_name(),
> +                                     kmstest_pipe_name(data-
> >pipe),
> +                                     igt_output_name(data-
> >output));
> +
> +             igt_assert_f(ret == 0,
> +                             "%s on pipe %s, connector %s:
> PASSED\n",
> +                                     igt_subtest_name(),
> +                                     kmstest_pipe_name(data-
> >pipe),
> +                                     igt_output_name(data-
> >output));
> +
> +             finish_crtc(data);
> +     }
> +}
> +
> +/*
> + * Function to test edp-DRRS feature.Exits from the function if PSR
> is enabled
> + */
> +void edp_drrs_test(void)
> +{
> +     drrs_data_t data = {};
> +
> +     igt_assert_f(!psr.can_test,
> +                     "DRRS cannot be tested as PSR is
> enabled\n");
> +     igt_skip_on_simulation();
> +
> +     /*
> +      * Using the same drm.fd which was opened during
> setup_environment
> +      */
> +     igt_assert_f(drm.fd != -1, "Invalid fd\n");
> +     data.devid = intel_get_drm_devid(drm.fd);
> +     igt_assert_f(data.devid >= 0, "Invalid dev id\n");
> +
> +     /*
> +      * Check if the DRRS is supported.If yes call the Idleness
> DRRS test
> +      */
> +     igt_require_f(is_drrs_supported(),
> +                     "DRRS not supported:check VBT/panel
> caps\n");
> +     igt_display_init(&data.display, drm.fd);
> +     run_test(&data);
> +     igt_display_fini(&data.display);
> +}
> +
>  int main(int argc, char *argv[])
>  {
>       struct test_mode t;
> @@ -3628,6 +4076,9 @@ int main(int argc, char *argv[])
>                       suspend_subtest(&t);
>       TEST_MODE_ITER_END
>  
> +     igt_subtest_f("edp-DRRS")
> +             edp_drrs_test();
> +
>       t.pipes = PIPE_SINGLE;
>       t.screen = SCREEN_PRIM;
>       t.plane = PLANE_PRI;
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to