Bug Summary

File:dev/pci/drm/i915/display/intel_dmc.c
Warning:line 588, column 27
Value stored to 'i915' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name intel_dmc.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/pci/drm/i915/display/intel_dmc.c
1/*
2 * Copyright © 2014 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 */
24
25#include <linux/firmware.h>
26
27#include "i915_drv.h"
28#include "i915_reg.h"
29#include "intel_de.h"
30#include "intel_dmc.h"
31#include "intel_dmc_regs.h"
32
33/**
34 * DOC: DMC Firmware Support
35 *
36 * From gen9 onwards we have newly added DMC (Display microcontroller) in display
37 * engine to save and restore the state of display engine when it enter into
38 * low-power state and comes back to normal.
39 */
40
41#define DMC_VERSION(major, minor)((major) << 16 | (minor)) ((major) << 16 | (minor))
42#define DMC_VERSION_MAJOR(version)((version) >> 16) ((version) >> 16)
43#define DMC_VERSION_MINOR(version)((version) & 0xffff) ((version) & 0xffff)
44
45#define DMC_PATH(platform, major, minor)"i915/" "platform" "_dmc_ver" "major" "_" "minor" ".bin" \
46 "i915/" \
47 __stringify(platform)"platform" "_dmc_ver" \
48 __stringify(major)"major" "_" \
49 __stringify(minor)"minor" ".bin"
50
51#define DISPLAY_VER13_DMC_MAX_FW_SIZE0x20000 0x20000
52
53#define DISPLAY_VER12_DMC_MAX_FW_SIZE0x6000 ICL_DMC_MAX_FW_SIZE0x6000
54
55#define DG2_DMC_PATH"i915/" "dg2" "_dmc_ver" "2" "_" "07" ".bin" DMC_PATH(dg2, 2, 07)"i915/" "dg2" "_dmc_ver" "2" "_" "07" ".bin"
56#define DG2_DMC_VERSION_REQUIRED((2) << 16 | (07)) DMC_VERSION(2, 07)((2) << 16 | (07))
57MODULE_FIRMWARE(DG2_DMC_PATH);
58
59#define ADLP_DMC_PATH"i915/" "adlp" "_dmc_ver" "2" "_" "16" ".bin" DMC_PATH(adlp, 2, 16)"i915/" "adlp" "_dmc_ver" "2" "_" "16" ".bin"
60#define ADLP_DMC_VERSION_REQUIRED((2) << 16 | (16)) DMC_VERSION(2, 16)((2) << 16 | (16))
61MODULE_FIRMWARE(ADLP_DMC_PATH);
62
63#define ADLS_DMC_PATH"i915/" "adls" "_dmc_ver" "2" "_" "01" ".bin" DMC_PATH(adls, 2, 01)"i915/" "adls" "_dmc_ver" "2" "_" "01" ".bin"
64#define ADLS_DMC_VERSION_REQUIRED((2) << 16 | (1)) DMC_VERSION(2, 1)((2) << 16 | (1))
65MODULE_FIRMWARE(ADLS_DMC_PATH);
66
67#define DG1_DMC_PATH"i915/" "dg1" "_dmc_ver" "2" "_" "02" ".bin" DMC_PATH(dg1, 2, 02)"i915/" "dg1" "_dmc_ver" "2" "_" "02" ".bin"
68#define DG1_DMC_VERSION_REQUIRED((2) << 16 | (2)) DMC_VERSION(2, 2)((2) << 16 | (2))
69MODULE_FIRMWARE(DG1_DMC_PATH);
70
71#define RKL_DMC_PATH"i915/" "rkl" "_dmc_ver" "2" "_" "03" ".bin" DMC_PATH(rkl, 2, 03)"i915/" "rkl" "_dmc_ver" "2" "_" "03" ".bin"
72#define RKL_DMC_VERSION_REQUIRED((2) << 16 | (3)) DMC_VERSION(2, 3)((2) << 16 | (3))
73MODULE_FIRMWARE(RKL_DMC_PATH);
74
75#define TGL_DMC_PATH"i915/" "tgl" "_dmc_ver" "2" "_" "12" ".bin" DMC_PATH(tgl, 2, 12)"i915/" "tgl" "_dmc_ver" "2" "_" "12" ".bin"
76#define TGL_DMC_VERSION_REQUIRED((2) << 16 | (12)) DMC_VERSION(2, 12)((2) << 16 | (12))
77MODULE_FIRMWARE(TGL_DMC_PATH);
78
79#define ICL_DMC_PATH"i915/" "icl" "_dmc_ver" "1" "_" "09" ".bin" DMC_PATH(icl, 1, 09)"i915/" "icl" "_dmc_ver" "1" "_" "09" ".bin"
80#define ICL_DMC_VERSION_REQUIRED((1) << 16 | (9)) DMC_VERSION(1, 9)((1) << 16 | (9))
81#define ICL_DMC_MAX_FW_SIZE0x6000 0x6000
82MODULE_FIRMWARE(ICL_DMC_PATH);
83
84#define GLK_DMC_PATH"i915/" "glk" "_dmc_ver" "1" "_" "04" ".bin" DMC_PATH(glk, 1, 04)"i915/" "glk" "_dmc_ver" "1" "_" "04" ".bin"
85#define GLK_DMC_VERSION_REQUIRED((1) << 16 | (4)) DMC_VERSION(1, 4)((1) << 16 | (4))
86#define GLK_DMC_MAX_FW_SIZE0x4000 0x4000
87MODULE_FIRMWARE(GLK_DMC_PATH);
88
89#define KBL_DMC_PATH"i915/" "kbl" "_dmc_ver" "1" "_" "04" ".bin" DMC_PATH(kbl, 1, 04)"i915/" "kbl" "_dmc_ver" "1" "_" "04" ".bin"
90#define KBL_DMC_VERSION_REQUIRED((1) << 16 | (4)) DMC_VERSION(1, 4)((1) << 16 | (4))
91#define KBL_DMC_MAX_FW_SIZE0x3000 BXT_DMC_MAX_FW_SIZE0x3000
92MODULE_FIRMWARE(KBL_DMC_PATH);
93
94#define SKL_DMC_PATH"i915/" "skl" "_dmc_ver" "1" "_" "27" ".bin" DMC_PATH(skl, 1, 27)"i915/" "skl" "_dmc_ver" "1" "_" "27" ".bin"
95#define SKL_DMC_VERSION_REQUIRED((1) << 16 | (27)) DMC_VERSION(1, 27)((1) << 16 | (27))
96#define SKL_DMC_MAX_FW_SIZE0x3000 BXT_DMC_MAX_FW_SIZE0x3000
97MODULE_FIRMWARE(SKL_DMC_PATH);
98
99#define BXT_DMC_PATH"i915/" "bxt" "_dmc_ver" "1" "_" "07" ".bin" DMC_PATH(bxt, 1, 07)"i915/" "bxt" "_dmc_ver" "1" "_" "07" ".bin"
100#define BXT_DMC_VERSION_REQUIRED((1) << 16 | (7)) DMC_VERSION(1, 7)((1) << 16 | (7))
101#define BXT_DMC_MAX_FW_SIZE0x3000 0x3000
102MODULE_FIRMWARE(BXT_DMC_PATH);
103
104#define DMC_DEFAULT_FW_OFFSET0xFFFFFFFF 0xFFFFFFFF
105#define PACKAGE_MAX_FW_INFO_ENTRIES20 20
106#define PACKAGE_V2_MAX_FW_INFO_ENTRIES32 32
107#define DMC_V1_MAX_MMIO_COUNT8 8
108#define DMC_V3_MAX_MMIO_COUNT20 20
109#define DMC_V1_MMIO_START_RANGE0x80000 0x80000
110
111struct intel_css_header {
112 /* 0x09 for DMC */
113 u32 module_type;
114
115 /* Includes the DMC specific header in dwords */
116 u32 header_len;
117
118 /* always value would be 0x10000 */
119 u32 header_ver;
120
121 /* Not used */
122 u32 module_id;
123
124 /* Not used */
125 u32 module_vendor;
126
127 /* in YYYYMMDD format */
128 u32 date;
129
130 /* Size in dwords (CSS_Headerlen + PackageHeaderLen + dmc FWsLen)/4 */
131 u32 size;
132
133 /* Not used */
134 u32 key_size;
135
136 /* Not used */
137 u32 modulus_size;
138
139 /* Not used */
140 u32 exponent_size;
141
142 /* Not used */
143 u32 reserved1[12];
144
145 /* Major Minor */
146 u32 version;
147
148 /* Not used */
149 u32 reserved2[8];
150
151 /* Not used */
152 u32 kernel_header_info;
153} __packed__attribute__((__packed__));
154
155struct intel_fw_info {
156 u8 reserved1;
157
158 /* reserved on package_header version 1, must be 0 on version 2 */
159 u8 dmc_id;
160
161 /* Stepping (A, B, C, ..., *). * is a wildcard */
162 char stepping;
163
164 /* Sub-stepping (0, 1, ..., *). * is a wildcard */
165 char substepping;
166
167 u32 offset;
168 u32 reserved2;
169} __packed__attribute__((__packed__));
170
171struct intel_package_header {
172 /* DMC container header length in dwords */
173 u8 header_len;
174
175 /* 0x01, 0x02 */
176 u8 header_ver;
177
178 u8 reserved[10];
179
180 /* Number of valid entries in the FWInfo array below */
181 u32 num_entries;
182} __packed__attribute__((__packed__));
183
184struct intel_dmc_header_base {
185 /* always value would be 0x40403E3E */
186 u32 signature;
187
188 /* DMC binary header length */
189 u8 header_len;
190
191 /* 0x01 */
192 u8 header_ver;
193
194 /* Reserved */
195 u16 dmcc_ver;
196
197 /* Major, Minor */
198 u32 project;
199
200 /* Firmware program size (excluding header) in dwords */
201 u32 fw_size;
202
203 /* Major Minor version */
204 u32 fw_version;
205} __packed__attribute__((__packed__));
206
207struct intel_dmc_header_v1 {
208 struct intel_dmc_header_base base;
209
210 /* Number of valid MMIO cycles present. */
211 u32 mmio_count;
212
213 /* MMIO address */
214 u32 mmioaddr[DMC_V1_MAX_MMIO_COUNT8];
215
216 /* MMIO data */
217 u32 mmiodata[DMC_V1_MAX_MMIO_COUNT8];
218
219 /* FW filename */
220 char dfile[32];
221
222 u32 reserved1[2];
223} __packed__attribute__((__packed__));
224
225struct intel_dmc_header_v3 {
226 struct intel_dmc_header_base base;
227
228 /* DMC RAM start MMIO address */
229 u32 start_mmioaddr;
230
231 u32 reserved[9];
232
233 /* FW filename */
234 char dfile[32];
235
236 /* Number of valid MMIO cycles present. */
237 u32 mmio_count;
238
239 /* MMIO address */
240 u32 mmioaddr[DMC_V3_MAX_MMIO_COUNT20];
241
242 /* MMIO data */
243 u32 mmiodata[DMC_V3_MAX_MMIO_COUNT20];
244} __packed__attribute__((__packed__));
245
246struct stepping_info {
247 char stepping;
248 char substepping;
249};
250
251static bool_Bool has_dmc_id_fw(struct drm_i915_privateinteldrm_softc *i915, int dmc_id)
252{
253 return i915->display.dmc.dmc_info[dmc_id].payload;
254}
255
256bool_Bool intel_dmc_has_payload(struct drm_i915_privateinteldrm_softc *i915)
257{
258 return has_dmc_id_fw(i915, DMC_FW_MAIN);
259}
260
261static const struct stepping_info *
262intel_get_stepping_info(struct drm_i915_privateinteldrm_softc *i915,
263 struct stepping_info *si)
264{
265 const char *step_name = intel_step_name(RUNTIME_INFO(i915)(&(i915)->__runtime)->step.display_step);
266
267 si->stepping = step_name[0];
268 si->substepping = step_name[1];
269 return si;
270}
271
272static void gen9_set_dc_state_debugmask(struct drm_i915_privateinteldrm_softc *dev_priv)
273{
274 /* The below bit doesn't need to be cleared ever afterwards */
275 intel_de_rmw(dev_priv, DC_STATE_DEBUG((const i915_reg_t){ .reg = (0x45520) }), 0,
276 DC_STATE_DEBUG_MASK_CORES(1 << 0) | DC_STATE_DEBUG_MASK_MEMORY_UP(1 << 1));
277 intel_de_posting_read(dev_priv, DC_STATE_DEBUG((const i915_reg_t){ .reg = (0x45520) }));
278}
279
280static void disable_event_handler(struct drm_i915_privateinteldrm_softc *i915,
281 i915_reg_t ctl_reg, i915_reg_t htp_reg)
282{
283 intel_de_write(i915, ctl_reg,
284 REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK,((u32)((((typeof(((u32)((((~0UL) >> (64 - (17) - 1)) &
((~0UL) << (16))) + 0))))(3) << (__builtin_ffsll
(((u32)((((~0UL) >> (64 - (17) - 1)) & ((~0UL) <<
(16))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (17
) - 1)) & ((~0UL) << (16))) + 0)))) + 0 + 0 + 0 + 0
))
285 DMC_EVT_CTL_TYPE_EDGE_0_1)((u32)((((typeof(((u32)((((~0UL) >> (64 - (17) - 1)) &
((~0UL) << (16))) + 0))))(3) << (__builtin_ffsll
(((u32)((((~0UL) >> (64 - (17) - 1)) & ((~0UL) <<
(16))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (17
) - 1)) & ((~0UL) << (16))) + 0)))) + 0 + 0 + 0 + 0
))
|
286 REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK,((u32)((((typeof(((u32)((((~0UL) >> (64 - (15) - 1)) &
((~0UL) << (8))) + 0))))(0x01) << (__builtin_ffsll
(((u32)((((~0UL) >> (64 - (15) - 1)) & ((~0UL) <<
(8))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (15
) - 1)) & ((~0UL) << (8))) + 0)))) + 0 + 0 + 0 + 0)
)
287 DMC_EVT_CTL_EVENT_ID_FALSE)((u32)((((typeof(((u32)((((~0UL) >> (64 - (15) - 1)) &
((~0UL) << (8))) + 0))))(0x01) << (__builtin_ffsll
(((u32)((((~0UL) >> (64 - (15) - 1)) & ((~0UL) <<
(8))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (15
) - 1)) & ((~0UL) << (8))) + 0)))) + 0 + 0 + 0 + 0)
)
);
288 intel_de_write(i915, htp_reg, 0);
289}
290
291static void
292disable_flip_queue_event(struct drm_i915_privateinteldrm_softc *i915,
293 i915_reg_t ctl_reg, i915_reg_t htp_reg)
294{
295 u32 event_ctl;
296 u32 event_htp;
297
298 event_ctl = intel_de_read(i915, ctl_reg);
299 event_htp = intel_de_read(i915, htp_reg);
300 if (event_ctl != (DMC_EVT_CTL_ENABLE((u32)((1UL << (31)) + 0)) |
301 DMC_EVT_CTL_RECURRING((u32)((1UL << (30)) + 0)) |
302 REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK,((u32)((((typeof(((u32)((((~0UL) >> (64 - (17) - 1)) &
((~0UL) << (16))) + 0))))(3) << (__builtin_ffsll
(((u32)((((~0UL) >> (64 - (17) - 1)) & ((~0UL) <<
(16))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (17
) - 1)) & ((~0UL) << (16))) + 0)))) + 0 + 0 + 0 + 0
))
303 DMC_EVT_CTL_TYPE_EDGE_0_1)((u32)((((typeof(((u32)((((~0UL) >> (64 - (17) - 1)) &
((~0UL) << (16))) + 0))))(3) << (__builtin_ffsll
(((u32)((((~0UL) >> (64 - (17) - 1)) & ((~0UL) <<
(16))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (17
) - 1)) & ((~0UL) << (16))) + 0)))) + 0 + 0 + 0 + 0
))
|
304 REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK,((u32)((((typeof(((u32)((((~0UL) >> (64 - (15) - 1)) &
((~0UL) << (8))) + 0))))(0xbf) << (__builtin_ffsll
(((u32)((((~0UL) >> (64 - (15) - 1)) & ((~0UL) <<
(8))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (15
) - 1)) & ((~0UL) << (8))) + 0)))) + 0 + 0 + 0 + 0)
)
305 DMC_EVT_CTL_EVENT_ID_CLK_MSEC)((u32)((((typeof(((u32)((((~0UL) >> (64 - (15) - 1)) &
((~0UL) << (8))) + 0))))(0xbf) << (__builtin_ffsll
(((u32)((((~0UL) >> (64 - (15) - 1)) & ((~0UL) <<
(8))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (15
) - 1)) & ((~0UL) << (8))) + 0)))) + 0 + 0 + 0 + 0)
)
) ||
306 !event_htp) {
307 drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "Unexpected DMC event configuration (control %08x htp %08x)\n"
, event_ctl, event_htp)
308 "Unexpected DMC event configuration (control %08x htp %08x)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "Unexpected DMC event configuration (control %08x htp %08x)\n"
, event_ctl, event_htp)
309 event_ctl, event_htp)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "Unexpected DMC event configuration (control %08x htp %08x)\n"
, event_ctl, event_htp)
;
310 return;
311 }
312
313 disable_event_handler(i915, ctl_reg, htp_reg);
314}
315
316static bool_Bool
317get_flip_queue_event_regs(struct drm_i915_privateinteldrm_softc *i915, int dmc_id,
318 i915_reg_t *ctl_reg, i915_reg_t *htp_reg)
319{
320 switch (dmc_id) {
321 case DMC_FW_MAIN:
322 if (DISPLAY_VER(i915)((&(i915)->__runtime)->display.ip.ver) == 12) {
323 *ctl_reg = DMC_EVT_CTL(i915, dmc_id, 3)((const i915_reg_t){ .reg = (((0x8f034) - 0x8f000 + ((dmc_id)
== DMC_FW_MAIN ? 0x8f000 : ((((&(i915)->__runtime)->
display.ip.ver) >= 13 ? 0x5f000 : 0x92000) + 0x400 * ((dmc_id
) - 1)))) + 4 * (3)) })
;
324 *htp_reg = DMC_EVT_HTP(i915, dmc_id, 3)((const i915_reg_t){ .reg = (((0x8f004) - 0x8f000 + ((dmc_id)
== DMC_FW_MAIN ? 0x8f000 : ((((&(i915)->__runtime)->
display.ip.ver) >= 13 ? 0x5f000 : 0x92000) + 0x400 * ((dmc_id
) - 1)))) + 4 * (3)) })
;
325
326 return true1;
327 }
328 break;
329 case DMC_FW_PIPEA ... DMC_FW_PIPED:
330 if (IS_DG2(i915)IS_PLATFORM(i915, INTEL_DG2)) {
331 *ctl_reg = DMC_EVT_CTL(i915, dmc_id, 2)((const i915_reg_t){ .reg = (((0x8f034) - 0x8f000 + ((dmc_id)
== DMC_FW_MAIN ? 0x8f000 : ((((&(i915)->__runtime)->
display.ip.ver) >= 13 ? 0x5f000 : 0x92000) + 0x400 * ((dmc_id
) - 1)))) + 4 * (2)) })
;
332 *htp_reg = DMC_EVT_HTP(i915, dmc_id, 2)((const i915_reg_t){ .reg = (((0x8f004) - 0x8f000 + ((dmc_id)
== DMC_FW_MAIN ? 0x8f000 : ((((&(i915)->__runtime)->
display.ip.ver) >= 13 ? 0x5f000 : 0x92000) + 0x400 * ((dmc_id
) - 1)))) + 4 * (2)) })
;
333
334 return true1;
335 }
336 break;
337 }
338
339 return false0;
340}
341
342static void
343disable_all_flip_queue_events(struct drm_i915_privateinteldrm_softc *i915)
344{
345 int dmc_id;
346
347 /* TODO: check if the following applies to all D13+ platforms. */
348 if (!IS_DG2(i915)IS_PLATFORM(i915, INTEL_DG2) && !IS_TIGERLAKE(i915)IS_PLATFORM(i915, INTEL_TIGERLAKE))
349 return;
350
351 for (dmc_id = 0; dmc_id < DMC_FW_MAX; dmc_id++) {
352 i915_reg_t ctl_reg;
353 i915_reg_t htp_reg;
354
355 if (!has_dmc_id_fw(i915, dmc_id))
356 continue;
357
358 if (!get_flip_queue_event_regs(i915, dmc_id, &ctl_reg, &htp_reg))
359 continue;
360
361 disable_flip_queue_event(i915, ctl_reg, htp_reg);
362 }
363}
364
365static void disable_all_event_handlers(struct drm_i915_privateinteldrm_softc *i915)
366{
367 int id;
368
369 /* TODO: disable the event handlers on pre-GEN12 platforms as well */
370 if (DISPLAY_VER(i915)((&(i915)->__runtime)->display.ip.ver) < 12)
371 return;
372
373 for (id = DMC_FW_MAIN; id < DMC_FW_MAX; id++) {
374 int handler;
375
376 if (!has_dmc_id_fw(i915, id))
377 continue;
378
379 for (handler = 0; handler < DMC_EVENT_HANDLER_COUNT_GEN128; handler++)
380 disable_event_handler(i915,
381 DMC_EVT_CTL(i915, id, handler)((const i915_reg_t){ .reg = (((0x8f034) - 0x8f000 + ((id) == DMC_FW_MAIN
? 0x8f000 : ((((&(i915)->__runtime)->display.ip.ver
) >= 13 ? 0x5f000 : 0x92000) + 0x400 * ((id) - 1)))) + 4 *
(handler)) })
,
382 DMC_EVT_HTP(i915, id, handler)((const i915_reg_t){ .reg = (((0x8f004) - 0x8f000 + ((id) == DMC_FW_MAIN
? 0x8f000 : ((((&(i915)->__runtime)->display.ip.ver
) >= 13 ? 0x5f000 : 0x92000) + 0x400 * ((id) - 1)))) + 4 *
(handler)) })
);
383 }
384}
385
386static void pipedmc_clock_gating_wa(struct drm_i915_privateinteldrm_softc *i915, bool_Bool enable)
387{
388 enum pipe pipe;
389
390 if (DISPLAY_VER(i915)((&(i915)->__runtime)->display.ip.ver) != 13)
391 return;
392
393 /*
394 * Wa_16015201720:adl-p,dg2
395 * The WA requires clock gating to be disabled all the time
396 * for pipe A and B.
397 * For pipe C and D clock gating needs to be disabled only
398 * during initializing the firmware.
399 */
400 if (enable)
401 for (pipe = PIPE_A; pipe <= PIPE_D; pipe++)
402 intel_de_rmw(i915, CLKGATE_DIS_PSL_EXT(pipe)((const i915_reg_t){ .reg = (((0x4654C) + (pipe) * ((0x46550)
- (0x4654C)))) })
,
403 0, PIPEDMC_GATING_DIS((u32)((1UL << (12)) + 0)));
404 else
405 for (pipe = PIPE_C; pipe <= PIPE_D; pipe++)
406 intel_de_rmw(i915, CLKGATE_DIS_PSL_EXT(pipe)((const i915_reg_t){ .reg = (((0x4654C) + (pipe) * ((0x46550)
- (0x4654C)))) })
,
407 PIPEDMC_GATING_DIS((u32)((1UL << (12)) + 0)), 0);
408}
409
410/**
411 * intel_dmc_load_program() - write the firmware from memory to register.
412 * @dev_priv: i915 drm device.
413 *
414 * DMC firmware is read from a .bin file and kept in internal memory one time.
415 * Everytime display comes back from low power state this function is called to
416 * copy the firmware from internal memory to registers.
417 */
418void intel_dmc_load_program(struct drm_i915_privateinteldrm_softc *dev_priv)
419{
420 struct intel_dmc *dmc = &dev_priv->display.dmc;
421 u32 id, i;
422
423 if (!intel_dmc_has_payload(dev_priv))
424 return;
425
426 pipedmc_clock_gating_wa(dev_priv, true1);
427
428 disable_all_event_handlers(dev_priv);
429
430 assert_rpm_wakelock_held(&dev_priv->runtime_pm);
431
432 preempt_disable();
433
434 for (id = 0; id < DMC_FW_MAX; id++) {
435 for (i = 0; i < dmc->dmc_info[id].dmc_fw_size; i++) {
436 intel_uncore_write_fw(&dev_priv->uncore,__raw_uncore_write32(&dev_priv->uncore, ((const i915_reg_t
){ .reg = ((dmc->dmc_info[id].start_mmioaddr) + (i) * 4) }
), dmc->dmc_info[id].payload[i])
437 DMC_PROGRAM(dmc->dmc_info[id].start_mmioaddr, i),__raw_uncore_write32(&dev_priv->uncore, ((const i915_reg_t
){ .reg = ((dmc->dmc_info[id].start_mmioaddr) + (i) * 4) }
), dmc->dmc_info[id].payload[i])
438 dmc->dmc_info[id].payload[i])__raw_uncore_write32(&dev_priv->uncore, ((const i915_reg_t
){ .reg = ((dmc->dmc_info[id].start_mmioaddr) + (i) * 4) }
), dmc->dmc_info[id].payload[i])
;
439 }
440 }
441
442 preempt_enable();
443
444 for (id = 0; id < DMC_FW_MAX; id++) {
445 for (i = 0; i < dmc->dmc_info[id].mmio_count; i++) {
446 intel_de_write(dev_priv, dmc->dmc_info[id].mmioaddr[i],
447 dmc->dmc_info[id].mmiodata[i]);
448 }
449 }
450
451 dev_priv->display.dmc.dc_state = 0;
452
453 gen9_set_dc_state_debugmask(dev_priv);
454
455 /*
456 * Flip queue events need to be disabled before enabling DC5/6.
457 * i915 doesn't use the flip queue feature, so disable it already
458 * here.
459 */
460 disable_all_flip_queue_events(dev_priv);
461
462 pipedmc_clock_gating_wa(dev_priv, false0);
463}
464
465/**
466 * intel_dmc_disable_program() - disable the firmware
467 * @i915: i915 drm device
468 *
469 * Disable all event handlers in the firmware, making sure the firmware is
470 * inactive after the display is uninitialized.
471 */
472void intel_dmc_disable_program(struct drm_i915_privateinteldrm_softc *i915)
473{
474 if (!intel_dmc_has_payload(i915))
475 return;
476
477 pipedmc_clock_gating_wa(i915, true1);
478 disable_all_event_handlers(i915);
479 pipedmc_clock_gating_wa(i915, false0);
480}
481
482void assert_dmc_loaded(struct drm_i915_privateinteldrm_softc *i915)
483{
484 drm_WARN_ONCE(&i915->drm,({ static int __warned; int __ret = !!(!intel_de_read(i915, (
(const i915_reg_t){ .reg = ((i915->display.dmc.dmc_info[DMC_FW_MAIN
].start_mmioaddr) + (0) * 4) }))); if (__ret && !__warned
) { printf("%s %s: " "DMC program storage start is NULL\n", dev_driver_string
((&i915->drm)->dev), ""); __warned = 1; } __builtin_expect
(!!(__ret), 0); })
485 !intel_de_read(i915, DMC_PROGRAM(i915->display.dmc.dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)),({ static int __warned; int __ret = !!(!intel_de_read(i915, (
(const i915_reg_t){ .reg = ((i915->display.dmc.dmc_info[DMC_FW_MAIN
].start_mmioaddr) + (0) * 4) }))); if (__ret && !__warned
) { printf("%s %s: " "DMC program storage start is NULL\n", dev_driver_string
((&i915->drm)->dev), ""); __warned = 1; } __builtin_expect
(!!(__ret), 0); })
486 "DMC program storage start is NULL\n")({ static int __warned; int __ret = !!(!intel_de_read(i915, (
(const i915_reg_t){ .reg = ((i915->display.dmc.dmc_info[DMC_FW_MAIN
].start_mmioaddr) + (0) * 4) }))); if (__ret && !__warned
) { printf("%s %s: " "DMC program storage start is NULL\n", dev_driver_string
((&i915->drm)->dev), ""); __warned = 1; } __builtin_expect
(!!(__ret), 0); })
;
487 drm_WARN_ONCE(&i915->drm, !intel_de_read(i915, DMC_SSP_BASE),({ static int __warned; int __ret = !!(!intel_de_read(i915, (
(const i915_reg_t){ .reg = (0x8F074) }))); if (__ret &&
!__warned) { printf("%s %s: " "DMC SSP Base Not fine\n", dev_driver_string
((&i915->drm)->dev), ""); __warned = 1; } __builtin_expect
(!!(__ret), 0); })
488 "DMC SSP Base Not fine\n")({ static int __warned; int __ret = !!(!intel_de_read(i915, (
(const i915_reg_t){ .reg = (0x8F074) }))); if (__ret &&
!__warned) { printf("%s %s: " "DMC SSP Base Not fine\n", dev_driver_string
((&i915->drm)->dev), ""); __warned = 1; } __builtin_expect
(!!(__ret), 0); })
;
489 drm_WARN_ONCE(&i915->drm, !intel_de_read(i915, DMC_HTP_SKL),({ static int __warned; int __ret = !!(!intel_de_read(i915, (
(const i915_reg_t){ .reg = (0x8F004) }))); if (__ret &&
!__warned) { printf("%s %s: " "DMC HTP Not fine\n", dev_driver_string
((&i915->drm)->dev), ""); __warned = 1; } __builtin_expect
(!!(__ret), 0); })
490 "DMC HTP Not fine\n")({ static int __warned; int __ret = !!(!intel_de_read(i915, (
(const i915_reg_t){ .reg = (0x8F004) }))); if (__ret &&
!__warned) { printf("%s %s: " "DMC HTP Not fine\n", dev_driver_string
((&i915->drm)->dev), ""); __warned = 1; } __builtin_expect
(!!(__ret), 0); })
;
491}
492
493static bool_Bool fw_info_matches_stepping(const struct intel_fw_info *fw_info,
494 const struct stepping_info *si)
495{
496 if ((fw_info->substepping == '*' && si->stepping == fw_info->stepping) ||
497 (si->stepping == fw_info->stepping && si->substepping == fw_info->substepping) ||
498 /*
499 * If we don't find a more specific one from above two checks, we
500 * then check for the generic one to be sure to work even with
501 * "broken firmware"
502 */
503 (si->stepping == '*' && si->substepping == fw_info->substepping) ||
504 (fw_info->stepping == '*' && fw_info->substepping == '*'))
505 return true1;
506
507 return false0;
508}
509
510/*
511 * Search fw_info table for dmc_offset to find firmware binary: num_entries is
512 * already sanitized.
513 */
514static void dmc_set_fw_offset(struct intel_dmc *dmc,
515 const struct intel_fw_info *fw_info,
516 unsigned int num_entries,
517 const struct stepping_info *si,
518 u8 package_ver)
519{
520 unsigned int i, id;
521
522 struct drm_i915_privateinteldrm_softc *i915 = container_of(dmc, typeof(*i915), display.dmc)({ const __typeof( ((typeof(*i915) *)0)->display.dmc ) *__mptr
= (dmc); (typeof(*i915) *)( (char *)__mptr - __builtin_offsetof
(typeof(*i915), display.dmc) );})
;
523
524 for (i = 0; i < num_entries; i++) {
525 id = package_ver <= 1 ? DMC_FW_MAIN : fw_info[i].dmc_id;
526
527 if (id >= DMC_FW_MAX) {
528 drm_dbg(&i915->drm, "Unsupported firmware id: %u\n", id)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_DRIVER, "Unsupported firmware id: %u\n"
, id)
;
529 continue;
530 }
531
532 /* More specific versions come first, so we don't even have to
533 * check for the stepping since we already found a previous FW
534 * for this id.
535 */
536 if (dmc->dmc_info[id].present)
537 continue;
538
539 if (fw_info_matches_stepping(&fw_info[i], si)) {
540 dmc->dmc_info[id].present = true1;
541 dmc->dmc_info[id].dmc_offset = fw_info[i].offset;
542 }
543 }
544}
545
546static bool_Bool dmc_mmio_addr_sanity_check(struct intel_dmc *dmc,
547 const u32 *mmioaddr, u32 mmio_count,
548 int header_ver, u8 dmc_id)
549{
550 struct drm_i915_privateinteldrm_softc *i915 = container_of(dmc, typeof(*i915), display.dmc)({ const __typeof( ((typeof(*i915) *)0)->display.dmc ) *__mptr
= (dmc); (typeof(*i915) *)( (char *)__mptr - __builtin_offsetof
(typeof(*i915), display.dmc) );})
;
551 u32 start_range, end_range;
552 int i;
553
554 if (dmc_id >= DMC_FW_MAX) {
555 drm_warn(&i915->drm, "Unsupported firmware id %u\n", dmc_id)printf("drm:pid%d:%s *WARNING* " "[drm] " "Unsupported firmware id %u\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , dmc_id
)
;
556 return false0;
557 }
558
559 if (header_ver == 1) {
560 start_range = DMC_MMIO_START_RANGE0x80000;
561 end_range = DMC_MMIO_END_RANGE0x8FFFF;
562 } else if (dmc_id == DMC_FW_MAIN) {
563 start_range = TGL_MAIN_MMIO_START0x8F000;
564 end_range = TGL_MAIN_MMIO_END0x8FFFF;
565 } else if (DISPLAY_VER(i915)((&(i915)->__runtime)->display.ip.ver) >= 13) {
566 start_range = ADLP_PIPE_MMIO_START0x5F000;
567 end_range = ADLP_PIPE_MMIO_END0x5FFFF;
568 } else if (DISPLAY_VER(i915)((&(i915)->__runtime)->display.ip.ver) >= 12) {
569 start_range = TGL_PIPE_MMIO_START(dmc_id)((0x92000) + (((dmc_id) - 1)) * ((0x96000) - (0x92000)));
570 end_range = TGL_PIPE_MMIO_END(dmc_id)((0x93FFF) + (((dmc_id) - 1)) * ((0x97FFF) - (0x93FFF)));
571 } else {
572 drm_warn(&i915->drm, "Unknown mmio range for sanity check")printf("drm:pid%d:%s *WARNING* " "[drm] " "Unknown mmio range for sanity check"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__)
;
573 return false0;
574 }
575
576 for (i = 0; i < mmio_count; i++) {
577 if (mmioaddr[i] < start_range || mmioaddr[i] > end_range)
578 return false0;
579 }
580
581 return true1;
582}
583
584static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
585 const struct intel_dmc_header_base *dmc_header,
586 size_t rem_size, u8 dmc_id)
587{
588 struct drm_i915_privateinteldrm_softc *i915 = container_of(dmc, typeof(*i915), display.dmc)({ const __typeof( ((typeof(*i915) *)0)->display.dmc ) *__mptr
= (dmc); (typeof(*i915) *)( (char *)__mptr - __builtin_offsetof
(typeof(*i915), display.dmc) );})
;
Value stored to 'i915' during its initialization is never read
589 struct dmc_fw_info *dmc_info = &dmc->dmc_info[dmc_id];
590 unsigned int header_len_bytes, dmc_header_size, payload_size, i;
591 const u32 *mmioaddr, *mmiodata;
592 u32 mmio_count, mmio_count_max, start_mmioaddr;
593 u8 *payload;
594
595 BUILD_BUG_ON(ARRAY_SIZE(dmc_info->mmioaddr) < DMC_V3_MAX_MMIO_COUNT ||extern char _ctassert[(!((sizeof((dmc_info->mmioaddr)) / sizeof
((dmc_info->mmioaddr)[0])) < 20 || (sizeof((dmc_info->
mmioaddr)) / sizeof((dmc_info->mmioaddr)[0])) < 8)) ? 1
: -1 ] __attribute__((__unused__))
596 ARRAY_SIZE(dmc_info->mmioaddr) < DMC_V1_MAX_MMIO_COUNT)extern char _ctassert[(!((sizeof((dmc_info->mmioaddr)) / sizeof
((dmc_info->mmioaddr)[0])) < 20 || (sizeof((dmc_info->
mmioaddr)) / sizeof((dmc_info->mmioaddr)[0])) < 8)) ? 1
: -1 ] __attribute__((__unused__))
;
597
598 /*
599 * Check if we can access common fields, we will checkc again below
600 * after we have read the version
601 */
602 if (rem_size < sizeof(struct intel_dmc_header_base))
603 goto error_truncated;
604
605 /* Cope with small differences between v1 and v3 */
606 if (dmc_header->header_ver == 3) {
607 const struct intel_dmc_header_v3 *v3 =
608 (const struct intel_dmc_header_v3 *)dmc_header;
609
610 if (rem_size < sizeof(struct intel_dmc_header_v3))
611 goto error_truncated;
612
613 mmioaddr = v3->mmioaddr;
614 mmiodata = v3->mmiodata;
615 mmio_count = v3->mmio_count;
616 mmio_count_max = DMC_V3_MAX_MMIO_COUNT20;
617 /* header_len is in dwords */
618 header_len_bytes = dmc_header->header_len * 4;
619 start_mmioaddr = v3->start_mmioaddr;
620 dmc_header_size = sizeof(*v3);
621 } else if (dmc_header->header_ver == 1) {
622 const struct intel_dmc_header_v1 *v1 =
623 (const struct intel_dmc_header_v1 *)dmc_header;
624
625 if (rem_size < sizeof(struct intel_dmc_header_v1))
626 goto error_truncated;
627
628 mmioaddr = v1->mmioaddr;
629 mmiodata = v1->mmiodata;
630 mmio_count = v1->mmio_count;
631 mmio_count_max = DMC_V1_MAX_MMIO_COUNT8;
632 header_len_bytes = dmc_header->header_len;
633 start_mmioaddr = DMC_V1_MMIO_START_RANGE0x80000;
634 dmc_header_size = sizeof(*v1);
635 } else {
636 drm_err(&i915->drm, "Unknown DMC fw header version: %u\n",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Unknown DMC fw header version: %u\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , dmc_header
->header_ver)
637 dmc_header->header_ver)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Unknown DMC fw header version: %u\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , dmc_header
->header_ver)
;
638 return 0;
639 }
640
641 if (header_len_bytes != dmc_header_size) {
642 drm_err(&i915->drm, "DMC firmware has wrong dmc header length "printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC firmware has wrong dmc header length "
"(%u bytes)\n", ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , header_len_bytes
)
643 "(%u bytes)\n", header_len_bytes)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC firmware has wrong dmc header length "
"(%u bytes)\n", ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , header_len_bytes
)
;
644 return 0;
645 }
646
647 /* Cache the dmc header info. */
648 if (mmio_count > mmio_count_max) {
649 drm_err(&i915->drm, "DMC firmware has wrong mmio count %u\n", mmio_count)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC firmware has wrong mmio count %u\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , mmio_count
)
;
650 return 0;
651 }
652
653 if (!dmc_mmio_addr_sanity_check(dmc, mmioaddr, mmio_count,
654 dmc_header->header_ver, dmc_id)) {
655 drm_err(&i915->drm, "DMC firmware has Wrong MMIO Addresses\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC firmware has Wrong MMIO Addresses\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__)
;
656 return 0;
657 }
658
659 for (i = 0; i < mmio_count; i++) {
660 dmc_info->mmioaddr[i] = _MMIO(mmioaddr[i])((const i915_reg_t){ .reg = (mmioaddr[i]) });
661 dmc_info->mmiodata[i] = mmiodata[i];
662 }
663 dmc_info->mmio_count = mmio_count;
664 dmc_info->start_mmioaddr = start_mmioaddr;
665
666 rem_size -= header_len_bytes;
667
668 /* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
669 payload_size = dmc_header->fw_size * 4;
670 if (rem_size < payload_size)
671 goto error_truncated;
672
673 if (payload_size > dmc->max_fw_size) {
674 drm_err(&i915->drm, "DMC FW too big (%u bytes)\n", payload_size)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC FW too big (%u bytes)\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , payload_size
)
;
675 return 0;
676 }
677 dmc_info->dmc_fw_size = dmc_header->fw_size;
678
679 dmc_info->payload = kmalloc(payload_size, GFP_KERNEL(0x0001 | 0x0004));
680 if (!dmc_info->payload)
681 return 0;
682
683 payload = (u8 *)(dmc_header) + header_len_bytes;
684 memcpy(dmc_info->payload, payload, payload_size)__builtin_memcpy((dmc_info->payload), (payload), (payload_size
))
;
685
686 return header_len_bytes + payload_size;
687
688error_truncated:
689 drm_err(&i915->drm, "Truncated DMC firmware, refusing.\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Truncated DMC firmware, refusing.\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__)
;
690 return 0;
691}
692
693static u32
694parse_dmc_fw_package(struct intel_dmc *dmc,
695 const struct intel_package_header *package_header,
696 const struct stepping_info *si,
697 size_t rem_size)
698{
699 struct drm_i915_privateinteldrm_softc *i915 = container_of(dmc, typeof(*i915), display.dmc)({ const __typeof( ((typeof(*i915) *)0)->display.dmc ) *__mptr
= (dmc); (typeof(*i915) *)( (char *)__mptr - __builtin_offsetof
(typeof(*i915), display.dmc) );})
;
700 u32 package_size = sizeof(struct intel_package_header);
701 u32 num_entries, max_entries;
702 const struct intel_fw_info *fw_info;
703
704 if (rem_size < package_size)
705 goto error_truncated;
706
707 if (package_header->header_ver == 1) {
708 max_entries = PACKAGE_MAX_FW_INFO_ENTRIES20;
709 } else if (package_header->header_ver == 2) {
710 max_entries = PACKAGE_V2_MAX_FW_INFO_ENTRIES32;
711 } else {
712 drm_err(&i915->drm, "DMC firmware has unknown header version %u\n",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC firmware has unknown header version %u\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , package_header
->header_ver)
713 package_header->header_ver)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC firmware has unknown header version %u\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , package_header
->header_ver)
;
714 return 0;
715 }
716
717 /*
718 * We should always have space for max_entries,
719 * even if not all are used
720 */
721 package_size += max_entries * sizeof(struct intel_fw_info);
722 if (rem_size < package_size)
723 goto error_truncated;
724
725 if (package_header->header_len * 4 != package_size) {
726 drm_err(&i915->drm, "DMC firmware has wrong package header length "printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC firmware has wrong package header length "
"(%u bytes)\n", ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , package_size
)
727 "(%u bytes)\n", package_size)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC firmware has wrong package header length "
"(%u bytes)\n", ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , package_size
)
;
728 return 0;
729 }
730
731 num_entries = package_header->num_entries;
732 if (WARN_ON(package_header->num_entries > max_entries)({ int __ret = !!(package_header->num_entries > max_entries
); if (__ret) printf("WARNING %s failed at %s:%d\n", "package_header->num_entries > max_entries"
, "/usr/src/sys/dev/pci/drm/i915/display/intel_dmc.c", 732); __builtin_expect
(!!(__ret), 0); })
)
733 num_entries = max_entries;
734
735 fw_info = (const struct intel_fw_info *)
736 ((u8 *)package_header + sizeof(*package_header));
737 dmc_set_fw_offset(dmc, fw_info, num_entries, si,
738 package_header->header_ver);
739
740 /* dmc_offset is in dwords */
741 return package_size;
742
743error_truncated:
744 drm_err(&i915->drm, "Truncated DMC firmware, refusing.\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Truncated DMC firmware, refusing.\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__)
;
745 return 0;
746}
747
748/* Return number of bytes parsed or 0 on error */
749static u32 parse_dmc_fw_css(struct intel_dmc *dmc,
750 struct intel_css_header *css_header,
751 size_t rem_size)
752{
753 struct drm_i915_privateinteldrm_softc *i915 = container_of(dmc, typeof(*i915), display.dmc)({ const __typeof( ((typeof(*i915) *)0)->display.dmc ) *__mptr
= (dmc); (typeof(*i915) *)( (char *)__mptr - __builtin_offsetof
(typeof(*i915), display.dmc) );})
;
754
755 if (rem_size < sizeof(struct intel_css_header)) {
756 drm_err(&i915->drm, "Truncated DMC firmware, refusing.\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Truncated DMC firmware, refusing.\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__)
;
757 return 0;
758 }
759
760 if (sizeof(struct intel_css_header) !=
761 (css_header->header_len * 4)) {
762 drm_err(&i915->drm, "DMC firmware has wrong CSS header length "printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC firmware has wrong CSS header length "
"(%u bytes)\n", ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , (css_header
->header_len * 4))
763 "(%u bytes)\n",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC firmware has wrong CSS header length "
"(%u bytes)\n", ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , (css_header
->header_len * 4))
764 (css_header->header_len * 4))printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMC firmware has wrong CSS header length "
"(%u bytes)\n", ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , (css_header
->header_len * 4))
;
765 return 0;
766 }
767
768 if (dmc->required_version &&
769 css_header->version != dmc->required_version) {
770 drm_info(&i915->drm, "Refusing to load DMC firmware v%u.%u,"do { } while(0)
771 " please use v%u.%u\n",do { } while(0)
772 DMC_VERSION_MAJOR(css_header->version),do { } while(0)
773 DMC_VERSION_MINOR(css_header->version),do { } while(0)
774 DMC_VERSION_MAJOR(dmc->required_version),do { } while(0)
775 DMC_VERSION_MINOR(dmc->required_version))do { } while(0);
776 return 0;
777 }
778
779 dmc->version = css_header->version;
780
781 return sizeof(struct intel_css_header);
782}
783
784static void parse_dmc_fw(struct drm_i915_privateinteldrm_softc *dev_priv,
785 const struct firmware *fw)
786{
787 struct intel_css_header *css_header;
788 struct intel_package_header *package_header;
789 struct intel_dmc_header_base *dmc_header;
790 struct intel_dmc *dmc = &dev_priv->display.dmc;
791 struct stepping_info display_info = { '*', '*'};
792 const struct stepping_info *si = intel_get_stepping_info(dev_priv, &display_info);
793 u32 readcount = 0;
794 u32 r, offset;
795 int id;
796
797 if (!fw)
798 return;
799
800 /* Extract CSS Header information */
801 css_header = (struct intel_css_header *)fw->data;
802 r = parse_dmc_fw_css(dmc, css_header, fw->size);
803 if (!r)
804 return;
805
806 readcount += r;
807
808 /* Extract Package Header information */
809 package_header = (struct intel_package_header *)&fw->data[readcount];
810 r = parse_dmc_fw_package(dmc, package_header, si, fw->size - readcount);
811 if (!r)
812 return;
813
814 readcount += r;
815
816 for (id = 0; id < DMC_FW_MAX; id++) {
817 if (!dev_priv->display.dmc.dmc_info[id].present)
818 continue;
819
820 offset = readcount + dmc->dmc_info[id].dmc_offset * 4;
821 if (offset > fw->size) {
822 drm_err(&dev_priv->drm, "Reading beyond the fw_size\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Reading beyond the fw_size\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__)
;
823 continue;
824 }
825
826 dmc_header = (struct intel_dmc_header_base *)&fw->data[offset];
827 parse_dmc_fw_header(dmc, dmc_header, fw->size - offset, id);
828 }
829}
830
831static void intel_dmc_runtime_pm_get(struct drm_i915_privateinteldrm_softc *dev_priv)
832{
833 drm_WARN_ON(&dev_priv->drm, dev_priv->display.dmc.wakeref)({ int __ret = !!((dev_priv->display.dmc.wakeref)); if (__ret
) printf("%s %s: " "%s", dev_driver_string(((&dev_priv->
drm))->dev), "", "drm_WARN_ON(" "dev_priv->display.dmc.wakeref"
")"); __builtin_expect(!!(__ret), 0); })
;
834 dev_priv->display.dmc.wakeref =
835 intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
836}
837
838static void intel_dmc_runtime_pm_put(struct drm_i915_privateinteldrm_softc *dev_priv)
839{
840 intel_wakeref_t wakeref __maybe_unused__attribute__((__unused__)) =
841 fetch_and_zero(&dev_priv->display.dmc.wakeref)({ typeof(*&dev_priv->display.dmc.wakeref) __T = *(&
dev_priv->display.dmc.wakeref); *(&dev_priv->display
.dmc.wakeref) = (typeof(*&dev_priv->display.dmc.wakeref
))0; __T; })
;
842
843 intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
844}
845
846static void dmc_load_work_fn(struct work_struct *work)
847{
848 struct drm_i915_privateinteldrm_softc *dev_priv;
849 struct intel_dmc *dmc;
850 const struct firmware *fw = NULL((void *)0);
851
852 dev_priv = container_of(work, typeof(*dev_priv), display.dmc.work)({ const __typeof( ((typeof(*dev_priv) *)0)->display.dmc.work
) *__mptr = (work); (typeof(*dev_priv) *)( (char *)__mptr - __builtin_offsetof
(typeof(*dev_priv), display.dmc.work) );})
;
853 dmc = &dev_priv->display.dmc;
854
855#ifdef __linux__
856 request_firmware(&fw, dev_priv->display.dmc.fw_path, dev_priv->drm.dev);
857#else
858 request_firmware(&fw, dev_priv->display.dmc.fw_path, NULL((void *)0));
859#endif
860 parse_dmc_fw(dev_priv, fw);
861
862 if (intel_dmc_has_payload(dev_priv)) {
863 intel_dmc_load_program(dev_priv);
864 intel_dmc_runtime_pm_put(dev_priv);
865
866 drm_info(&dev_priv->drm,do { } while(0)
867 "Finished loading DMC firmware %s (v%u.%u)\n",do { } while(0)
868 dev_priv->display.dmc.fw_path, DMC_VERSION_MAJOR(dmc->version),do { } while(0)
869 DMC_VERSION_MINOR(dmc->version))do { } while(0);
870 } else {
871 drm_notice(&dev_priv->drm,printf("drm:pid%d:%s *NOTICE* " "[drm] " "Failed to load DMC firmware %s."
" Disabling runtime power management.\n", ({struct cpu_info *
__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_pid, __func__ , dmc->fw_path)
872 "Failed to load DMC firmware %s."printf("drm:pid%d:%s *NOTICE* " "[drm] " "Failed to load DMC firmware %s."
" Disabling runtime power management.\n", ({struct cpu_info *
__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_pid, __func__ , dmc->fw_path)
873 " Disabling runtime power management.\n",printf("drm:pid%d:%s *NOTICE* " "[drm] " "Failed to load DMC firmware %s."
" Disabling runtime power management.\n", ({struct cpu_info *
__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_pid, __func__ , dmc->fw_path)
874 dmc->fw_path)printf("drm:pid%d:%s *NOTICE* " "[drm] " "Failed to load DMC firmware %s."
" Disabling runtime power management.\n", ({struct cpu_info *
__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_pid, __func__ , dmc->fw_path)
;
875#ifdef __linux__
876 drm_notice(&dev_priv->drm, "DMC firmware homepage: %s",printf("drm:pid%d:%s *NOTICE* " "[drm] " "DMC firmware homepage: %s"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/i915"
)
877 INTEL_UC_FIRMWARE_URL)printf("drm:pid%d:%s *NOTICE* " "[drm] " "DMC firmware homepage: %s"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/i915"
)
;
878#endif
879 }
880
881 release_firmware(fw);
882}
883
884/**
885 * intel_dmc_ucode_init() - initialize the firmware loading.
886 * @dev_priv: i915 drm device.
887 *
888 * This function is called at the time of loading the display driver to read
889 * firmware from a .bin file and copied into a internal memory.
890 */
891void intel_dmc_ucode_init(struct drm_i915_privateinteldrm_softc *dev_priv)
892{
893 struct intel_dmc *dmc = &dev_priv->display.dmc;
894
895 INIT_WORK(&dev_priv->display.dmc.work, dmc_load_work_fn);
896
897 if (!HAS_DMC(dev_priv)((&(dev_priv)->__runtime)->has_dmc))
898 return;
899
900 /*
901 * Obtain a runtime pm reference, until DMC is loaded, to avoid entering
902 * runtime-suspend.
903 *
904 * On error, we return with the rpm wakeref held to prevent runtime
905 * suspend as runtime suspend *requires* a working DMC for whatever
906 * reason.
907 */
908 intel_dmc_runtime_pm_get(dev_priv);
909
910 if (IS_DG2(dev_priv)IS_PLATFORM(dev_priv, INTEL_DG2)) {
911 dmc->fw_path = DG2_DMC_PATH"i915/" "dg2" "_dmc_ver" "2" "_" "07" ".bin";
912 dmc->required_version = DG2_DMC_VERSION_REQUIRED((2) << 16 | (07));
913 dmc->max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE0x20000;
914 } else if (IS_ALDERLAKE_P(dev_priv)IS_PLATFORM(dev_priv, INTEL_ALDERLAKE_P)) {
915 dmc->fw_path = ADLP_DMC_PATH"i915/" "adlp" "_dmc_ver" "2" "_" "16" ".bin";
916 dmc->required_version = ADLP_DMC_VERSION_REQUIRED((2) << 16 | (16));
917 dmc->max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE0x20000;
918 } else if (IS_ALDERLAKE_S(dev_priv)IS_PLATFORM(dev_priv, INTEL_ALDERLAKE_S)) {
919 dmc->fw_path = ADLS_DMC_PATH"i915/" "adls" "_dmc_ver" "2" "_" "01" ".bin";
920 dmc->required_version = ADLS_DMC_VERSION_REQUIRED((2) << 16 | (1));
921 dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE0x6000;
922 } else if (IS_DG1(dev_priv)IS_PLATFORM(dev_priv, INTEL_DG1)) {
923 dmc->fw_path = DG1_DMC_PATH"i915/" "dg1" "_dmc_ver" "2" "_" "02" ".bin";
924 dmc->required_version = DG1_DMC_VERSION_REQUIRED((2) << 16 | (2));
925 dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE0x6000;
926 } else if (IS_ROCKETLAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_ROCKETLAKE)) {
927 dmc->fw_path = RKL_DMC_PATH"i915/" "rkl" "_dmc_ver" "2" "_" "03" ".bin";
928 dmc->required_version = RKL_DMC_VERSION_REQUIRED((2) << 16 | (3));
929 dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE0x6000;
930 } else if (IS_TIGERLAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_TIGERLAKE)) {
931 dmc->fw_path = TGL_DMC_PATH"i915/" "tgl" "_dmc_ver" "2" "_" "12" ".bin";
932 dmc->required_version = TGL_DMC_VERSION_REQUIRED((2) << 16 | (12));
933 dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE0x6000;
934 } else if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) == 11) {
935 dmc->fw_path = ICL_DMC_PATH"i915/" "icl" "_dmc_ver" "1" "_" "09" ".bin";
936 dmc->required_version = ICL_DMC_VERSION_REQUIRED((1) << 16 | (9));
937 dmc->max_fw_size = ICL_DMC_MAX_FW_SIZE0x6000;
938 } else if (IS_GEMINILAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_GEMINILAKE)) {
939 dmc->fw_path = GLK_DMC_PATH"i915/" "glk" "_dmc_ver" "1" "_" "04" ".bin";
940 dmc->required_version = GLK_DMC_VERSION_REQUIRED((1) << 16 | (4));
941 dmc->max_fw_size = GLK_DMC_MAX_FW_SIZE0x4000;
942 } else if (IS_KABYLAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_KABYLAKE) ||
943 IS_COFFEELAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_COFFEELAKE) ||
944 IS_COMETLAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_COMETLAKE)) {
945 dmc->fw_path = KBL_DMC_PATH"i915/" "kbl" "_dmc_ver" "1" "_" "04" ".bin";
946 dmc->required_version = KBL_DMC_VERSION_REQUIRED((1) << 16 | (4));
947 dmc->max_fw_size = KBL_DMC_MAX_FW_SIZE0x3000;
948 } else if (IS_SKYLAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_SKYLAKE)) {
949 dmc->fw_path = SKL_DMC_PATH"i915/" "skl" "_dmc_ver" "1" "_" "27" ".bin";
950 dmc->required_version = SKL_DMC_VERSION_REQUIRED((1) << 16 | (27));
951 dmc->max_fw_size = SKL_DMC_MAX_FW_SIZE0x3000;
952 } else if (IS_BROXTON(dev_priv)IS_PLATFORM(dev_priv, INTEL_BROXTON)) {
953 dmc->fw_path = BXT_DMC_PATH"i915/" "bxt" "_dmc_ver" "1" "_" "07" ".bin";
954 dmc->required_version = BXT_DMC_VERSION_REQUIRED((1) << 16 | (7));
955 dmc->max_fw_size = BXT_DMC_MAX_FW_SIZE0x3000;
956 }
957
958 if (dev_priv->params.dmc_firmware_path) {
959 if (strlen(dev_priv->params.dmc_firmware_path) == 0) {
960 dmc->fw_path = NULL((void *)0);
961 drm_info(&dev_priv->drm,do { } while(0)
962 "Disabling DMC firmware and runtime PM\n")do { } while(0);
963 return;
964 }
965
966 dmc->fw_path = dev_priv->params.dmc_firmware_path;
967 /* Bypass version check for firmware override. */
968 dmc->required_version = 0;
969 }
970
971 if (!dmc->fw_path) {
972 drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "No known DMC firmware for platform, disabling runtime PM\n"
)
973 "No known DMC firmware for platform, disabling runtime PM\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "No known DMC firmware for platform, disabling runtime PM\n"
)
;
974 return;
975 }
976
977 drm_dbg_kms(&dev_priv->drm, "Loading %s\n", dmc->fw_path)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Loading %s\n", dmc
->fw_path)
;
978 schedule_work(&dev_priv->display.dmc.work);
979}
980
981/**
982 * intel_dmc_ucode_suspend() - prepare DMC firmware before system suspend
983 * @dev_priv: i915 drm device
984 *
985 * Prepare the DMC firmware before entering system suspend. This includes
986 * flushing pending work items and releasing any resources acquired during
987 * init.
988 */
989void intel_dmc_ucode_suspend(struct drm_i915_privateinteldrm_softc *dev_priv)
990{
991 if (!HAS_DMC(dev_priv)((&(dev_priv)->__runtime)->has_dmc))
992 return;
993
994 flush_work(&dev_priv->display.dmc.work);
995
996 /* Drop the reference held in case DMC isn't loaded. */
997 if (!intel_dmc_has_payload(dev_priv))
998 intel_dmc_runtime_pm_put(dev_priv);
999}
1000
1001/**
1002 * intel_dmc_ucode_resume() - init DMC firmware during system resume
1003 * @dev_priv: i915 drm device
1004 *
1005 * Reinitialize the DMC firmware during system resume, reacquiring any
1006 * resources released in intel_dmc_ucode_suspend().
1007 */
1008void intel_dmc_ucode_resume(struct drm_i915_privateinteldrm_softc *dev_priv)
1009{
1010 if (!HAS_DMC(dev_priv)((&(dev_priv)->__runtime)->has_dmc))
1011 return;
1012
1013 /*
1014 * Reacquire the reference to keep RPM disabled in case DMC isn't
1015 * loaded.
1016 */
1017 if (!intel_dmc_has_payload(dev_priv))
1018 intel_dmc_runtime_pm_get(dev_priv);
1019}
1020
1021/**
1022 * intel_dmc_ucode_fini() - unload the DMC firmware.
1023 * @dev_priv: i915 drm device.
1024 *
1025 * Firmmware unloading includes freeing the internal memory and reset the
1026 * firmware loading status.
1027 */
1028void intel_dmc_ucode_fini(struct drm_i915_privateinteldrm_softc *dev_priv)
1029{
1030 int id;
1031
1032 if (!HAS_DMC(dev_priv)((&(dev_priv)->__runtime)->has_dmc))
1033 return;
1034
1035 intel_dmc_ucode_suspend(dev_priv);
1036 drm_WARN_ON(&dev_priv->drm, dev_priv->display.dmc.wakeref)({ int __ret = !!((dev_priv->display.dmc.wakeref)); if (__ret
) printf("%s %s: " "%s", dev_driver_string(((&dev_priv->
drm))->dev), "", "drm_WARN_ON(" "dev_priv->display.dmc.wakeref"
")"); __builtin_expect(!!(__ret), 0); })
;
1037
1038 for (id = 0; id < DMC_FW_MAX; id++)
1039 kfree(dev_priv->display.dmc.dmc_info[id].payload);
1040}
1041
1042void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m,
1043 struct drm_i915_privateinteldrm_softc *i915)
1044{
1045 struct intel_dmc *dmc = &i915->display.dmc;
1046
1047 if (!HAS_DMC(i915)((&(i915)->__runtime)->has_dmc))
1048 return;
1049
1050 i915_error_printf(m, "DMC loaded: %s\n",
1051 str_yes_no(intel_dmc_has_payload(i915)));
1052 i915_error_printf(m, "DMC fw version: %d.%d\n",
1053 DMC_VERSION_MAJOR(dmc->version)((dmc->version) >> 16),
1054 DMC_VERSION_MINOR(dmc->version)((dmc->version) & 0xffff));
1055}
1056
1057#ifdef notyet
1058
1059static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
1060{
1061 struct drm_i915_privateinteldrm_softc *i915 = m->private;
1062 intel_wakeref_t wakeref;
1063 struct intel_dmc *dmc;
1064 i915_reg_t dc5_reg, dc6_reg = INVALID_MMIO_REG((const i915_reg_t){ .reg = (0) });
1065
1066 if (!HAS_DMC(i915)((&(i915)->__runtime)->has_dmc))
1067 return -ENODEV19;
1068
1069 dmc = &i915->display.dmc;
1070
1071 wakeref = intel_runtime_pm_get(&i915->runtime_pm);
1072
1073 seq_printf(m, "fw loaded: %s\n",
1074 str_yes_no(intel_dmc_has_payload(i915)));
1075 seq_printf(m, "path: %s\n", dmc->fw_path);
1076 seq_printf(m, "Pipe A fw support: %s\n",
1077 str_yes_no(GRAPHICS_VER(i915)((&(i915)->__runtime)->graphics.ip.ver) >= 12));
1078 seq_printf(m, "Pipe A fw loaded: %s\n",
1079 str_yes_no(dmc->dmc_info[DMC_FW_PIPEA].payload));
1080 seq_printf(m, "Pipe B fw support: %s\n",
1081 str_yes_no(IS_ALDERLAKE_P(i915)IS_PLATFORM(i915, INTEL_ALDERLAKE_P)));
1082 seq_printf(m, "Pipe B fw loaded: %s\n",
1083 str_yes_no(dmc->dmc_info[DMC_FW_PIPEB].payload));
1084
1085 if (!intel_dmc_has_payload(i915))
1086 goto out;
1087
1088 seq_printf(m, "version: %d.%d\n", DMC_VERSION_MAJOR(dmc->version)((dmc->version) >> 16),
1089 DMC_VERSION_MINOR(dmc->version)((dmc->version) & 0xffff));
1090
1091 if (DISPLAY_VER(i915)((&(i915)->__runtime)->display.ip.ver) >= 12) {
1092 if (IS_DGFX(i915)((&(i915)->__info)->is_dgfx)) {
1093 dc5_reg = DG1_DMC_DEBUG_DC5_COUNT((const i915_reg_t){ .reg = (0x134154) });
1094 } else {
1095 dc5_reg = TGL_DMC_DEBUG_DC5_COUNT((const i915_reg_t){ .reg = (0x101084) });
1096 dc6_reg = TGL_DMC_DEBUG_DC6_COUNT((const i915_reg_t){ .reg = (0x101088) });
1097 }
1098
1099 /*
1100 * NOTE: DMC_DEBUG3 is a general purpose reg.
1101 * According to B.Specs:49196 DMC f/w reuses DC5/6 counter
1102 * reg for DC3CO debugging and validation,
1103 * but TGL DMC f/w is using DMC_DEBUG3 reg for DC3CO counter.
1104 */
1105 seq_printf(m, "DC3CO count: %d\n",
1106 intel_de_read(i915, IS_DGFX(i915)((&(i915)->__info)->is_dgfx) ?
1107 DG1_DMC_DEBUG3((const i915_reg_t){ .reg = (0x13415c) }) : TGL_DMC_DEBUG3((const i915_reg_t){ .reg = (0x101090) })));
1108 } else {
1109 dc5_reg = IS_BROXTON(i915)IS_PLATFORM(i915, INTEL_BROXTON) ? BXT_DMC_DC3_DC5_COUNT((const i915_reg_t){ .reg = (0x80038) }) :
1110 SKL_DMC_DC3_DC5_COUNT((const i915_reg_t){ .reg = (0x80030) });
1111 if (!IS_GEMINILAKE(i915)IS_PLATFORM(i915, INTEL_GEMINILAKE) && !IS_BROXTON(i915)IS_PLATFORM(i915, INTEL_BROXTON))
1112 dc6_reg = SKL_DMC_DC5_DC6_COUNT((const i915_reg_t){ .reg = (0x8002C) });
1113 }
1114
1115 seq_printf(m, "DC3 -> DC5 count: %d\n", intel_de_read(i915, dc5_reg));
1116 if (i915_mmio_reg_valid(dc6_reg))
1117 seq_printf(m, "DC5 -> DC6 count: %d\n",
1118 intel_de_read(i915, dc6_reg));
1119
1120out:
1121 seq_printf(m, "program base: 0x%08x\n",
1122 intel_de_read(i915, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)((const i915_reg_t){ .reg = ((dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr
) + (0) * 4) })
));
1123 seq_printf(m, "ssp base: 0x%08x\n",
1124 intel_de_read(i915, DMC_SSP_BASE((const i915_reg_t){ .reg = (0x8F074) })));
1125 seq_printf(m, "htp: 0x%08x\n", intel_de_read(i915, DMC_HTP_SKL((const i915_reg_t){ .reg = (0x8F004) })));
1126
1127 intel_runtime_pm_put(&i915->runtime_pm, wakeref);
1128
1129 return 0;
1130}
1131
1132DEFINE_SHOW_ATTRIBUTE(intel_dmc_debugfs_status);
1133
1134#endif /* notyet */
1135
1136void intel_dmc_debugfs_register(struct drm_i915_privateinteldrm_softc *i915)
1137{
1138 struct drm_minor *minor = i915->drm.primary;
1139
1140 debugfs_create_file("i915_dmc_info", 0444, minor->debugfs_root,ERR_PTR(-78)
1141 i915, &intel_dmc_debugfs_status_fops)ERR_PTR(-78);
1142}