• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 Advanced Micro Devices, Inc.
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 shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "igt.h"
24 #include "drmtest.h"
25 #include "igt_kms.h"
26 #include <limits.h>
27 #include <errno.h>
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <time.h>
34 
35 #define BACKLIGHT_PATH "/sys/class/backlight/amdgpu_bl0"
36 
37 typedef struct data {
38 	igt_display_t display;
39 	int drm_fd;
40 	int debugfs;
41 	uint32_t output_id;
42 	uint32_t abm_prop_id;
43 } data_t;
44 
read_current_backlight_pwm(int debugfs_dir)45 static int read_current_backlight_pwm(int debugfs_dir)
46 {
47 	char buf[20];
48 
49 	igt_debugfs_simple_read(debugfs_dir, "amdgpu_current_backlight_pwm",
50 			 buf, sizeof(buf));
51 
52 	return strtol(buf, NULL, 0);
53 }
54 
read_target_backlight_pwm(int debugfs_dir)55 static int read_target_backlight_pwm(int debugfs_dir)
56 {
57 	char buf[20];
58 
59 	igt_debugfs_simple_read(debugfs_dir, "amdgpu_target_backlight_pwm",
60 			 buf, sizeof(buf));
61 
62 	return strtol(buf, NULL, 0);
63 }
64 
backlight_write_brightness(int value)65 static int backlight_write_brightness(int value)
66 {
67 	int fd;
68 	char full[PATH_MAX];
69 	char src[64];
70 	int len;
71 
72 	igt_assert(snprintf(full, PATH_MAX, "%s/%s", BACKLIGHT_PATH, "brightness") < PATH_MAX);
73 	fd = open(full, O_WRONLY);
74 	if (fd == -1)
75 		return -errno;
76 
77 	len = snprintf(src, sizeof(src), "%i", value);
78 	len = write(fd, src, len);
79 	close(fd);
80 
81 	if (len < 0)
82 		return len;
83 
84 	return 0;
85 }
86 
set_abm_level(data_t * data,int level)87 static void set_abm_level(data_t *data, int level)
88 {
89 	uint32_t type = DRM_MODE_OBJECT_CONNECTOR;
90 	int ret;
91 
92 	ret = drmModeObjectSetProperty(data->drm_fd, data->output_id, type,
93 				       data->abm_prop_id, level);
94 	igt_assert_eq(ret, 0);
95 }
96 
backlight_read_max_brightness(int * result)97 static int backlight_read_max_brightness(int *result)
98 {
99 	int fd;
100 	char full[PATH_MAX];
101 	char dst[64];
102 	int r, e;
103 
104 	igt_assert(snprintf(full, PATH_MAX, "%s/%s", BACKLIGHT_PATH, "max_brightness") < PATH_MAX);
105 
106 	fd = open(full, O_RDONLY);
107 	if (fd == -1)
108 		return -errno;
109 
110 	r = read(fd, dst, sizeof(dst));
111 	e = errno;
112 	close(fd);
113 
114 	if (r < 0)
115 		return -e;
116 
117 	errno = 0;
118 	*result = strtol(dst, NULL, 10);
119 	return errno;
120 }
121 
test_init(data_t * data)122 static void test_init(data_t *data)
123 {
124 	igt_display_t *display = &data->display;
125 	int ret, i;
126 	char buf[20];
127 	bool abm_prop_exists;
128 	uint32_t type = DRM_MODE_OBJECT_CONNECTOR;
129 
130 	ret = igt_debugfs_simple_read(data->debugfs, "amdgpu_current_backlight_pwm",
131 			 buf, sizeof(buf));
132 
133 	if (ret < 0)
134 		igt_skip("No current backlight debugfs entry.\n");
135 
136 	ret = igt_debugfs_simple_read(data->debugfs, "amdgpu_target_backlight_pwm",
137 			 buf, sizeof(buf));
138 
139 	if (ret < 0)
140 		igt_skip("No target backlight debugfs entry.\n");
141 
142 	abm_prop_exists = false;
143 
144 	for (i = 0; i < display->n_outputs; i++) {
145 		data->output_id = display->outputs[i].id;
146 
147 		abm_prop_exists = kmstest_get_property(
148 			data->drm_fd, data->output_id, type, "abm level",
149 			&data->abm_prop_id, NULL, NULL);
150 
151 		if (abm_prop_exists)
152 			break;
153 	}
154 
155 	if (!abm_prop_exists)
156 		igt_skip("No abm level property on any connector.\n");
157 }
158 
159 
backlight_dpms_cycle(data_t * data,igt_output_t * output)160 static void backlight_dpms_cycle(data_t *data, igt_output_t *output)
161 {
162 	int ret;
163 	int max_brightness;
164 	int pwm_1, pwm_2;
165 
166 	ret = backlight_read_max_brightness(&max_brightness);
167 	igt_assert_eq(ret, 0);
168 
169 	set_abm_level(data, 0);
170 	backlight_write_brightness(max_brightness / 2);
171 	usleep(100000);
172 	pwm_1 = read_target_backlight_pwm(data->debugfs);
173 
174 	kmstest_set_connector_dpms(data->drm_fd, output->config.connector, DRM_MODE_DPMS_OFF);
175 	kmstest_set_connector_dpms(data->drm_fd, output->config.connector, DRM_MODE_DPMS_ON);
176 	usleep(100000);
177 	pwm_2 = read_target_backlight_pwm(data->debugfs);
178 	igt_assert_eq(pwm_1, pwm_2);
179 }
180 
backlight_monotonic_basic(data_t * data)181 static void backlight_monotonic_basic(data_t *data)
182 {
183 	int ret;
184 	int max_brightness;
185 	int prev_pwm, pwm;
186 	int brightness_step;
187 	int brightness;
188 
189 	ret = backlight_read_max_brightness(&max_brightness);
190 	igt_assert_eq(ret, 0);
191 
192 	brightness_step = max_brightness / 10;
193 
194 	set_abm_level(data, 0);
195 	backlight_write_brightness(max_brightness);
196 	usleep(100000);
197 	prev_pwm = read_target_backlight_pwm(data->debugfs);
198 	for (brightness = max_brightness - brightness_step;
199 	     brightness > 0;
200 	     brightness -= brightness_step) {
201 		backlight_write_brightness(brightness);
202 		usleep(100000);
203 		pwm = read_target_backlight_pwm(data->debugfs);
204 		igt_assert(pwm < prev_pwm);
205 		prev_pwm = pwm;
206 	}
207 
208 }
209 
backlight_monotonic_abm(data_t * data)210 static void backlight_monotonic_abm(data_t *data)
211 {
212 	int ret, i;
213 	int max_brightness;
214 	int prev_pwm, pwm;
215 	int brightness_step;
216 	int brightness;
217 
218 	ret = backlight_read_max_brightness(&max_brightness);
219 	igt_assert_eq(ret, 0);
220 
221 	brightness_step = max_brightness / 10;
222 	for (i = 1; i < 5; i++) {
223 		set_abm_level(data, i);
224 		backlight_write_brightness(max_brightness);
225 		usleep(100000);
226 		prev_pwm = read_target_backlight_pwm(data->debugfs);
227 		for (brightness = max_brightness - brightness_step;
228 		     brightness > 0;
229 		     brightness -= brightness_step) {
230 			backlight_write_brightness(brightness);
231 			usleep(100000);
232 			pwm = read_target_backlight_pwm(data->debugfs);
233 			igt_assert(pwm < prev_pwm);
234 			prev_pwm = pwm;
235 		}
236 	}
237 }
238 
abm_enabled(data_t * data)239 static void abm_enabled(data_t *data)
240 {
241 	int ret, i;
242 	int max_brightness;
243 	int pwm, prev_pwm, pwm_without_abm;
244 
245 	ret = backlight_read_max_brightness(&max_brightness);
246 	igt_assert_eq(ret, 0);
247 
248 	set_abm_level(data, 0);
249 	backlight_write_brightness(max_brightness);
250 	usleep(100000);
251 	prev_pwm = read_target_backlight_pwm(data->debugfs);
252 	pwm_without_abm = prev_pwm;
253 
254 	for (i = 1; i < 5; i++) {
255 		set_abm_level(data, i);
256 		usleep(100000);
257 		pwm = read_target_backlight_pwm(data->debugfs);
258 		igt_assert(pwm <= prev_pwm);
259 		igt_assert(pwm < pwm_without_abm);
260 		prev_pwm = pwm;
261 	}
262 
263 }
264 
abm_gradual(data_t * data)265 static void abm_gradual(data_t *data)
266 {
267 	int ret, i;
268 	int convergence_delay = 15;
269 	int prev_pwm, pwm, curr;
270 	int max_brightness;
271 
272 	ret = backlight_read_max_brightness(&max_brightness);
273 
274 	igt_assert_eq(ret, 0);
275 
276 	set_abm_level(data, 0);
277 	backlight_write_brightness(max_brightness);
278 
279 	sleep(convergence_delay);
280 	prev_pwm = read_target_backlight_pwm(data->debugfs);
281 	curr = read_current_backlight_pwm(data->debugfs);
282 
283 	igt_assert_eq(prev_pwm, curr);
284 	set_abm_level(data, 4);
285 	for (i = 0; i < 10; i++) {
286 		usleep(100000);
287 		pwm = read_current_backlight_pwm(data->debugfs);
288 		igt_assert(pwm < prev_pwm);
289 		prev_pwm = pwm;
290 	}
291 
292 	sleep(convergence_delay - 1);
293 
294 	prev_pwm = read_target_backlight_pwm(data->debugfs);
295 	curr = read_current_backlight_pwm(data->debugfs);
296 
297 	igt_assert_eq(prev_pwm, curr);
298 }
299 
300 igt_main
301 {
302 	data_t data = { 0 };
303 	enum pipe pipe;
304 	igt_output_t *output;
305 
306 	igt_skip_on_simulation();
307 
308 	igt_fixture {
309 		data.drm_fd = drm_open_driver_master(DRIVER_AMDGPU);
310 
311 		if (data.drm_fd == -1)
312 			igt_skip("Not an amdgpu driver.\n");
313 
314 		data.debugfs = igt_debugfs_dir(data.drm_fd);
315 
316 		kmstest_set_vt_graphics_mode();
317 
318 		igt_display_require(&data.display, data.drm_fd);
319 
320 		test_init(&data);
321 
322 		for_each_pipe_with_valid_output(&data.display, pipe, output) {
323 			if (output->config.connector->connector_type == DRM_MODE_CONNECTOR_eDP)
324 				break;
325 		}
326 	}
327 
328 	igt_subtest("dpms_cycle")
329 		backlight_dpms_cycle(&data, output);
330 	igt_subtest("backlight_monotonic_basic")
331 		backlight_monotonic_basic(&data);
332 	igt_subtest("backlight_monotonic_abm")
333 		backlight_monotonic_abm(&data);
334 	igt_subtest("abm_enabled")
335 		abm_enabled(&data);
336 	igt_subtest("abm_gradual")
337 		abm_gradual(&data);
338 
339 	igt_fixture {
340 		igt_display_fini(&data.display);
341 	}
342 }
343