Bug Summary

File:dev/pci/drm/i915/display/intel_combo_phy.c
Warning:line 425, column 33
The left operand of '+' is a garbage value due to array index out of bounds

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_combo_phy.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_combo_phy.c
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2018 Intel Corporation
4 */
5
6#include "intel_combo_phy.h"
7#include "intel_combo_phy_regs.h"
8#include "intel_de.h"
9#include "intel_display_types.h"
10
11#define for_each_combo_phy(__dev_priv, __phy)for ((__phy) = PHY_A; (__phy) < I915_MAX_PHYS; (__phy)++) if
(!(intel_phy_is_combo(__dev_priv, __phy))) {} else
\
12 for ((__phy) = PHY_A; (__phy) < I915_MAX_PHYS; (__phy)++) \
13 for_each_if(intel_phy_is_combo(__dev_priv, __phy))if (!(intel_phy_is_combo(__dev_priv, __phy))) {} else
14
15#define for_each_combo_phy_reverse(__dev_priv, __phy)for ((__phy) = I915_MAX_PHYS; (__phy)-- > PHY_A;) if (!(intel_phy_is_combo
(__dev_priv, __phy))) {} else
\
16 for ((__phy) = I915_MAX_PHYS; (__phy)-- > PHY_A;) \
17 for_each_if(intel_phy_is_combo(__dev_priv, __phy))if (!(intel_phy_is_combo(__dev_priv, __phy))) {} else
18
19enum {
20 PROCMON_0_85V_DOT_0,
21 PROCMON_0_95V_DOT_0,
22 PROCMON_0_95V_DOT_1,
23 PROCMON_1_05V_DOT_0,
24 PROCMON_1_05V_DOT_1,
25};
26
27static const struct icl_procmon {
28 const char *name;
29 u32 dw1, dw9, dw10;
30} icl_procmon_values[] = {
31 [PROCMON_0_85V_DOT_0] = {
32 .name = "0.85V dot0 (low-voltage)",
33 .dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96,
34 },
35 [PROCMON_0_95V_DOT_0] = {
36 .name = "0.95V dot0",
37 .dw1 = 0x00000000, .dw9 = 0x86E172C7, .dw10 = 0x77CA5EAB,
38 },
39 [PROCMON_0_95V_DOT_1] = {
40 .name = "0.95V dot1",
41 .dw1 = 0x00000000, .dw9 = 0x93F87FE1, .dw10 = 0x8AE871C5,
42 },
43 [PROCMON_1_05V_DOT_0] = {
44 .name = "1.05V dot0",
45 .dw1 = 0x00000000, .dw9 = 0x98FA82DD, .dw10 = 0x89E46DC1,
46 },
47 [PROCMON_1_05V_DOT_1] = {
48 .name = "1.05V dot1",
49 .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1,
50 },
51};
52
53static const struct icl_procmon *
54icl_get_procmon_ref_values(struct drm_i915_privateinteldrm_softc *dev_priv, enum phy phy)
55{
56 const struct icl_procmon *procmon;
57 u32 val;
58
59 val = intel_de_read(dev_priv, ICL_PORT_COMP_DW3(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (3))) }
)
);
60 switch (val & (PROCESS_INFO_MASK(7 << 26) | VOLTAGE_INFO_MASK(3 << 24))) {
61 default:
62 MISSING_CASE(val)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n"
, "val", (long)(val)); __builtin_expect(!!(__ret), 0); })
;
63 fallthroughdo {} while (0);
64 case VOLTAGE_INFO_0_85V(0 << 24) | PROCESS_INFO_DOT_0(0 << 26):
65 procmon = &icl_procmon_values[PROCMON_0_85V_DOT_0];
66 break;
67 case VOLTAGE_INFO_0_95V(1 << 24) | PROCESS_INFO_DOT_0(0 << 26):
68 procmon = &icl_procmon_values[PROCMON_0_95V_DOT_0];
69 break;
70 case VOLTAGE_INFO_0_95V(1 << 24) | PROCESS_INFO_DOT_1(1 << 26):
71 procmon = &icl_procmon_values[PROCMON_0_95V_DOT_1];
72 break;
73 case VOLTAGE_INFO_1_05V(2 << 24) | PROCESS_INFO_DOT_0(0 << 26):
74 procmon = &icl_procmon_values[PROCMON_1_05V_DOT_0];
75 break;
76 case VOLTAGE_INFO_1_05V(2 << 24) | PROCESS_INFO_DOT_1(1 << 26):
77 procmon = &icl_procmon_values[PROCMON_1_05V_DOT_1];
78 break;
79 }
80
81 return procmon;
82}
83
84static void icl_set_procmon_ref_values(struct drm_i915_privateinteldrm_softc *dev_priv,
85 enum phy phy)
86{
87 const struct icl_procmon *procmon;
88 u32 val;
89
90 procmon = icl_get_procmon_ref_values(dev_priv, phy);
91
92 val = intel_de_read(dev_priv, ICL_PORT_COMP_DW1(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (1))) }
)
);
93 val &= ~((0xff << 16) | 0xff);
94 val |= procmon->dw1;
95 intel_de_write(dev_priv, ICL_PORT_COMP_DW1(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (1))) }
)
, val);
96
97 intel_de_write(dev_priv, ICL_PORT_COMP_DW9(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (9))) }
)
, procmon->dw9);
98 intel_de_write(dev_priv, ICL_PORT_COMP_DW10(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (10))) }
)
, procmon->dw10);
99}
100
101static bool_Bool check_phy_reg(struct drm_i915_privateinteldrm_softc *dev_priv,
102 enum phy phy, i915_reg_t reg, u32 mask,
103 u32 expected_val)
104{
105 u32 val = intel_de_read(dev_priv, reg);
106
107 if ((val & mask) != expected_val) {
108 drm_dbg(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_DRIVER, "Combo PHY %c reg %08x state mismatch: "
"current %08x mask %08x expected %08x\n", ((phy) + 'A'), reg
.reg, val, mask, expected_val)
109 "Combo PHY %c reg %08x state mismatch: "__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_DRIVER, "Combo PHY %c reg %08x state mismatch: "
"current %08x mask %08x expected %08x\n", ((phy) + 'A'), reg
.reg, val, mask, expected_val)
110 "current %08x mask %08x expected %08x\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_DRIVER, "Combo PHY %c reg %08x state mismatch: "
"current %08x mask %08x expected %08x\n", ((phy) + 'A'), reg
.reg, val, mask, expected_val)
111 phy_name(phy),__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_DRIVER, "Combo PHY %c reg %08x state mismatch: "
"current %08x mask %08x expected %08x\n", ((phy) + 'A'), reg
.reg, val, mask, expected_val)
112 reg.reg, val, mask, expected_val)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_DRIVER, "Combo PHY %c reg %08x state mismatch: "
"current %08x mask %08x expected %08x\n", ((phy) + 'A'), reg
.reg, val, mask, expected_val)
;
113 return false0;
114 }
115
116 return true1;
117}
118
119static bool_Bool icl_verify_procmon_ref_values(struct drm_i915_privateinteldrm_softc *dev_priv,
120 enum phy phy)
121{
122 const struct icl_procmon *procmon;
123 bool_Bool ret;
124
125 procmon = icl_get_procmon_ref_values(dev_priv, phy);
126
127 drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Combo PHY %c Voltage/Process Info : %s\n"
, ((phy) + 'A'), procmon->name)
128 "Combo PHY %c Voltage/Process Info : %s\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Combo PHY %c Voltage/Process Info : %s\n"
, ((phy) + 'A'), procmon->name)
129 phy_name(phy), procmon->name)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Combo PHY %c Voltage/Process Info : %s\n"
, ((phy) + 'A'), procmon->name)
;
130
131 ret = check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW1(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (1))) }
)
,
132 (0xff << 16) | 0xff, procmon->dw1);
133 ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW9(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (9))) }
)
,
134 -1U, procmon->dw9);
135 ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW10(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (10))) }
)
,
136 -1U, procmon->dw10);
137
138 return ret;
139}
140
141static bool_Bool has_phy_misc(struct drm_i915_privateinteldrm_softc *i915, enum phy phy)
142{
143 /*
144 * Some platforms only expect PHY_MISC to be programmed for PHY-A and
145 * PHY-B and may not even have instances of the register for the
146 * other combo PHY's.
147 *
148 * ADL-S technically has three instances of PHY_MISC, but only requires
149 * that we program it for PHY A.
150 */
151
152 if (IS_ALDERLAKE_S(i915)IS_PLATFORM(i915, INTEL_ALDERLAKE_S))
153 return phy == PHY_A;
154 else if (IS_JSL_EHL(i915)(IS_PLATFORM(i915, INTEL_JASPERLAKE) || IS_PLATFORM(i915, INTEL_ELKHARTLAKE
))
||
155 IS_ROCKETLAKE(i915)IS_PLATFORM(i915, INTEL_ROCKETLAKE) ||
156 IS_DG1(i915)IS_PLATFORM(i915, INTEL_DG1))
157 return phy < PHY_C;
158
159 return true1;
160}
161
162static bool_Bool icl_combo_phy_enabled(struct drm_i915_privateinteldrm_softc *dev_priv,
163 enum phy phy)
164{
165 /* The PHY C added by EHL has no PHY_MISC register */
166 if (!has_phy_misc(dev_priv, phy))
167 return intel_de_read(dev_priv, ICL_PORT_COMP_DW0(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (0))) }
)
) & COMP_INIT(1 << 31);
168 else
169 return !(intel_de_read(dev_priv, ICL_PHY_MISC(phy)((const i915_reg_t){ .reg = (((0x64C00) + (phy) * ((0x64C04) -
(0x64C00)))) })
) &
170 ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN(1 << 23)) &&
171 (intel_de_read(dev_priv, ICL_PORT_COMP_DW0(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (0))) }
)
) & COMP_INIT(1 << 31));
172}
173
174static bool_Bool ehl_vbt_ddi_d_present(struct drm_i915_privateinteldrm_softc *i915)
175{
176 bool_Bool ddi_a_present = intel_bios_is_port_present(i915, PORT_A);
177 bool_Bool ddi_d_present = intel_bios_is_port_present(i915, PORT_D);
178 bool_Bool dsi_present = intel_bios_is_dsi_present(i915, NULL((void *)0));
179
180 /*
181 * VBT's 'dvo port' field for child devices references the DDI, not
182 * the PHY. So if combo PHY A is wired up to drive an external
183 * display, we should see a child device present on PORT_D and
184 * nothing on PORT_A and no DSI.
185 */
186 if (ddi_d_present && !ddi_a_present && !dsi_present)
187 return true1;
188
189 /*
190 * If we encounter a VBT that claims to have an external display on
191 * DDI-D _and_ an internal display on DDI-A/DSI leave an error message
192 * in the log and let the internal display win.
193 */
194 if (ddi_d_present)
195 drm_err(&i915->drm,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "VBT claims to have both internal and external displays on PHY A. Configuring for internal.\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__)
196 "VBT claims to have both internal and external displays on PHY A. Configuring for internal.\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "VBT claims to have both internal and external displays on PHY A. Configuring for internal.\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__)
;
197
198 return false0;
199}
200
201static bool_Bool phy_is_master(struct drm_i915_privateinteldrm_softc *dev_priv, enum phy phy)
202{
203 /*
204 * Certain PHYs are connected to compensation resistors and act
205 * as masters to other PHYs.
206 *
207 * ICL,TGL:
208 * A(master) -> B(slave), C(slave)
209 * RKL,DG1:
210 * A(master) -> B(slave)
211 * C(master) -> D(slave)
212 * ADL-S:
213 * A(master) -> B(slave), C(slave)
214 * D(master) -> E(slave)
215 *
216 * We must set the IREFGEN bit for any PHY acting as a master
217 * to another PHY.
218 */
219 if (phy == PHY_A)
220 return true1;
221 else if (IS_ALDERLAKE_S(dev_priv)IS_PLATFORM(dev_priv, INTEL_ALDERLAKE_S))
222 return phy == PHY_D;
223 else if (IS_DG1(dev_priv)IS_PLATFORM(dev_priv, INTEL_DG1) || IS_ROCKETLAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_ROCKETLAKE))
224 return phy == PHY_C;
225
226 return false0;
227}
228
229static bool_Bool icl_combo_phy_verify_state(struct drm_i915_privateinteldrm_softc *dev_priv,
230 enum phy phy)
231{
232 bool_Bool ret = true1;
233 u32 expected_val = 0;
234
235 if (!icl_combo_phy_enabled(dev_priv, phy))
236 return false0;
237
238 if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 12) {
239 ret &= check_phy_reg(dev_priv, phy, ICL_PORT_TX_DW8_LN(0, phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + (0x880 + (0) * 0x100
) + 4 * (8))) })
,
240 ICL_PORT_TX_DW8_ODCC_CLK_SEL((u32)((1UL << (31)) + 0)) |
241 ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_MASK((u32)((((~0UL) >> (64 - (30) - 1)) & ((~0UL) <<
(29))) + 0))
,
242 ICL_PORT_TX_DW8_ODCC_CLK_SEL((u32)((1UL << (31)) + 0)) |
243 ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_DIV2((u32)((((typeof(((u32)((((~0UL) >> (64 - (30) - 1)) &
((~0UL) << (29))) + 0))))(0x1) << (__builtin_ffsll
(((u32)((((~0UL) >> (64 - (30) - 1)) & ((~0UL) <<
(29))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (30
) - 1)) & ((~0UL) << (29))) + 0)))) + 0 + 0 + 0 + 0
))
);
244
245 ret &= check_phy_reg(dev_priv, phy, ICL_PORT_PCS_DW1_LN(0, phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + (0x800 + (0) * 0x100
) + 4 * (1))) })
,
246 DCC_MODE_SELECT_MASK(0x3 << 20),
247 DCC_MODE_SELECT_CONTINUOSLY(0x3 << 20));
248 }
249
250 ret &= icl_verify_procmon_ref_values(dev_priv, phy);
251
252 if (phy_is_master(dev_priv, phy)) {
253 ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW8(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (8))) }
)
,
254 IREFGEN(1 << 24), IREFGEN(1 << 24));
255
256 if (IS_JSL_EHL(dev_priv)(IS_PLATFORM(dev_priv, INTEL_JASPERLAKE) || IS_PLATFORM(dev_priv
, INTEL_ELKHARTLAKE))
) {
257 if (ehl_vbt_ddi_d_present(dev_priv))
258 expected_val = ICL_PHY_MISC_MUX_DDID(1 << 28);
259
260 ret &= check_phy_reg(dev_priv, phy, ICL_PHY_MISC(phy)((const i915_reg_t){ .reg = (((0x64C00) + (phy) * ((0x64C04) -
(0x64C00)))) })
,
261 ICL_PHY_MISC_MUX_DDID(1 << 28),
262 expected_val);
263 }
264 }
265
266 ret &= check_phy_reg(dev_priv, phy, ICL_PORT_CL_DW5(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 4 * (5))) })
,
267 CL_POWER_DOWN_ENABLE(1 << 4), CL_POWER_DOWN_ENABLE(1 << 4));
268
269 return ret;
270}
271
272void intel_combo_phy_power_up_lanes(struct drm_i915_privateinteldrm_softc *dev_priv,
273 enum phy phy, bool_Bool is_dsi,
274 int lane_count, bool_Bool lane_reversal)
275{
276 u8 lane_mask;
277 u32 val;
278
279 if (is_dsi) {
280 drm_WARN_ON(&dev_priv->drm, lane_reversal)({ int __ret = !!((lane_reversal)); if (__ret) printf("%s %s: "
"%s", dev_driver_string(((&dev_priv->drm))->dev), ""
, "drm_WARN_ON(" "lane_reversal" ")"); __builtin_expect(!!(__ret
), 0); })
;
281
282 switch (lane_count) {
283 case 1:
284 lane_mask = PWR_DOWN_LN_3_1_0(0xb << 4);
285 break;
286 case 2:
287 lane_mask = PWR_DOWN_LN_3_1(0xa << 4);
288 break;
289 case 3:
290 lane_mask = PWR_DOWN_LN_3(0x8 << 4);
291 break;
292 default:
293 MISSING_CASE(lane_count)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n"
, "lane_count", (long)(lane_count)); __builtin_expect(!!(__ret
), 0); })
;
294 fallthroughdo {} while (0);
295 case 4:
296 lane_mask = PWR_UP_ALL_LANES(0x0 << 4);
297 break;
298 }
299 } else {
300 switch (lane_count) {
301 case 1:
302 lane_mask = lane_reversal ? PWR_DOWN_LN_2_1_0(0x7 << 4) :
303 PWR_DOWN_LN_3_2_1(0xe << 4);
304 break;
305 case 2:
306 lane_mask = lane_reversal ? PWR_DOWN_LN_1_0(0x3 << 4) :
307 PWR_DOWN_LN_3_2(0xc << 4);
308 break;
309 default:
310 MISSING_CASE(lane_count)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n"
, "lane_count", (long)(lane_count)); __builtin_expect(!!(__ret
), 0); })
;
311 fallthroughdo {} while (0);
312 case 4:
313 lane_mask = PWR_UP_ALL_LANES(0x0 << 4);
314 break;
315 }
316 }
317
318 val = intel_de_read(dev_priv, ICL_PORT_CL_DW10(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 4 * (10))) })
);
319 val &= ~PWR_DOWN_LN_MASK(0xf << 4);
320 val |= lane_mask;
321 intel_de_write(dev_priv, ICL_PORT_CL_DW10(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 4 * (10))) })
, val);
322}
323
324static void icl_combo_phys_init(struct drm_i915_privateinteldrm_softc *dev_priv)
325{
326 enum phy phy;
327
328 for_each_combo_phy(dev_priv, phy)for ((phy) = PHY_A; (phy) < I915_MAX_PHYS; (phy)++) if (!(
intel_phy_is_combo(dev_priv, phy))) {} else
{
329 u32 val;
330
331 if (icl_combo_phy_verify_state(dev_priv, phy)) {
332 drm_dbg(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_DRIVER, "Combo PHY %c already enabled, won't reprogram it.\n"
, ((phy) + 'A'))
333 "Combo PHY %c already enabled, won't reprogram it.\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_DRIVER, "Combo PHY %c already enabled, won't reprogram it.\n"
, ((phy) + 'A'))
334 phy_name(phy))__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_DRIVER, "Combo PHY %c already enabled, won't reprogram it.\n"
, ((phy) + 'A'))
;
335 continue;
336 }
337
338 if (!has_phy_misc(dev_priv, phy))
339 goto skip_phy_misc;
340
341 /*
342 * EHL's combo PHY A can be hooked up to either an external
343 * display (via DDI-D) or an internal display (via DDI-A or
344 * the DSI DPHY). This is a motherboard design decision that
345 * can't be changed on the fly, so initialize the PHY's mux
346 * based on whether our VBT indicates the presence of any
347 * "internal" child devices.
348 */
349 val = intel_de_read(dev_priv, ICL_PHY_MISC(phy)((const i915_reg_t){ .reg = (((0x64C00) + (phy) * ((0x64C04) -
(0x64C00)))) })
);
350 if (IS_JSL_EHL(dev_priv)(IS_PLATFORM(dev_priv, INTEL_JASPERLAKE) || IS_PLATFORM(dev_priv
, INTEL_ELKHARTLAKE))
&& phy == PHY_A) {
351 val &= ~ICL_PHY_MISC_MUX_DDID(1 << 28);
352
353 if (ehl_vbt_ddi_d_present(dev_priv))
354 val |= ICL_PHY_MISC_MUX_DDID(1 << 28);
355 }
356
357 val &= ~ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN(1 << 23);
358 intel_de_write(dev_priv, ICL_PHY_MISC(phy)((const i915_reg_t){ .reg = (((0x64C00) + (phy) * ((0x64C04) -
(0x64C00)))) })
, val);
359
360skip_phy_misc:
361 if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 12) {
362 val = intel_de_read(dev_priv, ICL_PORT_TX_DW8_LN(0, phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + (0x880 + (0) * 0x100
) + 4 * (8))) })
);
363 val &= ~ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_MASK((u32)((((~0UL) >> (64 - (30) - 1)) & ((~0UL) <<
(29))) + 0))
;
364 val |= ICL_PORT_TX_DW8_ODCC_CLK_SEL((u32)((1UL << (31)) + 0));
365 val |= ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_DIV2((u32)((((typeof(((u32)((((~0UL) >> (64 - (30) - 1)) &
((~0UL) << (29))) + 0))))(0x1) << (__builtin_ffsll
(((u32)((((~0UL) >> (64 - (30) - 1)) & ((~0UL) <<
(29))) + 0))) - 1)) & (((u32)((((~0UL) >> (64 - (30
) - 1)) & ((~0UL) << (29))) + 0)))) + 0 + 0 + 0 + 0
))
;
366 intel_de_write(dev_priv, ICL_PORT_TX_DW8_GRP(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x680 + 4 * (8))) }
)
, val);
367
368 val = intel_de_read(dev_priv, ICL_PORT_PCS_DW1_LN(0, phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + (0x800 + (0) * 0x100
) + 4 * (1))) })
);
369 val &= ~DCC_MODE_SELECT_MASK(0x3 << 20);
370 val |= DCC_MODE_SELECT_CONTINUOSLY(0x3 << 20);
371 intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x600 + 4 * (1))) }
)
, val);
372 }
373
374 icl_set_procmon_ref_values(dev_priv, phy);
375
376 if (phy_is_master(dev_priv, phy)) {
377 val = intel_de_read(dev_priv, ICL_PORT_COMP_DW8(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (8))) }
)
);
378 val |= IREFGEN(1 << 24);
379 intel_de_write(dev_priv, ICL_PORT_COMP_DW8(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (8))) }
)
, val);
380 }
381
382 val = intel_de_read(dev_priv, ICL_PORT_COMP_DW0(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (0))) }
)
);
383 val |= COMP_INIT(1 << 31);
384 intel_de_write(dev_priv, ICL_PORT_COMP_DW0(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (0))) }
)
, val);
385
386 val = intel_de_read(dev_priv, ICL_PORT_CL_DW5(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 4 * (5))) })
);
387 val |= CL_POWER_DOWN_ENABLE(1 << 4);
388 intel_de_write(dev_priv, ICL_PORT_CL_DW5(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 4 * (5))) })
, val);
389 }
390}
391
392static void icl_combo_phys_uninit(struct drm_i915_privateinteldrm_softc *dev_priv)
393{
394 enum phy phy;
395
396 for_each_combo_phy_reverse(dev_priv, phy)for ((phy) = I915_MAX_PHYS; (phy)-- > PHY_A;) if (!(intel_phy_is_combo
(dev_priv, phy))) {} else
{
2
The value 8 is assigned to 'phy'
3
Loop condition is true. Entering loop body
4
Assuming the condition is false
5
Taking false branch
397 u32 val;
398
399 if (phy
5.1
'phy' is not equal to PHY_A
== PHY_A &&
400 !icl_combo_phy_verify_state(dev_priv, phy)) {
401 if (IS_TIGERLAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_TIGERLAKE) || IS_DG1(dev_priv)IS_PLATFORM(dev_priv, INTEL_DG1)) {
402 /*
403 * A known problem with old ifwi:
404 * https://gitlab.freedesktop.org/drm/intel/-/issues/2411
405 * Suppress the warning for CI. Remove ASAP!
406 */
407 drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Combo PHY %c HW state changed unexpectedly\n"
, ((phy) + 'A'))
408 "Combo PHY %c HW state changed unexpectedly\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Combo PHY %c HW state changed unexpectedly\n"
, ((phy) + 'A'))
409 phy_name(phy))__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Combo PHY %c HW state changed unexpectedly\n"
, ((phy) + 'A'))
;
410 } else {
411 drm_warn(&dev_priv->drm,printf("drm:pid%d:%s *WARNING* " "[drm] " "Combo PHY %c HW state changed unexpectedly\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__ , ((phy)
+ 'A'))
412 "Combo PHY %c HW state changed unexpectedly\n",printf("drm:pid%d:%s *WARNING* " "[drm] " "Combo PHY %c HW state changed unexpectedly\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__ , ((phy)
+ 'A'))
413 phy_name(phy))printf("drm:pid%d:%s *WARNING* " "[drm] " "Combo PHY %c HW state changed unexpectedly\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__ , ((phy)
+ 'A'))
;
414 }
415 }
416
417 if (!has_phy_misc(dev_priv, phy))
6
Taking true branch
418 goto skip_phy_misc;
7
Control jumps to line 425
419
420 val = intel_de_read(dev_priv, ICL_PHY_MISC(phy)((const i915_reg_t){ .reg = (((0x64C00) + (phy) * ((0x64C04) -
(0x64C00)))) })
);
421 val |= ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN(1 << 23);
422 intel_de_write(dev_priv, ICL_PHY_MISC(phy)((const i915_reg_t){ .reg = (((0x64C00) + (phy) * ((0x64C04) -
(0x64C00)))) })
, val);
423
424skip_phy_misc:
425 val = intel_de_read(dev_priv, ICL_PORT_COMP_DW0(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (0))) }
)
);
8
The left operand of '+' is a garbage value due to array index out of bounds
426 val &= ~COMP_INIT(1 << 31);
427 intel_de_write(dev_priv, ICL_PORT_COMP_DW0(phy)((const i915_reg_t){ .reg = (((((const u32 []){ 0x162000, 0x6C000
, 0x160000, 0x161000, 0x16B000 })[phy]) + 0x100 + 4 * (0))) }
)
, val);
428 }
429}
430
431void intel_combo_phy_init(struct drm_i915_privateinteldrm_softc *i915)
432{
433 icl_combo_phys_init(i915);
434}
435
436void intel_combo_phy_uninit(struct drm_i915_privateinteldrm_softc *i915)
437{
438 icl_combo_phys_uninit(i915);
1
Calling 'icl_combo_phys_uninit'
439}