From patchwork Mon Mar 23 17:42:04 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ramalingam C X-Patchwork-Id: 6074681 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 1A8839F399 for ; Mon, 23 Mar 2015 17:47:55 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6EADB2025B for ; Mon, 23 Mar 2015 17:47:53 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 2E22B201FE for ; Mon, 23 Mar 2015 17:47:52 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9221B6E604; Mon, 23 Mar 2015 10:47:51 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTP id 4FE826E604 for ; Mon, 23 Mar 2015 10:47:50 -0700 (PDT) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga103.fm.intel.com with ESMTP; 23 Mar 2015 10:47:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.11,453,1422950400"; d="scan'208";a="696478533" Received: from ramaling-desktop.iind.intel.com ([10.223.26.95]) by fmsmga002.fm.intel.com with ESMTP; 23 Mar 2015 10:47:48 -0700 From: Ramalingam C To: intel-gfx@lists.freedesktop.org, rodrigo.vivi@intel.com, daniel@ffwll.ch Date: Mon, 23 Mar 2015 23:12:04 +0530 Message-Id: <1427132524-27829-4-git-send-email-ramalingam.c@intel.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1427132524-27829-1-git-send-email-ramalingam.c@intel.com> References: <1427132524-27829-1-git-send-email-ramalingam.c@intel.com> MIME-Version: 1.0 Cc: paulo.r.zanoni@intel.com Subject: [Intel-gfx] =?utf-8?q?=5BPATCH=5D_tests/kms=5Fdrrs=3A_Test_Idlene?= =?utf-8?q?ss_DRRS?= X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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. And as soon as there is a display content change there will be a DRRS state transition as DRRS_LOW_RR--> DRRS_HIGH_RR. 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_HIGH_RR 2. After a delay of 1.2Sec DRRS_LOW_RR 3. After changing the frame buffer DRRS_HIGH_RR 4. After a delay of 1.2Sec DRRS_LOW_RR 5. After changing the frame buffer DRRS_HIGH_RR 6. After a delay of 1.2Sec DRRS_LOW_RR Signed-off-by: Ramalingam C Signed-off-by: Vandana Kannan --- tests/Makefile.sources | 1 + tests/kms_drrs.c | 376 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 377 insertions(+) create mode 100644 tests/kms_drrs.c diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 74deec3..2305cd4 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -65,6 +65,7 @@ TESTS_progs_M = \ gem_write_read_ring_switch \ kms_addfb \ kms_cursor_crc \ + kms_drrs \ kms_fbc_crc \ kms_flip \ kms_flip_event_leak \ diff --git a/tests/kms_drrs.c b/tests/kms_drrs.c new file mode 100644 index 0000000..91bda5c --- /dev/null +++ b/tests/kms_drrs.c @@ -0,0 +1,376 @@ +/* + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "drmtest.h" +#include "igt_debugfs.h" +#include "igt_kms.h" +#include "intel_chipset.h" +#include "intel_batchbuffer.h" +#include "ioctl_wrappers.h" +#include + +IGT_TEST_DESCRIPTION( +"Performs write operations and then waits for DRRS to invoke the" +"Low Refresh Rate and then disturbs the contents of the screen once" +"again hence DRRS revert back to High Refresh Rate(Default)."); + +#define DRRS_STATUS_BYTES_CNT 1000 + +typedef struct { + int drm_fd; + 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]; +} data_t; + +struct __attribute__((packed, aligned(16))) fb_status { + bool rendered; + unsigned fb_bits; +}; + +/* + * print_date_and_time : Func to print the date and time + */ +static void print_date_and_time(void) +{ + time_t curtime; + struct tm *loctime; + + curtime = time(NULL); + loctime = localtime(&curtime); + fputs (asctime (loctime), stdout); +} + +/* + * read_drrs_status : Func to read the DRRS status from debugfs + */ +static bool read_drrs_status(data_t *data, char *str) +{ + FILE *status; + int cnt; + + status = igt_debugfs_fopen("i915_drrs_status", "r"); + igt_assert(status); + + cnt = fread(str, DRRS_STATUS_BYTES_CNT - 1, 1, status); + if (!cnt) { + if (!feof(status)) { + igt_info("Err %d at fread\n", ferror(status)); + return false; + } + clearerr(status); + } + + fclose(status); + return true; +} + +/* + * is_drrs_enabled : Func to check for DRRS support + */ +static bool is_drrs_enabled(data_t *data) +{ + char str[DRRS_STATUS_BYTES_CNT] = {}; + + read_drrs_status(data, str); + return strstr(str, "DRRS Supported: Yes") != NULL; +} + +/* + * print_drrs_status : Func to print the DRRS status from the debugfs + */ +static bool print_drrs_status(data_t *data) +{ + char str[DRRS_STATUS_BYTES_CNT] = {}; + + read_drrs_status(data, str); + igt_info("%s\n", str); + + return true; +} + +/* + * is_drrs_state : Func to check the DRRS state + */ +static bool is_drrs_state(data_t *data, const char str[15]) +{ + char status[DRRS_STATUS_BYTES_CNT] = {}; + + read_drrs_status(data, status); + return strstr(status, str) != NULL; + +} + +static bool prepare_crtc(data_t *data) +{ + igt_display_t *display = &data->display; + igt_output_t *output = data->output; + + /* select the pipe we want to use */ + igt_output_set_pipe(output, data->pipe); + igt_display_commit(display); + + if (!output->valid) { + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit(display); + return false; + } + + return true; +} + +/* + * execute_test: + * + * This function creates two different Framebuffer fb0, fb1 + * and apply them in the interval of 1.2Sec. So between FB change + * DRRS should toggle from DRRS_HIGH_RR -> DRRS_LOW_RR. + * And on next FB change DRRS_LOW_RR -> DRRS_HIGH_RR. + * + * These expected transistions are verified using the kernel debugfs + */ +static bool execute_test(data_t *data) +{ + igt_display_t *display = &data->display; + igt_output_t *output = data->output; + drmModeModeInfo *mode; + bool test_failed = false; + + data->primary = igt_output_get_plane(data->output, IGT_PLANE_PRIMARY); + mode = igt_output_get_mode(data->output); + + data->fb_id[0] = igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + I915_TILING_X, + 0.0, 100.1, 0.0, &data->fb[0]); + igt_assert(data->fb_id[0]); + data->fb_id[1] = igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + I915_TILING_X, + 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; + + /* scanout = fb[1] */ + igt_plane_set_fb(data->primary, &data->fb[1]); + igt_display_commit(display); + + if (!is_drrs_enabled(data)) { + igt_info("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(data->drm_fd, &data->fb[0]); + igt_remove_fb(data->drm_fd, &data->fb[1]); + return false; + } + + igt_wait_for_vblank(data->drm_fd, data->pipe); + + + if (is_drrs_state(data, "DRRS_HIGH_RR")) { + igt_info("Expected DRRS_HIGH_RR : PASSED\n"); + } else { + igt_info("Expected DRRS_HIGH_RR : FAILED\n"); + test_failed = true; + } + + /* 1.2Sec to Enter the Idleness */ + usleep(1200000); + + if (is_drrs_state(data, "DRRS_LOW_RR")) { + igt_info("Expected DRRS_LOW_RR : PASSED\n"); + } else { + igt_info("Expected DRRS_LOW_RR : FAILED\n"); + test_failed = true; + } + + igt_wait_for_vblank(data->drm_fd, data->pipe); + + /* scanout = fb[0] */ + igt_plane_set_fb(data->primary, &data->fb[0]); + igt_display_commit(display); + + igt_wait_for_vblank(data->drm_fd, data->pipe); + + if (is_drrs_state(data, "DRRS_HIGH_RR")) { + igt_info("Expected DRRS_HIGH_RR : PASSED\n"); + } else { + igt_info("Expected DRRS_HIGH_RR : FAILED\n"); + test_failed = true; + } + + /* 1.2Sec to Enter the Idleness */ + usleep(1200000); + + if (is_drrs_state(data, "DRRS_LOW_RR")) { + igt_info("Expected DRRS_LOW_RR : PASSED\n"); + } else { + igt_info("Expected DRRS_LOW_RR : FAILED\n"); + test_failed = true; + } + + igt_wait_for_vblank(data->drm_fd, data->pipe); + + igt_plane_set_fb(data->primary, &data->fb[1]); + igt_display_commit(display); + + igt_wait_for_vblank(data->drm_fd, data->pipe); + + if (is_drrs_state(data, "DRRS_HIGH_RR")) { + igt_info("Expected DRRS_HIGH_RR : PASSED\n"); + } else { + igt_info("Expected DRRS_HIGH_RR : FAILED\n"); + test_failed = true; + } + + /* 1.2Sec to Enter the Idleness */ + usleep(1200000); + + if (is_drrs_state(data, "DRRS_LOW_RR")) { + igt_info("Expected DRRS_LOW_RR : PASSED\n"); + } else { + igt_info("Expected DRRS_LOW_RR : FAILED\n"); + test_failed = true; + } + + igt_wait_for_vblank(data->drm_fd, data->pipe); + + igt_assert(!test_failed); + return true; +} + +static void finish_crtc(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(data->drm_fd, &data->fb[0]); + igt_remove_fb(data->drm_fd, &data->fb[1]); +} + +static void reset_display(data_t *data) +{ + igt_display_t *display = &data->display; + + for_each_connected_output(display, data->output) { + if (data->output->valid) { + data->primary = igt_output_get_plane(data->output, + IGT_PLANE_PRIMARY); + igt_plane_set_fb(data->primary, NULL); + } + igt_output_set_pipe(data->output, PIPE_ANY); + } +} + +static void run_test(data_t *data) +{ + igt_display_t *display = &data->display; + int valid_tests = 0; + + reset_display(data); + + for_each_connected_output(display, data->output) { + for_each_pipe(display, data->pipe) { + if (!prepare_crtc(data)) + continue; + + igt_info("Beginning %s on pipe %s, connector %s\n", + igt_subtest_name(), + kmstest_pipe_name(data->pipe), + igt_output_name(data->output)); + + if (!execute_test(data)) { + igt_info("%s on pipe %s, connector %s: SKIPPED\n", + igt_subtest_name(), + kmstest_pipe_name(data->pipe), + igt_output_name(data->output)); + continue; + } + + valid_tests++; + + igt_info("%s on pipe %s, connector %s: PASSED\n", + igt_subtest_name(), + kmstest_pipe_name(data->pipe), + igt_output_name(data->output)); + + finish_crtc(data); + } + } + + igt_require_f(valid_tests, "no valid crtc/connector combinations found\n"); +} + +igt_main +{ + data_t data = {}; + + igt_skip_on_simulation(); + + igt_fixture { + char buf[64]; + int cnt; + FILE *status; + + data.drm_fd = drm_open_any_master(); + + data.devid = intel_get_drm_devid(data.drm_fd); + + status = igt_debugfs_fopen("i915_drrs_status", "r"); + igt_require_f(status, "No i915_drrs_status found\n"); + cnt = fread(buf, sizeof(buf), 1, status); + if (!cnt) { + igt_info("fread failed\n"); + return; + } + fclose(status); + buf[sizeof(buf) - 1] = '\0'; + igt_require_f(!strstr(buf, "disabled"), + "DRRS not supported:check VBT/panel caps\n"); + + /* Check if the DRRS is supported. + * If yes call the Idleness DRRS test */ + + igt_display_init(&data.display, data.drm_fd); + } + + igt_subtest_f("Idleness DRRS") + run_test(&data); + + igt_fixture { + igt_display_fini(&data.display); + } +}