blob: a695f90913fd62177b14ff38a1631138f55b7f92 [file] [log] [blame]
Antti Koskipaaf3867412015-05-28 14:44:54 +03001/*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Author:
24 * Antti Koskipaa <antti.koskipaa@linux.intel.com>
25 *
26 */
27
Thomas Wood804e11f2015-08-17 17:57:43 +010028#include "igt.h"
Antti Koskipaaf3867412015-05-28 14:44:54 +030029#include <limits.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <fcntl.h>
33#include <stdio.h>
34#include <errno.h>
35#include <unistd.h>
36#include <time.h>
37
Jani Nikula7afd94e2015-11-18 12:28:06 +020038struct context {
39 int max;
40};
41
Antti Koskipaaf3867412015-05-28 14:44:54 +030042
43#define TOLERANCE 5 /* percent */
44#define BACKLIGHT_PATH "/sys/class/backlight/intel_backlight"
45
46#define FADESTEPS 10
47#define FADESPEED 100 /* milliseconds between steps */
48
49IGT_TEST_DESCRIPTION("Basic backlight sysfs test");
50
51static int backlight_read(int *result, const char *fname)
52{
53 int fd;
54 char full[PATH_MAX];
55 char dst[64];
56 int r, e;
57
58 igt_assert(snprintf(full, PATH_MAX, "%s/%s", BACKLIGHT_PATH, fname) < PATH_MAX);
59
60 fd = open(full, O_RDONLY);
61 if (fd == -1)
62 return -errno;
63
64 r = read(fd, dst, sizeof(dst));
65 e = errno;
66 close(fd);
67
68 if (r < 0)
69 return -e;
70
71 errno = 0;
72 *result = strtol(dst, NULL, 10);
73 return errno;
74}
75
76static int backlight_write(int value, const char *fname)
77{
78 int fd;
79 char full[PATH_MAX];
80 char src[64];
81 int len;
82
83 igt_assert(snprintf(full, PATH_MAX, "%s/%s", BACKLIGHT_PATH, fname) < PATH_MAX);
84 fd = open(full, O_WRONLY);
85 if (fd == -1)
86 return -errno;
87
88 len = snprintf(src, sizeof(src), "%i", value);
89 len = write(fd, src, len);
90 close(fd);
91
92 if (len < 0)
93 return len;
94
95 return 0;
96}
97
Jani Nikula18170d22015-11-18 12:52:40 +020098static void test_and_verify(struct context *context, int val)
Antti Koskipaaf3867412015-05-28 14:44:54 +030099{
100 int result;
Jani Nikula77a76ba2015-11-18 12:46:53 +0200101 int tolerance = val * TOLERANCE / 100;
Antti Koskipaaf3867412015-05-28 14:44:54 +0300102
Daniel Stonede7ccdd2015-10-01 14:16:48 +0100103 igt_assert_eq(backlight_write(val, "brightness"), 0);
104 igt_assert_eq(backlight_read(&result, "brightness"), 0);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300105 /* Check that the exact value sticks */
Daniel Stonede7ccdd2015-10-01 14:16:48 +0100106 igt_assert_eq(result, val);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300107
Daniel Stonede7ccdd2015-10-01 14:16:48 +0100108 igt_assert_eq(backlight_read(&result, "actual_brightness"), 0);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300109 /* Some rounding may happen depending on hw. Just check that it's close enough. */
Jani Nikula18170d22015-11-18 12:52:40 +0200110 igt_assert_lte(result, min(context->max, val + tolerance));
111 igt_assert_lte(max(0, val - tolerance), result);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300112}
113
Jani Nikula7afd94e2015-11-18 12:28:06 +0200114static void test_brightness(struct context *context)
Antti Koskipaaf3867412015-05-28 14:44:54 +0300115{
Jani Nikula18170d22015-11-18 12:52:40 +0200116 test_and_verify(context, 0);
117 test_and_verify(context, context->max);
118 test_and_verify(context, context->max / 2);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300119}
120
Jani Nikula7afd94e2015-11-18 12:28:06 +0200121static void test_bad_brightness(struct context *context)
Antti Koskipaaf3867412015-05-28 14:44:54 +0300122{
123 int val;
124 /* First write some sane value */
Jani Nikula7afd94e2015-11-18 12:28:06 +0200125 backlight_write(context->max / 2, "brightness");
Antti Koskipaaf3867412015-05-28 14:44:54 +0300126 /* Writing invalid values should fail and not change the value */
Daniel Stonede7ccdd2015-10-01 14:16:48 +0100127 igt_assert_lt(backlight_write(-1, "brightness"), 0);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300128 backlight_read(&val, "brightness");
Jani Nikula7afd94e2015-11-18 12:28:06 +0200129 igt_assert_eq(val, context->max / 2);
130 igt_assert_lt(backlight_write(context->max + 1, "brightness"), 0);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300131 backlight_read(&val, "brightness");
Jani Nikula7afd94e2015-11-18 12:28:06 +0200132 igt_assert_eq(val, context->max / 2);
Daniel Stonede7ccdd2015-10-01 14:16:48 +0100133 igt_assert_lt(backlight_write(INT_MAX, "brightness"), 0);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300134 backlight_read(&val, "brightness");
Jani Nikula7afd94e2015-11-18 12:28:06 +0200135 igt_assert_eq(val, context->max / 2);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300136}
137
Jani Nikula7afd94e2015-11-18 12:28:06 +0200138static void test_fade(struct context *context)
Antti Koskipaaf3867412015-05-28 14:44:54 +0300139{
140 int i;
141 static const struct timespec ts = { .tv_sec = 0, .tv_nsec = FADESPEED*1000000 };
142
143 /* Fade out, then in */
Jani Nikula7afd94e2015-11-18 12:28:06 +0200144 for (i = context->max; i > 0; i -= context->max / FADESTEPS) {
Jani Nikula18170d22015-11-18 12:52:40 +0200145 test_and_verify(context, i);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300146 nanosleep(&ts, NULL);
147 }
Jani Nikula7afd94e2015-11-18 12:28:06 +0200148 for (i = 0; i <= context->max; i += context->max / FADESTEPS) {
Jani Nikula18170d22015-11-18 12:52:40 +0200149 test_and_verify(context, i);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300150 nanosleep(&ts, NULL);
151 }
152}
153
154igt_main
155{
Jani Nikula7afd94e2015-11-18 12:28:06 +0200156 struct context context = {0};
157 int old;
Maarten Lankhorst69fbd442017-10-10 17:57:29 +0200158 igt_display_t display;
159 struct igt_fb fb;
Antti Koskipaaf3867412015-05-28 14:44:54 +0300160
161 igt_skip_on_simulation();
162
163 igt_fixture {
Maarten Lankhorst69fbd442017-10-10 17:57:29 +0200164 enum pipe pipe;
165 igt_output_t *output;
166 bool found = false;
167 char full_name[32] = {};
168 char *name;
169 drmModeModeInfo *mode;
170 igt_plane_t *primary;
171
Antti Koskipaaf3867412015-05-28 14:44:54 +0300172 /* Get the max value and skip the whole test if sysfs interface not available */
173 igt_skip_on(backlight_read(&old, "brightness"));
Jani Nikula7afd94e2015-11-18 12:28:06 +0200174 igt_assert(backlight_read(&context.max, "max_brightness") > -1);
Maarten Lankhorst69fbd442017-10-10 17:57:29 +0200175
176 /*
177 * Backlight tests requires the output to be enabled,
178 * try to enable all.
179 */
180 kmstest_set_vt_graphics_mode();
181 igt_display_init(&display, drm_open_driver(DRIVER_INTEL));
182
183 /* should be ../../cardX-$output */
184 igt_assert_lt(12, readlink(BACKLIGHT_PATH "/device", full_name, sizeof(full_name) - 1));
185 name = basename(full_name);
186
187 for_each_pipe_with_valid_output(&display, pipe, output) {
188 if (strcmp(name + 6, output->name))
189 continue;
190
191 found = true;
192 break;
193 }
194
195 igt_assert_f(found, "Could not map \"%s\" to output (%s?)\n", name, name + 6);
196
197 igt_output_set_pipe(output, pipe);
198 mode = igt_output_get_mode(output);
199
200 igt_create_pattern_fb(display.drm_fd,
201 mode->hdisplay, mode->vdisplay,
202 DRM_FORMAT_XRGB8888,
203 LOCAL_DRM_FORMAT_MOD_NONE, &fb);
204 primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
205 igt_plane_set_fb(primary, &fb);
206
207 igt_display_commit2(&display, display.is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300208 }
209
Jesse Barnes68d1b532015-08-13 13:13:23 -0700210 igt_subtest("basic-brightness")
Jani Nikula7afd94e2015-11-18 12:28:06 +0200211 test_brightness(&context);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300212 igt_subtest("bad-brightness")
Jani Nikula7afd94e2015-11-18 12:28:06 +0200213 test_bad_brightness(&context);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300214 igt_subtest("fade")
Jani Nikula7afd94e2015-11-18 12:28:06 +0200215 test_fade(&context);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300216
217 igt_fixture {
218 /* Restore old brightness */
219 backlight_write(old, "brightness");
Maarten Lankhorst69fbd442017-10-10 17:57:29 +0200220
221 igt_display_fini(&display);
222 igt_remove_fb(display.drm_fd, &fb);
223 close(display.drm_fd);
Antti Koskipaaf3867412015-05-28 14:44:54 +0300224 }
225}