Bug Summary

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