xref: /aosp_15_r20/external/igt-gpu-tools/tools/intel_gpu_frequency.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2015,2018 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*d83cc019SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  */
23*d83cc019SAndroid Build Coastguard Worker 
24*d83cc019SAndroid Build Coastguard Worker #include <assert.h>
25*d83cc019SAndroid Build Coastguard Worker #include <getopt.h>
26*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
27*d83cc019SAndroid Build Coastguard Worker #include <time.h>
28*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
29*d83cc019SAndroid Build Coastguard Worker 
30*d83cc019SAndroid Build Coastguard Worker #include "drmtest.h"
31*d83cc019SAndroid Build Coastguard Worker #include "igt_device.h"
32*d83cc019SAndroid Build Coastguard Worker #include "intel_chipset.h"
33*d83cc019SAndroid Build Coastguard Worker 
34*d83cc019SAndroid Build Coastguard Worker #define VERSION "1.0"
35*d83cc019SAndroid Build Coastguard Worker 
36*d83cc019SAndroid Build Coastguard Worker static int device, devid;
37*d83cc019SAndroid Build Coastguard Worker 
38*d83cc019SAndroid Build Coastguard Worker enum {
39*d83cc019SAndroid Build Coastguard Worker 	CUR=0,
40*d83cc019SAndroid Build Coastguard Worker 	MIN,
41*d83cc019SAndroid Build Coastguard Worker 	EFF,
42*d83cc019SAndroid Build Coastguard Worker 	MAX,
43*d83cc019SAndroid Build Coastguard Worker 	RP0,
44*d83cc019SAndroid Build Coastguard Worker 	RPn
45*d83cc019SAndroid Build Coastguard Worker };
46*d83cc019SAndroid Build Coastguard Worker 
47*d83cc019SAndroid Build Coastguard Worker struct freq_info {
48*d83cc019SAndroid Build Coastguard Worker 	const char *name;
49*d83cc019SAndroid Build Coastguard Worker 	const char *mode;
50*d83cc019SAndroid Build Coastguard Worker 	FILE *filp;
51*d83cc019SAndroid Build Coastguard Worker 	char *path;
52*d83cc019SAndroid Build Coastguard Worker };
53*d83cc019SAndroid Build Coastguard Worker 
54*d83cc019SAndroid Build Coastguard Worker static struct freq_info info[] = {
55*d83cc019SAndroid Build Coastguard Worker 	{ "cur", "r"  },
56*d83cc019SAndroid Build Coastguard Worker 	{ "min", "rb+" },
57*d83cc019SAndroid Build Coastguard Worker 	{ "RP1", "r" },
58*d83cc019SAndroid Build Coastguard Worker 	{ "max", "rb+" },
59*d83cc019SAndroid Build Coastguard Worker 	{ "RP0", "r" },
60*d83cc019SAndroid Build Coastguard Worker 	{ "RPn", "r" }
61*d83cc019SAndroid Build Coastguard Worker };
62*d83cc019SAndroid Build Coastguard Worker 
63*d83cc019SAndroid Build Coastguard Worker static char *
get_sysfs_path(const char * which)64*d83cc019SAndroid Build Coastguard Worker get_sysfs_path(const char *which)
65*d83cc019SAndroid Build Coastguard Worker {
66*d83cc019SAndroid Build Coastguard Worker 	static const char fmt[] = "/sys/class/drm/card%1d/gt_%3s_freq_mhz";
67*d83cc019SAndroid Build Coastguard Worker 	char *path;
68*d83cc019SAndroid Build Coastguard Worker 	int ret;
69*d83cc019SAndroid Build Coastguard Worker 
70*d83cc019SAndroid Build Coastguard Worker #define STATIC_STRLEN(string) (sizeof(string) / sizeof(string [0]))
71*d83cc019SAndroid Build Coastguard Worker 	ret = asprintf(&path, fmt, device, which);
72*d83cc019SAndroid Build Coastguard Worker 	assert(ret == (STATIC_STRLEN(fmt) - 3));
73*d83cc019SAndroid Build Coastguard Worker #undef STATIC_STRLEN
74*d83cc019SAndroid Build Coastguard Worker 
75*d83cc019SAndroid Build Coastguard Worker 	return path;
76*d83cc019SAndroid Build Coastguard Worker }
77*d83cc019SAndroid Build Coastguard Worker 
78*d83cc019SAndroid Build Coastguard Worker static void
initialize_freq_info(struct freq_info * freq_info)79*d83cc019SAndroid Build Coastguard Worker initialize_freq_info(struct freq_info *freq_info)
80*d83cc019SAndroid Build Coastguard Worker {
81*d83cc019SAndroid Build Coastguard Worker 	if (freq_info->filp)
82*d83cc019SAndroid Build Coastguard Worker 		return;
83*d83cc019SAndroid Build Coastguard Worker 
84*d83cc019SAndroid Build Coastguard Worker 	freq_info->path = get_sysfs_path(freq_info->name);
85*d83cc019SAndroid Build Coastguard Worker 	assert(freq_info->path);
86*d83cc019SAndroid Build Coastguard Worker 	freq_info->filp = fopen(freq_info->path, freq_info->mode);
87*d83cc019SAndroid Build Coastguard Worker 	assert(freq_info->filp);
88*d83cc019SAndroid Build Coastguard Worker }
89*d83cc019SAndroid Build Coastguard Worker 
wait_freq_settle(void)90*d83cc019SAndroid Build Coastguard Worker static void wait_freq_settle(void)
91*d83cc019SAndroid Build Coastguard Worker {
92*d83cc019SAndroid Build Coastguard Worker 	struct timespec ts;
93*d83cc019SAndroid Build Coastguard Worker 
94*d83cc019SAndroid Build Coastguard Worker 	/* FIXME: Lazy sleep without check. */
95*d83cc019SAndroid Build Coastguard Worker 	ts.tv_sec = 0;
96*d83cc019SAndroid Build Coastguard Worker 	ts.tv_nsec = 20000;
97*d83cc019SAndroid Build Coastguard Worker 	clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
98*d83cc019SAndroid Build Coastguard Worker }
99*d83cc019SAndroid Build Coastguard Worker 
set_frequency(struct freq_info * freq_info,int val)100*d83cc019SAndroid Build Coastguard Worker static void set_frequency(struct freq_info *freq_info, int val)
101*d83cc019SAndroid Build Coastguard Worker {
102*d83cc019SAndroid Build Coastguard Worker 	initialize_freq_info(freq_info);
103*d83cc019SAndroid Build Coastguard Worker 	rewind(freq_info->filp);
104*d83cc019SAndroid Build Coastguard Worker 	assert(fprintf(freq_info->filp, "%d", val) > 0);
105*d83cc019SAndroid Build Coastguard Worker 
106*d83cc019SAndroid Build Coastguard Worker 	wait_freq_settle();
107*d83cc019SAndroid Build Coastguard Worker }
108*d83cc019SAndroid Build Coastguard Worker 
get_frequency(struct freq_info * freq_info)109*d83cc019SAndroid Build Coastguard Worker static int get_frequency(struct freq_info *freq_info)
110*d83cc019SAndroid Build Coastguard Worker {
111*d83cc019SAndroid Build Coastguard Worker 	int val;
112*d83cc019SAndroid Build Coastguard Worker 
113*d83cc019SAndroid Build Coastguard Worker 	initialize_freq_info(freq_info);
114*d83cc019SAndroid Build Coastguard Worker 	rewind(freq_info->filp);
115*d83cc019SAndroid Build Coastguard Worker 	assert(fscanf(freq_info->filp, "%d", &val)==1);
116*d83cc019SAndroid Build Coastguard Worker 
117*d83cc019SAndroid Build Coastguard Worker 	return val;
118*d83cc019SAndroid Build Coastguard Worker }
119*d83cc019SAndroid Build Coastguard Worker 
120*d83cc019SAndroid Build Coastguard Worker static void __attribute__((noreturn))
usage(const char * prog)121*d83cc019SAndroid Build Coastguard Worker usage(const char *prog)
122*d83cc019SAndroid Build Coastguard Worker {
123*d83cc019SAndroid Build Coastguard Worker 	printf("%s A program to manipulate Intel GPU frequencies.\n\n", prog);
124*d83cc019SAndroid Build Coastguard Worker 	printf("Usage: %s [-e] [--min | --max] [--get] [--set frequency_mhz]\n\n", prog);
125*d83cc019SAndroid Build Coastguard Worker 	printf("Options: \n");
126*d83cc019SAndroid Build Coastguard Worker 	printf("  -e		Lock frequency to the most efficient frequency\n");
127*d83cc019SAndroid Build Coastguard Worker 	printf("  -g, --get     Get all the frequency settings\n");
128*d83cc019SAndroid Build Coastguard Worker 	printf("  -s, --set     Lock frequency to an absolute value (MHz)\n");
129*d83cc019SAndroid Build Coastguard Worker 	printf("  -c, --custom  Set a min, or max frequency \"min=X | max=Y\"\n");
130*d83cc019SAndroid Build Coastguard Worker 	printf("  -m  --max     Lock frequency to max frequency\n");
131*d83cc019SAndroid Build Coastguard Worker 	printf("  -i  --min     Lock frequency to min (never a good idea, DEBUG ONLY)\n");
132*d83cc019SAndroid Build Coastguard Worker 	printf("  -d  --defaults  Return the system to hardware defaults\n");
133*d83cc019SAndroid Build Coastguard Worker 	printf("  -h  --help    Returns this\n");
134*d83cc019SAndroid Build Coastguard Worker 	printf("  -v  --version Version\n");
135*d83cc019SAndroid Build Coastguard Worker 	printf("\n");
136*d83cc019SAndroid Build Coastguard Worker 	printf("Examples:\n");
137*d83cc019SAndroid Build Coastguard Worker 	printf("   intel_gpu_frequency --get\t\tGet the current and minimum frequency\n");
138*d83cc019SAndroid Build Coastguard Worker 	printf("   intel_gpu_frequency --set 400\tLock frequency to 400Mhz\n");
139*d83cc019SAndroid Build Coastguard Worker 	printf("   intel_gpu_frequency --custom max=750\tSet the max frequency to 750MHz\n");
140*d83cc019SAndroid Build Coastguard Worker 	printf("\n");
141*d83cc019SAndroid Build Coastguard Worker 	printf("Report bugs to <bugs.freedesktop.org>\n");
142*d83cc019SAndroid Build Coastguard Worker 	exit(EXIT_FAILURE);
143*d83cc019SAndroid Build Coastguard Worker }
144*d83cc019SAndroid Build Coastguard Worker 
145*d83cc019SAndroid Build Coastguard Worker static void
version(const char * prog)146*d83cc019SAndroid Build Coastguard Worker version(const char *prog)
147*d83cc019SAndroid Build Coastguard Worker {
148*d83cc019SAndroid Build Coastguard Worker 	printf("%s: %s\n", prog, VERSION);
149*d83cc019SAndroid Build Coastguard Worker 	printf("Copyright © 2015,2018 Intel Corporation\n");
150*d83cc019SAndroid Build Coastguard Worker }
151*d83cc019SAndroid Build Coastguard Worker 
152*d83cc019SAndroid Build Coastguard Worker /* Returns read or write operation */
153*d83cc019SAndroid Build Coastguard Worker static bool
parse(int argc,char * argv[],bool * act_upon,size_t act_upon_n,int * new_freq)154*d83cc019SAndroid Build Coastguard Worker parse(int argc, char *argv[], bool *act_upon, size_t act_upon_n, int *new_freq)
155*d83cc019SAndroid Build Coastguard Worker {
156*d83cc019SAndroid Build Coastguard Worker 	int c, tmp;
157*d83cc019SAndroid Build Coastguard Worker 	bool write = false;
158*d83cc019SAndroid Build Coastguard Worker 
159*d83cc019SAndroid Build Coastguard Worker 	/* No args means -g" */
160*d83cc019SAndroid Build Coastguard Worker 	if (argc == 1) {
161*d83cc019SAndroid Build Coastguard Worker 		for (c = 0; c < act_upon_n; c++)
162*d83cc019SAndroid Build Coastguard Worker 			act_upon[c] = true;
163*d83cc019SAndroid Build Coastguard Worker 		goto done;
164*d83cc019SAndroid Build Coastguard Worker 	}
165*d83cc019SAndroid Build Coastguard Worker 	while (1) {
166*d83cc019SAndroid Build Coastguard Worker 		int option_index = 0;
167*d83cc019SAndroid Build Coastguard Worker 		static struct option long_options[] = {
168*d83cc019SAndroid Build Coastguard Worker 			{ "get", no_argument, NULL, 'g' },
169*d83cc019SAndroid Build Coastguard Worker 			{ "set", required_argument, NULL, 's' },
170*d83cc019SAndroid Build Coastguard Worker 			{ "custom", required_argument, NULL, 'c'},
171*d83cc019SAndroid Build Coastguard Worker 			{ "min", no_argument, NULL, 'i' },
172*d83cc019SAndroid Build Coastguard Worker 			{ "max", no_argument, NULL, 'm' },
173*d83cc019SAndroid Build Coastguard Worker 			{ "defaults", no_argument, NULL, 'd' },
174*d83cc019SAndroid Build Coastguard Worker 			{ "help", no_argument, NULL, 'h' },
175*d83cc019SAndroid Build Coastguard Worker 			{ "version", no_argument, NULL, 'v' },
176*d83cc019SAndroid Build Coastguard Worker 			{ NULL, 0, NULL, 0}
177*d83cc019SAndroid Build Coastguard Worker 		};
178*d83cc019SAndroid Build Coastguard Worker 
179*d83cc019SAndroid Build Coastguard Worker 		c = getopt_long(argc, argv, "egs:c:midh", long_options, &option_index);
180*d83cc019SAndroid Build Coastguard Worker 		if (c == -1)
181*d83cc019SAndroid Build Coastguard Worker 			break;
182*d83cc019SAndroid Build Coastguard Worker 
183*d83cc019SAndroid Build Coastguard Worker 		switch (c) {
184*d83cc019SAndroid Build Coastguard Worker 		case 'g':
185*d83cc019SAndroid Build Coastguard Worker 			if (write == true)
186*d83cc019SAndroid Build Coastguard Worker 				fprintf(stderr, "Read and write operations not support simultaneously.\n");
187*d83cc019SAndroid Build Coastguard Worker 			{
188*d83cc019SAndroid Build Coastguard Worker 				int i;
189*d83cc019SAndroid Build Coastguard Worker 				for (i = 0; i < act_upon_n; i++)
190*d83cc019SAndroid Build Coastguard Worker 					act_upon[i] = true;
191*d83cc019SAndroid Build Coastguard Worker 			}
192*d83cc019SAndroid Build Coastguard Worker 			break;
193*d83cc019SAndroid Build Coastguard Worker 		case 's':
194*d83cc019SAndroid Build Coastguard Worker 			if (!optarg)
195*d83cc019SAndroid Build Coastguard Worker 				usage(argv[0]);
196*d83cc019SAndroid Build Coastguard Worker 
197*d83cc019SAndroid Build Coastguard Worker 			if (write == true) {
198*d83cc019SAndroid Build Coastguard Worker 				fprintf(stderr, "Only one write may be specified at a time\n");
199*d83cc019SAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
200*d83cc019SAndroid Build Coastguard Worker 			}
201*d83cc019SAndroid Build Coastguard Worker 
202*d83cc019SAndroid Build Coastguard Worker 			write = true;
203*d83cc019SAndroid Build Coastguard Worker 			act_upon[MIN] = true;
204*d83cc019SAndroid Build Coastguard Worker 			act_upon[MAX] = true;
205*d83cc019SAndroid Build Coastguard Worker 			sscanf(optarg, "%d", &new_freq[MAX]);
206*d83cc019SAndroid Build Coastguard Worker 			new_freq[MIN] = new_freq[MAX];
207*d83cc019SAndroid Build Coastguard Worker 			break;
208*d83cc019SAndroid Build Coastguard Worker 		case 'c':
209*d83cc019SAndroid Build Coastguard Worker 			if (!optarg)
210*d83cc019SAndroid Build Coastguard Worker 				usage(argv[0]);
211*d83cc019SAndroid Build Coastguard Worker 
212*d83cc019SAndroid Build Coastguard Worker 			if (write == true) {
213*d83cc019SAndroid Build Coastguard Worker 				fprintf(stderr, "Only one write may be specified at a time\n");
214*d83cc019SAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
215*d83cc019SAndroid Build Coastguard Worker 			}
216*d83cc019SAndroid Build Coastguard Worker 
217*d83cc019SAndroid Build Coastguard Worker 			write = true;
218*d83cc019SAndroid Build Coastguard Worker 
219*d83cc019SAndroid Build Coastguard Worker 			if (!strncmp("min=", optarg, 4)) {
220*d83cc019SAndroid Build Coastguard Worker 				act_upon[MIN] = true;
221*d83cc019SAndroid Build Coastguard Worker 				sscanf(optarg+4, "%d", &new_freq[MIN]);
222*d83cc019SAndroid Build Coastguard Worker 			} else if (!strncmp("max=", optarg, 4)) {
223*d83cc019SAndroid Build Coastguard Worker 				act_upon[MAX] = true;
224*d83cc019SAndroid Build Coastguard Worker 				sscanf(optarg+4, "%d", &new_freq[MAX]);
225*d83cc019SAndroid Build Coastguard Worker 			} else {
226*d83cc019SAndroid Build Coastguard Worker 				fprintf(stderr, "Selected unmodifiable frequency\n");
227*d83cc019SAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
228*d83cc019SAndroid Build Coastguard Worker 			}
229*d83cc019SAndroid Build Coastguard Worker 			break;
230*d83cc019SAndroid Build Coastguard Worker 		case 'e': /* efficient */
231*d83cc019SAndroid Build Coastguard Worker 			if (IS_VALLEYVIEW(devid) || IS_CHERRYVIEW(devid)) {
232*d83cc019SAndroid Build Coastguard Worker 				/* the LP parts have special efficient frequencies */
233*d83cc019SAndroid Build Coastguard Worker 				fprintf(stderr,
234*d83cc019SAndroid Build Coastguard Worker 					"FIXME: Warning efficient frequency information is incorrect.\n");
235*d83cc019SAndroid Build Coastguard Worker 				exit(EXIT_FAILURE);
236*d83cc019SAndroid Build Coastguard Worker 			}
237*d83cc019SAndroid Build Coastguard Worker 			tmp = get_frequency(&info[EFF]);
238*d83cc019SAndroid Build Coastguard Worker 			new_freq[MIN] = tmp;
239*d83cc019SAndroid Build Coastguard Worker 			new_freq[MAX] = tmp;
240*d83cc019SAndroid Build Coastguard Worker 			act_upon[MIN] = true;
241*d83cc019SAndroid Build Coastguard Worker 			act_upon[MAX] = true;
242*d83cc019SAndroid Build Coastguard Worker 			write = true;
243*d83cc019SAndroid Build Coastguard Worker 			break;
244*d83cc019SAndroid Build Coastguard Worker 		case 'i': /* mIn */
245*d83cc019SAndroid Build Coastguard Worker 			tmp = get_frequency(&info[RPn]);
246*d83cc019SAndroid Build Coastguard Worker 			new_freq[MIN] = tmp;
247*d83cc019SAndroid Build Coastguard Worker 			new_freq[MAX] = tmp;
248*d83cc019SAndroid Build Coastguard Worker 			act_upon[MIN] = true;
249*d83cc019SAndroid Build Coastguard Worker 			act_upon[MAX] = true;
250*d83cc019SAndroid Build Coastguard Worker 			write = true;
251*d83cc019SAndroid Build Coastguard Worker 			break;
252*d83cc019SAndroid Build Coastguard Worker 		case 'm': /* max */
253*d83cc019SAndroid Build Coastguard Worker 			tmp = get_frequency(&info[RP0]);
254*d83cc019SAndroid Build Coastguard Worker 			new_freq[MIN] = tmp;
255*d83cc019SAndroid Build Coastguard Worker 			new_freq[MAX] = tmp;
256*d83cc019SAndroid Build Coastguard Worker 			act_upon[MIN] = true;
257*d83cc019SAndroid Build Coastguard Worker 			act_upon[MAX] = true;
258*d83cc019SAndroid Build Coastguard Worker 			write = true;
259*d83cc019SAndroid Build Coastguard Worker 			break;
260*d83cc019SAndroid Build Coastguard Worker 		case 'd': /* defaults */
261*d83cc019SAndroid Build Coastguard Worker 			new_freq[MIN] = get_frequency(&info[RPn]);
262*d83cc019SAndroid Build Coastguard Worker 			new_freq[MAX] = get_frequency(&info[RP0]);
263*d83cc019SAndroid Build Coastguard Worker 			act_upon[MIN] = true;
264*d83cc019SAndroid Build Coastguard Worker 			act_upon[MAX] = true;
265*d83cc019SAndroid Build Coastguard Worker 			write = true;
266*d83cc019SAndroid Build Coastguard Worker 			break;
267*d83cc019SAndroid Build Coastguard Worker 		case 'v':
268*d83cc019SAndroid Build Coastguard Worker 			version(argv[0]);
269*d83cc019SAndroid Build Coastguard Worker 			exit(0);
270*d83cc019SAndroid Build Coastguard Worker 		case 'h':
271*d83cc019SAndroid Build Coastguard Worker 		default:
272*d83cc019SAndroid Build Coastguard Worker 			usage(argv[0]);
273*d83cc019SAndroid Build Coastguard Worker 		}
274*d83cc019SAndroid Build Coastguard Worker 	}
275*d83cc019SAndroid Build Coastguard Worker 
276*d83cc019SAndroid Build Coastguard Worker done:
277*d83cc019SAndroid Build Coastguard Worker 	return write;
278*d83cc019SAndroid Build Coastguard Worker }
279*d83cc019SAndroid Build Coastguard Worker 
main(int argc,char * argv[])280*d83cc019SAndroid Build Coastguard Worker int main(int argc, char *argv[])
281*d83cc019SAndroid Build Coastguard Worker {
282*d83cc019SAndroid Build Coastguard Worker 
283*d83cc019SAndroid Build Coastguard Worker 	bool write, fail, targets[MAX+1] = {false};
284*d83cc019SAndroid Build Coastguard Worker 	int i, fd, try = 1, set_freq[MAX+1] = {0};
285*d83cc019SAndroid Build Coastguard Worker 
286*d83cc019SAndroid Build Coastguard Worker 	fd = drm_open_driver(DRIVER_INTEL);
287*d83cc019SAndroid Build Coastguard Worker 	devid = intel_get_drm_devid(fd);
288*d83cc019SAndroid Build Coastguard Worker 	device = igt_device_get_card_index(fd);
289*d83cc019SAndroid Build Coastguard Worker 	close(fd);
290*d83cc019SAndroid Build Coastguard Worker 
291*d83cc019SAndroid Build Coastguard Worker 	write = parse(argc, argv, targets, ARRAY_SIZE(targets), set_freq);
292*d83cc019SAndroid Build Coastguard Worker 	fail = write;
293*d83cc019SAndroid Build Coastguard Worker 
294*d83cc019SAndroid Build Coastguard Worker 	/* If we've previously locked the frequency, we need to make sure to set things
295*d83cc019SAndroid Build Coastguard Worker 	 * in the correct order, or else the operation will fail (ie. min = max = 200,
296*d83cc019SAndroid Build Coastguard Worker 	 * and we set min to 300, we fail because it would try to set min >
297*d83cc019SAndroid Build Coastguard Worker 	 * max). This can be accomplished be going either forward or reverse
298*d83cc019SAndroid Build Coastguard Worker 	 * through the loop. MIN is always before MAX.
299*d83cc019SAndroid Build Coastguard Worker 	 *
300*d83cc019SAndroid Build Coastguard Worker 	 * XXX: Since only min and max are at play, the super lazy way is to do this
301*d83cc019SAndroid Build Coastguard Worker 	 * 3 times and if we still fail after 3, it's for real.
302*d83cc019SAndroid Build Coastguard Worker 	 */
303*d83cc019SAndroid Build Coastguard Worker again:
304*d83cc019SAndroid Build Coastguard Worker 	if (try > 2) {
305*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Did not achieve desired freq.\n");
306*d83cc019SAndroid Build Coastguard Worker 		exit(EXIT_FAILURE);
307*d83cc019SAndroid Build Coastguard Worker 	}
308*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(targets); i++) {
309*d83cc019SAndroid Build Coastguard Worker 		if (targets[i] == false)
310*d83cc019SAndroid Build Coastguard Worker 			continue;
311*d83cc019SAndroid Build Coastguard Worker 
312*d83cc019SAndroid Build Coastguard Worker 		if (write) {
313*d83cc019SAndroid Build Coastguard Worker 			set_frequency(&info[i], set_freq[i]);
314*d83cc019SAndroid Build Coastguard Worker 			if (get_frequency(&info[i]) != set_freq[i])
315*d83cc019SAndroid Build Coastguard Worker 				fail = true;
316*d83cc019SAndroid Build Coastguard Worker 			else
317*d83cc019SAndroid Build Coastguard Worker 				fail = false;
318*d83cc019SAndroid Build Coastguard Worker 		} else {
319*d83cc019SAndroid Build Coastguard Worker 			printf("%s: %d MHz\n", info[i].name, get_frequency(&info[i]));
320*d83cc019SAndroid Build Coastguard Worker 		}
321*d83cc019SAndroid Build Coastguard Worker 	}
322*d83cc019SAndroid Build Coastguard Worker 
323*d83cc019SAndroid Build Coastguard Worker 	if (fail) {
324*d83cc019SAndroid Build Coastguard Worker 		try++;
325*d83cc019SAndroid Build Coastguard Worker 		goto again;
326*d83cc019SAndroid Build Coastguard Worker 	}
327*d83cc019SAndroid Build Coastguard Worker 
328*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(targets); i++) {
329*d83cc019SAndroid Build Coastguard Worker 		if (info[i].filp) {
330*d83cc019SAndroid Build Coastguard Worker 			fclose(info[i].filp);
331*d83cc019SAndroid Build Coastguard Worker 			free(info[i].path);
332*d83cc019SAndroid Build Coastguard Worker 		}
333*d83cc019SAndroid Build Coastguard Worker 	}
334*d83cc019SAndroid Build Coastguard Worker 
335*d83cc019SAndroid Build Coastguard Worker 	return EXIT_SUCCESS;
336*d83cc019SAndroid Build Coastguard Worker }
337