File: intel_fbc.c

package info (click to toggle)
intel-gpu-tools 2.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 63,360 kB
  • sloc: xml: 781,458; ansic: 360,567; python: 8,336; yacc: 2,781; perl: 1,196; sh: 1,177; lex: 487; asm: 227; lisp: 35; makefile: 30
file content (229 lines) | stat: -rw-r--r-- 5,390 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/* SPDX-License-Identifier: MIT */
/*
 * Copyright © 2023 Intel Corporation
 */

#include <fcntl.h>

#include "igt.h"
#include "igt_psr.h"

#include "intel_fbc.h"
#include "intel_wa.h"

#define FBC_STATUS_BUF_LEN 128

/**
 * intel_fbc_supported_on_chipset:
 * @device: fd of the device
 * @pipe: Display pipe
 *
 * Check if FBC is supported by chipset on given pipe.
 *
 * Returns:
 * true if FBC is supported and false otherwise.
 */
bool intel_fbc_supported_on_chipset(int device, enum pipe pipe)
{
	char buf[FBC_STATUS_BUF_LEN];
	int dir;

	dir = igt_debugfs_pipe_dir(device, pipe, O_DIRECTORY);
	igt_require_fd(dir);
	igt_debugfs_simple_read(dir, "i915_fbc_status", buf, sizeof(buf));
	close(dir);
	if (*buf == '\0')
		return false;

	return !strstr(buf, "FBC unsupported on this chipset\n") &&
		!strstr(buf, "stolen memory not initialised\n");
}

static bool _intel_fbc_is_enabled(int device, enum pipe pipe, int log_level, char *last_fbc_buf)
{
	char buf[FBC_STATUS_BUF_LEN];
	bool print = true;
	int dir;

	dir = igt_debugfs_pipe_dir(device, pipe, O_DIRECTORY);
	igt_require_fd(dir);
	igt_debugfs_simple_read(dir, "i915_fbc_status", buf, sizeof(buf));
	close(dir);
	if (log_level != IGT_LOG_DEBUG)
		last_fbc_buf[0] = '\0';
	else if (strcmp(last_fbc_buf, buf))
		strcpy(last_fbc_buf, buf);
	else
		print = false;

	if (print)
		igt_log(IGT_LOG_DOMAIN, log_level, "fbc_is_enabled():\n%s\n", buf);

	return strstr(buf, "FBC enabled\n");
}

/**
 * intel_fbc_is_enabled:
 * @device: fd of the device
 * @pipe: Display pipe
 * @log_level: Wanted loglevel
 *
 * Check if FBC is enabled on given pipe. Loglevel can be used to
 * control at which loglevel current state is printed out.
 *
 * Returns:
 * true if FBC is enabled.
 */
bool intel_fbc_is_enabled(int device, enum pipe pipe, int log_level)
{
	char last_fbc_buf[FBC_STATUS_BUF_LEN] = {'\0'};

	return _intel_fbc_is_enabled(device, pipe, log_level, last_fbc_buf);
}

/**
 * intel_fbc_wait_until_enabled:
 * @device: fd of the device
 * @pipe: Display pipe
 *
 * Wait until fbc is enabled. Used timeout is constant 2 seconds.
 *
 * Returns:
 * true if FBC got enabled.
 */
bool intel_fbc_wait_until_enabled(int device, enum pipe pipe)
{
	char last_fbc_buf[FBC_STATUS_BUF_LEN] = {'\0'};
	bool enabled = igt_wait(_intel_fbc_is_enabled(device, pipe, IGT_LOG_DEBUG, last_fbc_buf), 2000, 1);

	if (!enabled)
		igt_info("FBC is not enabled: \n%s\n", last_fbc_buf);

	return enabled;
}

/**
 * intel_fbc_max_plane_size
 *
 * @fd: fd of the device
 * @width: To get the max supported width
 * @height: To get the max supported height
 *
 * Function to update maximum plane size supported by FBC per platform
 *
 * Returns:
 * None
 */
void intel_fbc_max_plane_size(int fd, uint32_t *width, uint32_t *height)
{
	const uint32_t dev_id = intel_get_drm_devid(fd);
	const struct intel_device_info *info = intel_get_device_info(dev_id);
	int ver = info->graphics_ver;

	if (ver >= 10) {
		*width = 5120;
		*height = 4096;
	} else if (ver >= 8 || IS_HASWELL(fd)) {
		*width = 4096;
		*height = 4096;
	} else if (IS_G4X(fd) || ver >= 5) {
		*width = 4096;
		*height = 2048;
	} else {
		*width = 2048;
		*height = 1536;
	}
}


/**
 * intel_fbc_plane_size_supported
 *
 * @fd: fd of the device
 * @width: width of the plane to be checked
 * @height: height of the plane to be checked
 *
 * Checks if the plane size is supported for FBC
 *
 * Returns:
 * true if plane size is within the range as per the FBC supported size restrictions per platform
 */
bool intel_fbc_plane_size_supported(int fd, uint32_t width, uint32_t height)
{
	unsigned int max_w, max_h;

	intel_fbc_max_plane_size(fd, &max_w, &max_h);

	return width <= max_w && height <= max_h;
}

/**
 * intel_fbc_supported_for_psr_mode
 *
 * @disp_ver: Display version
 * @mode: psr mode
 *
 * FBC and PSR1/PSR2/PR combination support depends on the display version.
 *
 * Returns:
 * true if FBC and the given PSR mode can be enabled together in a platform
 */
bool intel_fbc_supported_for_psr_mode(int disp_ver, enum psr_mode mode)
{
	bool fbc_supported = true;

	switch(mode) {
	case PSR_MODE_1:
		/* TODO: Update this to exclude MTL C0 onwards from this list */
		if (disp_ver >= 12 && disp_ver <= 14)
			fbc_supported = false;
		break;
	case PSR_MODE_2:
	case PSR_MODE_2_SEL_FETCH:
	case PSR_MODE_2_ET:
	case PR_MODE_SEL_FETCH:
	case PR_MODE_SEL_FETCH_ET:
		/*
		 * FBC is not supported if PSR2 is enabled in display version 12 to 14.
		 * According to the xe2lpd+ requirements, display driver need to
		 * implement a selection logic between FBC and PSR2/Panel Replay selective
		 * update based on dirty region threshold. Until that is implemented,
		 * keep FBC disabled if PSR2/PR selective update is on.
		 *
		 * TODO: Update this based on the selection logic in the driver
		 */
		fbc_supported = false;
		break;
	case PR_MODE:
	default:
		break;
	}

	return fbc_supported;
}

/**
 * intel_is_fbc_disabled_by_wa
 *
 * @fd: fd of the device
 *
 * This function check if WA is present on some GT, which in turn make
 * FBC not possible
 *
 * Returns:
 * true: if WA is applied and FBC id disabled
 * false: otherwise
 */
bool intel_is_fbc_disabled_by_wa(int fd)
{
	int wa;
	const char *wa_fbc_disabled = "16023588340";

	if (!is_xe_device(fd))
		return false;

	wa = igt_has_intel_wa(fd, wa_fbc_disabled);
	igt_assert_f(wa >= 0, "WA path not found on GTs\n");

	return wa == 1;
}