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;
}
|