File: | dev/pci/drm/i915/display/intel_lspcon.c |
Warning: | line 516, column 27 Value stored to 'i915' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright © 2016 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 |
21 | * DEALINGS IN THE SOFTWARE. |
22 | * |
23 | * |
24 | */ |
25 | |
26 | #include <drm/display/drm_dp_dual_mode_helper.h> |
27 | #include <drm/display/drm_hdmi_helper.h> |
28 | #include <drm/drm_atomic_helper.h> |
29 | #include <drm/drm_edid.h> |
30 | |
31 | #include "intel_de.h" |
32 | #include "intel_display_types.h" |
33 | #include "intel_dp.h" |
34 | #include "intel_lspcon.h" |
35 | #include "intel_hdmi.h" |
36 | |
37 | /* LSPCON OUI Vendor ID(signatures) */ |
38 | #define LSPCON_VENDOR_PARADE_OUI0x001CF8 0x001CF8 |
39 | #define LSPCON_VENDOR_MCA_OUI0x0060AD 0x0060AD |
40 | |
41 | #define DPCD_MCA_LSPCON_HDR_STATUS0x70003 0x70003 |
42 | #define DPCD_PARADE_LSPCON_HDR_STATUS0x00511 0x00511 |
43 | |
44 | /* AUX addresses to write MCA AVI IF */ |
45 | #define LSPCON_MCA_AVI_IF_WRITE_OFFSET0x5C0 0x5C0 |
46 | #define LSPCON_MCA_AVI_IF_CTRL0x5DF 0x5DF |
47 | #define LSPCON_MCA_AVI_IF_KICKOFF(1 << 0) (1 << 0) |
48 | #define LSPCON_MCA_AVI_IF_HANDLED(1 << 1) (1 << 1) |
49 | |
50 | /* AUX addresses to write Parade AVI IF */ |
51 | #define LSPCON_PARADE_AVI_IF_WRITE_OFFSET0x516 0x516 |
52 | #define LSPCON_PARADE_AVI_IF_CTRL0x51E 0x51E |
53 | #define LSPCON_PARADE_AVI_IF_KICKOFF(1 << 7) (1 << 7) |
54 | #define LSPCON_PARADE_AVI_IF_DATA_SIZE32 32 |
55 | |
56 | static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon) |
57 | { |
58 | struct intel_digital_port *dig_port = |
59 | container_of(lspcon, struct intel_digital_port, lspcon)({ const __typeof( ((struct intel_digital_port *)0)->lspcon ) *__mptr = (lspcon); (struct intel_digital_port *)( (char * )__mptr - __builtin_offsetof(struct intel_digital_port, lspcon ) );}); |
60 | |
61 | return &dig_port->dp; |
62 | } |
63 | |
64 | static const char *lspcon_mode_name(enum drm_lspcon_mode mode) |
65 | { |
66 | switch (mode) { |
67 | case DRM_LSPCON_MODE_PCON: |
68 | return "PCON"; |
69 | case DRM_LSPCON_MODE_LS: |
70 | return "LS"; |
71 | case DRM_LSPCON_MODE_INVALID: |
72 | return "INVALID"; |
73 | default: |
74 | MISSING_CASE(mode)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "mode", (long)(mode)); __builtin_expect(!!(__ret), 0); }); |
75 | return "INVALID"; |
76 | } |
77 | } |
78 | |
79 | static bool_Bool lspcon_detect_vendor(struct intel_lspcon *lspcon) |
80 | { |
81 | struct intel_dp *dp = lspcon_to_intel_dp(lspcon); |
82 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(dp)to_i915(dp_to_dig_port(dp)->base.base.dev); |
83 | struct drm_dp_dpcd_ident *ident; |
84 | u32 vendor_oui; |
85 | |
86 | if (drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd))) { |
87 | drm_err(&i915->drm, "Can't read description\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Can't read description\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__); |
88 | return false0; |
89 | } |
90 | |
91 | ident = &dp->desc.ident; |
92 | vendor_oui = (ident->oui[0] << 16) | (ident->oui[1] << 8) | |
93 | ident->oui[2]; |
94 | |
95 | switch (vendor_oui) { |
96 | case LSPCON_VENDOR_MCA_OUI0x0060AD: |
97 | lspcon->vendor = LSPCON_VENDOR_MCA; |
98 | drm_dbg_kms(&i915->drm, "Vendor: Mega Chips\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Vendor: Mega Chips\n" ); |
99 | break; |
100 | |
101 | case LSPCON_VENDOR_PARADE_OUI0x001CF8: |
102 | lspcon->vendor = LSPCON_VENDOR_PARADE; |
103 | drm_dbg_kms(&i915->drm, "Vendor: Parade Tech\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Vendor: Parade Tech\n" ); |
104 | break; |
105 | |
106 | default: |
107 | drm_err(&i915->drm, "Invalid/Unknown vendor OUI\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid/Unknown vendor OUI\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__); |
108 | return false0; |
109 | } |
110 | |
111 | return true1; |
112 | } |
113 | |
114 | static u32 get_hdr_status_reg(struct intel_lspcon *lspcon) |
115 | { |
116 | if (lspcon->vendor == LSPCON_VENDOR_MCA) |
117 | return DPCD_MCA_LSPCON_HDR_STATUS0x70003; |
118 | else |
119 | return DPCD_PARADE_LSPCON_HDR_STATUS0x00511; |
120 | } |
121 | |
122 | void lspcon_detect_hdr_capability(struct intel_lspcon *lspcon) |
123 | { |
124 | struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); |
125 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(intel_dp)to_i915(dp_to_dig_port(intel_dp)->base.base.dev); |
126 | u8 hdr_caps; |
127 | int ret; |
128 | |
129 | ret = drm_dp_dpcd_read(&intel_dp->aux, get_hdr_status_reg(lspcon), |
130 | &hdr_caps, 1); |
131 | |
132 | if (ret < 0) { |
133 | drm_dbg_kms(&i915->drm, "HDR capability detection failed\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "HDR capability detection failed\n" ); |
134 | lspcon->hdr_supported = false0; |
135 | } else if (hdr_caps & 0x1) { |
136 | drm_dbg_kms(&i915->drm, "LSPCON capable of HDR\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "LSPCON capable of HDR\n" ); |
137 | lspcon->hdr_supported = true1; |
138 | } |
139 | } |
140 | |
141 | static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon) |
142 | { |
143 | struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); |
144 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(intel_dp)to_i915(dp_to_dig_port(intel_dp)->base.base.dev); |
145 | enum drm_lspcon_mode current_mode; |
146 | struct i2c_adapter *adapter = &intel_dp->aux.ddc; |
147 | |
148 | if (drm_lspcon_get_mode(intel_dp->aux.drm_dev, adapter, ¤t_mode)) { |
149 | drm_dbg_kms(&i915->drm, "Error reading LSPCON mode\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Error reading LSPCON mode\n" ); |
150 | return DRM_LSPCON_MODE_INVALID; |
151 | } |
152 | return current_mode; |
153 | } |
154 | |
155 | static enum drm_lspcon_mode lspcon_wait_mode(struct intel_lspcon *lspcon, |
156 | enum drm_lspcon_mode mode) |
157 | { |
158 | struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); |
159 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(intel_dp)to_i915(dp_to_dig_port(intel_dp)->base.base.dev); |
160 | enum drm_lspcon_mode current_mode; |
161 | |
162 | current_mode = lspcon_get_current_mode(lspcon); |
163 | if (current_mode == mode) |
164 | goto out; |
165 | |
166 | drm_dbg_kms(&i915->drm, "Waiting for LSPCON mode %s to settle\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Waiting for LSPCON mode %s to settle\n" , lspcon_mode_name(mode)) |
167 | lspcon_mode_name(mode))__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Waiting for LSPCON mode %s to settle\n" , lspcon_mode_name(mode)); |
168 | |
169 | wait_for((current_mode = lspcon_get_current_mode(lspcon)) == mode, 400)({ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (((400) * 1000))); long wait__ = ((10)); int ret__; assertwaitok (); for (;;) { const _Bool expired__ = ktime_after(ktime_get_raw (), end__); ; __asm volatile("" : : : "memory"); if ((((current_mode = lspcon_get_current_mode(lspcon)) == mode))) { ret__ = 0; break ; } if (expired__) { ret__ = -60; break; } usleep_range(wait__ , wait__ * 2); if (wait__ < ((1000))) wait__ <<= 1; } ret__; }); |
170 | if (current_mode != mode) |
171 | drm_err(&i915->drm, "LSPCON mode hasn't settled\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "LSPCON mode hasn't settled\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__); |
172 | |
173 | out: |
174 | drm_dbg_kms(&i915->drm, "Current LSPCON mode %s\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Current LSPCON mode %s\n" , lspcon_mode_name(current_mode)) |
175 | lspcon_mode_name(current_mode))__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Current LSPCON mode %s\n" , lspcon_mode_name(current_mode)); |
176 | |
177 | return current_mode; |
178 | } |
179 | |
180 | static int lspcon_change_mode(struct intel_lspcon *lspcon, |
181 | enum drm_lspcon_mode mode) |
182 | { |
183 | struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); |
184 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(intel_dp)to_i915(dp_to_dig_port(intel_dp)->base.base.dev); |
185 | int err; |
186 | enum drm_lspcon_mode current_mode; |
187 | struct i2c_adapter *adapter = &intel_dp->aux.ddc; |
188 | |
189 | err = drm_lspcon_get_mode(intel_dp->aux.drm_dev, adapter, ¤t_mode); |
190 | if (err) { |
191 | drm_err(&i915->drm, "Error reading LSPCON mode\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Error reading LSPCON mode\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__); |
192 | return err; |
193 | } |
194 | |
195 | if (current_mode == mode) { |
196 | drm_dbg_kms(&i915->drm, "Current mode = desired LSPCON mode\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Current mode = desired LSPCON mode\n" ); |
197 | return 0; |
198 | } |
199 | |
200 | err = drm_lspcon_set_mode(intel_dp->aux.drm_dev, adapter, mode); |
201 | if (err < 0) { |
202 | drm_err(&i915->drm, "LSPCON mode change failed\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "LSPCON mode change failed\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__); |
203 | return err; |
204 | } |
205 | |
206 | lspcon->mode = mode; |
207 | drm_dbg_kms(&i915->drm, "LSPCON mode changed done\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "LSPCON mode changed done\n" ); |
208 | return 0; |
209 | } |
210 | |
211 | static bool_Bool lspcon_wake_native_aux_ch(struct intel_lspcon *lspcon) |
212 | { |
213 | struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); |
214 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(intel_dp)to_i915(dp_to_dig_port(intel_dp)->base.base.dev); |
215 | u8 rev; |
216 | |
217 | if (drm_dp_dpcd_readb(&lspcon_to_intel_dp(lspcon)->aux, DP_DPCD_REV0x000, |
218 | &rev) != 1) { |
219 | drm_dbg_kms(&i915->drm, "Native AUX CH down\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Native AUX CH down\n" ); |
220 | return false0; |
221 | } |
222 | |
223 | drm_dbg_kms(&i915->drm, "Native AUX CH up, DPCD version: %d.%d\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Native AUX CH up, DPCD version: %d.%d\n" , rev >> 4, rev & 0xf) |
224 | rev >> 4, rev & 0xf)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Native AUX CH up, DPCD version: %d.%d\n" , rev >> 4, rev & 0xf); |
225 | |
226 | return true1; |
227 | } |
228 | |
229 | static bool_Bool lspcon_probe(struct intel_lspcon *lspcon) |
230 | { |
231 | int retry; |
232 | enum drm_dp_dual_mode_type adaptor_type; |
233 | struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); |
234 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(intel_dp)to_i915(dp_to_dig_port(intel_dp)->base.base.dev); |
235 | struct i2c_adapter *adapter = &intel_dp->aux.ddc; |
236 | enum drm_lspcon_mode expected_mode; |
237 | |
238 | expected_mode = lspcon_wake_native_aux_ch(lspcon) ? |
239 | DRM_LSPCON_MODE_PCON : DRM_LSPCON_MODE_LS; |
240 | |
241 | /* Lets probe the adaptor and check its type */ |
242 | for (retry = 0; retry < 6; retry++) { |
243 | if (retry) |
244 | usleep_range(500, 1000); |
245 | |
246 | adaptor_type = drm_dp_dual_mode_detect(intel_dp->aux.drm_dev, adapter); |
247 | if (adaptor_type == DRM_DP_DUAL_MODE_LSPCON) |
248 | break; |
249 | } |
250 | |
251 | if (adaptor_type != DRM_DP_DUAL_MODE_LSPCON) { |
252 | drm_dbg_kms(&i915->drm, "No LSPCON detected, found %s\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "No LSPCON detected, found %s\n" , drm_dp_get_dual_mode_type_name(adaptor_type)) |
253 | drm_dp_get_dual_mode_type_name(adaptor_type))__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "No LSPCON detected, found %s\n" , drm_dp_get_dual_mode_type_name(adaptor_type)); |
254 | return false0; |
255 | } |
256 | |
257 | /* Yay ... got a LSPCON device */ |
258 | drm_dbg_kms(&i915->drm, "LSPCON detected\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "LSPCON detected\n"); |
259 | lspcon->mode = lspcon_wait_mode(lspcon, expected_mode); |
260 | |
261 | /* |
262 | * In the SW state machine, lets Put LSPCON in PCON mode only. |
263 | * In this way, it will work with both HDMI 1.4 sinks as well as HDMI |
264 | * 2.0 sinks. |
265 | */ |
266 | if (lspcon->mode != DRM_LSPCON_MODE_PCON) { |
267 | if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON) < 0) { |
268 | drm_err(&i915->drm, "LSPCON mode change to PCON failed\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "LSPCON mode change to PCON failed\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__); |
269 | return false0; |
270 | } |
271 | } |
272 | return true1; |
273 | } |
274 | |
275 | static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon) |
276 | { |
277 | struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); |
278 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(intel_dp)to_i915(dp_to_dig_port(intel_dp)->base.base.dev); |
279 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
280 | unsigned long start = jiffies; |
281 | |
282 | while (1) { |
283 | if (intel_digital_port_connected(&dig_port->base)) { |
284 | drm_dbg_kms(&i915->drm, "LSPCON recovering in PCON mode after %u ms\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "LSPCON recovering in PCON mode after %u ms\n" , jiffies_to_msecs(jiffies - start)) |
285 | jiffies_to_msecs(jiffies - start))__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "LSPCON recovering in PCON mode after %u ms\n" , jiffies_to_msecs(jiffies - start)); |
286 | return; |
287 | } |
288 | |
289 | if (time_after(jiffies, start + msecs_to_jiffies(1000)(((uint64_t)(1000)) * hz / 1000))) |
290 | break; |
291 | |
292 | usleep_range(10000, 15000); |
293 | } |
294 | |
295 | drm_dbg_kms(&i915->drm, "LSPCON DP descriptor mismatch after resume\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "LSPCON DP descriptor mismatch after resume\n" ); |
296 | } |
297 | |
298 | static bool_Bool lspcon_parade_fw_ready(struct drm_dp_aux *aux) |
299 | { |
300 | u8 avi_if_ctrl; |
301 | u8 retry; |
302 | ssize_t ret; |
303 | |
304 | /* Check if LSPCON FW is ready for data */ |
305 | for (retry = 0; retry < 5; retry++) { |
306 | if (retry) |
307 | usleep_range(200, 300); |
308 | |
309 | ret = drm_dp_dpcd_read(aux, LSPCON_PARADE_AVI_IF_CTRL0x51E, |
310 | &avi_if_ctrl, 1); |
311 | if (ret < 0) { |
312 | drm_err(aux->drm_dev, "Failed to read AVI IF control\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to read AVI IF control\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__); |
313 | return false0; |
314 | } |
315 | |
316 | if ((avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF(1 << 7)) == 0) |
317 | return true1; |
318 | } |
319 | |
320 | drm_err(aux->drm_dev, "Parade FW not ready to accept AVI IF\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Parade FW not ready to accept AVI IF\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__); |
321 | return false0; |
322 | } |
323 | |
324 | static bool_Bool _lspcon_parade_write_infoframe_blocks(struct drm_dp_aux *aux, |
325 | u8 *avi_buf) |
326 | { |
327 | u8 avi_if_ctrl; |
328 | u8 block_count = 0; |
329 | u8 *data; |
330 | u16 reg; |
331 | ssize_t ret; |
332 | |
333 | while (block_count < 4) { |
334 | if (!lspcon_parade_fw_ready(aux)) { |
335 | drm_dbg_kms(aux->drm_dev, "LSPCON FW not ready, block %d\n",__drm_dev_dbg(((void *)0), (aux->drm_dev) ? (aux->drm_dev )->dev : ((void *)0), DRM_UT_KMS, "LSPCON FW not ready, block %d\n" , block_count) |
336 | block_count)__drm_dev_dbg(((void *)0), (aux->drm_dev) ? (aux->drm_dev )->dev : ((void *)0), DRM_UT_KMS, "LSPCON FW not ready, block %d\n" , block_count); |
337 | return false0; |
338 | } |
339 | |
340 | reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET0x516; |
341 | data = avi_buf + block_count * 8; |
342 | ret = drm_dp_dpcd_write(aux, reg, data, 8); |
343 | if (ret < 0) { |
344 | drm_err(aux->drm_dev, "Failed to write AVI IF block %d\n",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to write AVI IF block %d\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__ , block_count ) |
345 | block_count)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to write AVI IF block %d\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__ , block_count ); |
346 | return false0; |
347 | } |
348 | |
349 | /* |
350 | * Once a block of data is written, we have to inform the FW |
351 | * about this by writing into avi infoframe control register: |
352 | * - set the kickoff bit[7] to 1 |
353 | * - write the block no. to bits[1:0] |
354 | */ |
355 | reg = LSPCON_PARADE_AVI_IF_CTRL0x51E; |
356 | avi_if_ctrl = LSPCON_PARADE_AVI_IF_KICKOFF(1 << 7) | block_count; |
357 | ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1); |
358 | if (ret < 0) { |
359 | drm_err(aux->drm_dev, "Failed to update (0x%x), block %d\n",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to update (0x%x), block %d\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__ , reg, block_count ) |
360 | reg, block_count)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to update (0x%x), block %d\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__ , reg, block_count ); |
361 | return false0; |
362 | } |
363 | |
364 | block_count++; |
365 | } |
366 | |
367 | drm_dbg_kms(aux->drm_dev, "Wrote AVI IF blocks successfully\n")__drm_dev_dbg(((void *)0), (aux->drm_dev) ? (aux->drm_dev )->dev : ((void *)0), DRM_UT_KMS, "Wrote AVI IF blocks successfully\n" ); |
368 | return true1; |
369 | } |
370 | |
371 | static bool_Bool _lspcon_write_avi_infoframe_parade(struct drm_dp_aux *aux, |
372 | const u8 *frame, |
373 | ssize_t len) |
374 | { |
375 | u8 avi_if[LSPCON_PARADE_AVI_IF_DATA_SIZE32] = {1, }; |
376 | |
377 | /* |
378 | * Parade's frames contains 32 bytes of data, divided |
379 | * into 4 frames: |
380 | * Token byte (first byte of first frame, must be non-zero) |
381 | * HB0 to HB2 from AVI IF (3 bytes header) |
382 | * PB0 to PB27 from AVI IF (28 bytes data) |
383 | * So it should look like this |
384 | * first block: | <token> <HB0-HB2> <DB0-DB3> | |
385 | * next 3 blocks: |<DB4-DB11>|<DB12-DB19>|<DB20-DB28>| |
386 | */ |
387 | |
388 | if (len > LSPCON_PARADE_AVI_IF_DATA_SIZE32 - 1) { |
389 | drm_err(aux->drm_dev, "Invalid length of infoframes\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid length of infoframes\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__); |
390 | return false0; |
391 | } |
392 | |
393 | memcpy(&avi_if[1], frame, len)__builtin_memcpy((&avi_if[1]), (frame), (len)); |
394 | |
395 | if (!_lspcon_parade_write_infoframe_blocks(aux, avi_if)) { |
396 | drm_dbg_kms(aux->drm_dev, "Failed to write infoframe blocks\n")__drm_dev_dbg(((void *)0), (aux->drm_dev) ? (aux->drm_dev )->dev : ((void *)0), DRM_UT_KMS, "Failed to write infoframe blocks\n" ); |
397 | return false0; |
398 | } |
399 | |
400 | return true1; |
401 | } |
402 | |
403 | static bool_Bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, |
404 | const u8 *buffer, ssize_t len) |
405 | { |
406 | int ret; |
407 | u32 val = 0; |
408 | u32 retry; |
409 | u16 reg; |
410 | const u8 *data = buffer; |
411 | |
412 | reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET0x5C0; |
413 | while (val < len) { |
414 | /* DPCD write for AVI IF can fail on a slow FW day, so retry */ |
415 | for (retry = 0; retry < 5; retry++) { |
416 | ret = drm_dp_dpcd_write(aux, reg, (void *)data, 1); |
417 | if (ret == 1) { |
418 | break; |
419 | } else if (retry < 4) { |
420 | mdelay(50); |
421 | continue; |
422 | } else { |
423 | drm_err(aux->drm_dev, "DPCD write failed at:0x%x\n", reg)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DPCD write failed at:0x%x\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__ , reg); |
424 | return false0; |
425 | } |
426 | } |
427 | val++; reg++; data++; |
428 | } |
429 | |
430 | val = 0; |
431 | reg = LSPCON_MCA_AVI_IF_CTRL0x5DF; |
432 | ret = drm_dp_dpcd_read(aux, reg, &val, 1); |
433 | if (ret < 0) { |
434 | drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DPCD read failed, address 0x%x\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__ , reg); |
435 | return false0; |
436 | } |
437 | |
438 | /* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */ |
439 | val &= ~LSPCON_MCA_AVI_IF_HANDLED(1 << 1); |
440 | val |= LSPCON_MCA_AVI_IF_KICKOFF(1 << 0); |
441 | |
442 | ret = drm_dp_dpcd_write(aux, reg, &val, 1); |
443 | if (ret < 0) { |
444 | drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DPCD read failed, address 0x%x\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__ , reg); |
445 | return false0; |
446 | } |
447 | |
448 | val = 0; |
449 | ret = drm_dp_dpcd_read(aux, reg, &val, 1); |
450 | if (ret < 0) { |
451 | drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DPCD read failed, address 0x%x\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__ , reg); |
452 | return false0; |
453 | } |
454 | |
455 | if (val == LSPCON_MCA_AVI_IF_HANDLED(1 << 1)) |
456 | drm_dbg_kms(aux->drm_dev, "AVI IF handled by FW\n")__drm_dev_dbg(((void *)0), (aux->drm_dev) ? (aux->drm_dev )->dev : ((void *)0), DRM_UT_KMS, "AVI IF handled by FW\n" ); |
457 | |
458 | return true1; |
459 | } |
460 | |
461 | void lspcon_write_infoframe(struct intel_encoder *encoder, |
462 | const struct intel_crtc_state *crtc_state, |
463 | unsigned int type, |
464 | const void *frame, ssize_t len) |
465 | { |
466 | bool_Bool ret = true1; |
467 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
468 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(intel_dp)to_i915(dp_to_dig_port(intel_dp)->base.base.dev); |
469 | struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder); |
470 | |
471 | switch (type) { |
472 | case HDMI_INFOFRAME_TYPE_AVI: |
473 | if (lspcon->vendor == LSPCON_VENDOR_MCA) |
474 | ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux, |
475 | frame, len); |
476 | else |
477 | ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux, |
478 | frame, len); |
479 | break; |
480 | case HDMI_PACKET_TYPE_GAMUT_METADATA: |
481 | drm_dbg_kms(&i915->drm, "Update HDR metadata for lspcon\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Update HDR metadata for lspcon\n" ); |
482 | /* It uses the legacy hsw implementation for the same */ |
483 | hsw_write_infoframe(encoder, crtc_state, type, frame, len); |
484 | break; |
485 | default: |
486 | return; |
487 | } |
488 | |
489 | if (!ret) { |
490 | drm_err(&i915->drm, "Failed to write infoframes\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to write infoframes\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__); |
491 | return; |
492 | } |
493 | } |
494 | |
495 | void lspcon_read_infoframe(struct intel_encoder *encoder, |
496 | const struct intel_crtc_state *crtc_state, |
497 | unsigned int type, |
498 | void *frame, ssize_t len) |
499 | { |
500 | /* FIXME implement for AVI Infoframe as well */ |
501 | if (type == HDMI_PACKET_TYPE_GAMUT_METADATA) |
502 | hsw_read_infoframe(encoder, crtc_state, type, |
503 | frame, len); |
504 | } |
505 | |
506 | void lspcon_set_infoframes(struct intel_encoder *encoder, |
507 | bool_Bool enable, |
508 | const struct intel_crtc_state *crtc_state, |
509 | const struct drm_connector_state *conn_state) |
510 | { |
511 | ssize_t ret; |
512 | union hdmi_infoframe frame; |
513 | u8 buf[VIDEO_DIP_DATA_SIZE32]; |
514 | struct intel_digital_port *dig_port = enc_to_dig_port(encoder); |
515 | struct intel_lspcon *lspcon = &dig_port->lspcon; |
516 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(encoder->base.dev); |
Value stored to 'i915' during its initialization is never read | |
517 | const struct drm_display_mode *adjusted_mode = |
518 | &crtc_state->hw.adjusted_mode; |
519 | |
520 | if (!lspcon->active) { |
521 | drm_err(&i915->drm, "Writing infoframes while LSPCON disabled ?\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Writing infoframes while LSPCON disabled ?\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__); |
522 | return; |
523 | } |
524 | |
525 | /* FIXME precompute infoframes */ |
526 | |
527 | ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, |
528 | conn_state->connector, |
529 | adjusted_mode); |
530 | if (ret < 0) { |
531 | drm_err(&i915->drm, "couldn't fill AVI infoframe\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "couldn't fill AVI infoframe\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__); |
532 | return; |
533 | } |
534 | |
535 | /* |
536 | * Currently there is no interface defined to |
537 | * check user preference between RGB/YCBCR444 |
538 | * or YCBCR420. So the only possible case for |
539 | * YCBCR444 usage is driving YCBCR420 output |
540 | * with LSPCON, when pipe is configured for |
541 | * YCBCR444 output and LSPCON takes care of |
542 | * downsampling it. |
543 | */ |
544 | if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) |
545 | frame.avi.colorspace = HDMI_COLORSPACE_YUV420; |
546 | else |
547 | frame.avi.colorspace = HDMI_COLORSPACE_RGB; |
548 | |
549 | /* Set the Colorspace as per the HDMI spec */ |
550 | drm_hdmi_avi_infoframe_colorimetry(&frame.avi, conn_state); |
551 | |
552 | /* nonsense combination */ |
553 | drm_WARN_ON(encoder->base.dev, crtc_state->limited_color_range &&({ int __ret = !!((crtc_state->limited_color_range && crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((encoder-> base.dev))->dev), "", "drm_WARN_ON(" "crtc_state->limited_color_range && crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB" ")"); __builtin_expect(!!(__ret), 0); }) |
554 | crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)({ int __ret = !!((crtc_state->limited_color_range && crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((encoder-> base.dev))->dev), "", "drm_WARN_ON(" "crtc_state->limited_color_range && crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB" ")"); __builtin_expect(!!(__ret), 0); }); |
555 | |
556 | if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_RGB) { |
557 | drm_hdmi_avi_infoframe_quant_range(&frame.avi, |
558 | conn_state->connector, |
559 | adjusted_mode, |
560 | crtc_state->limited_color_range ? |
561 | HDMI_QUANTIZATION_RANGE_LIMITED : |
562 | HDMI_QUANTIZATION_RANGE_FULL); |
563 | } else { |
564 | frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT; |
565 | frame.avi.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; |
566 | } |
567 | |
568 | drm_hdmi_avi_infoframe_content_type(&frame.avi, conn_state); |
569 | |
570 | ret = hdmi_infoframe_pack(&frame, buf, sizeof(buf)); |
571 | if (ret < 0) { |
572 | drm_err(&i915->drm, "Failed to pack AVI IF\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to pack AVI IF\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__); |
573 | return; |
574 | } |
575 | |
576 | dig_port->write_infoframe(encoder, crtc_state, HDMI_INFOFRAME_TYPE_AVI, |
577 | buf, ret); |
578 | } |
579 | |
580 | static bool_Bool _lspcon_read_avi_infoframe_enabled_mca(struct drm_dp_aux *aux) |
581 | { |
582 | int ret; |
583 | u32 val = 0; |
584 | u16 reg = LSPCON_MCA_AVI_IF_CTRL0x5DF; |
585 | |
586 | ret = drm_dp_dpcd_read(aux, reg, &val, 1); |
587 | if (ret < 0) { |
588 | drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DPCD read failed, address 0x%x\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__ , reg); |
589 | return false0; |
590 | } |
591 | |
592 | return val & LSPCON_MCA_AVI_IF_KICKOFF(1 << 0); |
593 | } |
594 | |
595 | static bool_Bool _lspcon_read_avi_infoframe_enabled_parade(struct drm_dp_aux *aux) |
596 | { |
597 | int ret; |
598 | u32 val = 0; |
599 | u16 reg = LSPCON_PARADE_AVI_IF_CTRL0x51E; |
600 | |
601 | ret = drm_dp_dpcd_read(aux, reg, &val, 1); |
602 | if (ret < 0) { |
603 | drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DPCD read failed, address 0x%x\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__ , reg); |
604 | return false0; |
605 | } |
606 | |
607 | return val & LSPCON_PARADE_AVI_IF_KICKOFF(1 << 7); |
608 | } |
609 | |
610 | u32 lspcon_infoframes_enabled(struct intel_encoder *encoder, |
611 | const struct intel_crtc_state *pipe_config) |
612 | { |
613 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
614 | struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder); |
615 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
616 | bool_Bool infoframes_enabled; |
617 | u32 val = 0; |
618 | u32 mask, tmp; |
619 | |
620 | if (lspcon->vendor == LSPCON_VENDOR_MCA) |
621 | infoframes_enabled = _lspcon_read_avi_infoframe_enabled_mca(&intel_dp->aux); |
622 | else |
623 | infoframes_enabled = _lspcon_read_avi_infoframe_enabled_parade(&intel_dp->aux); |
624 | |
625 | if (infoframes_enabled) |
626 | val |= intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI); |
627 | |
628 | if (lspcon->hdr_supported) { |
629 | tmp = intel_de_read(dev_priv, |
630 | HSW_TVIDEO_DIP_CTL(pipe_config->cpu_transcoder)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(pipe_config->cpu_transcoder)] - (& (dev_priv)->__info)->display.trans_offsets[TRANSCODER_A ] + ((&(dev_priv)->__info)->display.mmio_offset) + ( 0x60200)) })); |
631 | mask = VIDEO_DIP_ENABLE_GMP_HSW(1 << 4); |
632 | |
633 | if (tmp & mask) |
634 | val |= intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA); |
635 | } |
636 | |
637 | return val; |
638 | } |
639 | |
640 | void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon) |
641 | { |
642 | lspcon_wait_mode(lspcon, DRM_LSPCON_MODE_PCON); |
643 | } |
644 | |
645 | bool_Bool lspcon_init(struct intel_digital_port *dig_port) |
646 | { |
647 | struct intel_dp *intel_dp = &dig_port->dp; |
648 | struct intel_lspcon *lspcon = &dig_port->lspcon; |
649 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(intel_dp)to_i915(dp_to_dig_port(intel_dp)->base.base.dev); |
650 | struct drm_connector *connector = &intel_dp->attached_connector->base; |
651 | |
652 | lspcon->active = false0; |
653 | lspcon->mode = DRM_LSPCON_MODE_INVALID; |
654 | |
655 | if (!lspcon_probe(lspcon)) { |
656 | drm_err(&i915->drm, "Failed to probe lspcon\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to probe lspcon\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__); |
657 | return false0; |
658 | } |
659 | |
660 | if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd) != 0) { |
661 | drm_err(&i915->drm, "LSPCON DPCD read failed\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "LSPCON DPCD read failed\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__); |
662 | return false0; |
663 | } |
664 | |
665 | if (!lspcon_detect_vendor(lspcon)) { |
666 | drm_err(&i915->drm, "LSPCON vendor detection failed\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "LSPCON vendor detection failed\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__); |
667 | return false0; |
668 | } |
669 | |
670 | connector->ycbcr_420_allowed = true1; |
671 | lspcon->active = true1; |
672 | drm_dbg_kms(&i915->drm, "Success: LSPCON init\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Success: LSPCON init\n" ); |
673 | return true1; |
674 | } |
675 | |
676 | u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder, |
677 | const struct intel_crtc_state *pipe_config) |
678 | { |
679 | struct intel_digital_port *dig_port = enc_to_dig_port(encoder); |
680 | |
681 | return dig_port->infoframes_enabled(encoder, pipe_config); |
682 | } |
683 | |
684 | void lspcon_resume(struct intel_digital_port *dig_port) |
685 | { |
686 | struct intel_lspcon *lspcon = &dig_port->lspcon; |
687 | struct drm_device *dev = dig_port->base.base.dev; |
688 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dev); |
689 | enum drm_lspcon_mode expected_mode; |
690 | |
691 | if (!intel_bios_is_lspcon_present(i915, dig_port->base.port)) |
692 | return; |
693 | |
694 | if (!lspcon->active) { |
695 | if (!lspcon_init(dig_port)) { |
696 | drm_err(&i915->drm, "LSPCON init failed on port %c\n",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "LSPCON init failed on port %c\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__ , ((dig_port ->base.port) + 'A')) |
697 | port_name(dig_port->base.port))printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "LSPCON init failed on port %c\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__ , ((dig_port ->base.port) + 'A')); |
698 | return; |
699 | } |
700 | } |
701 | |
702 | if (lspcon_wake_native_aux_ch(lspcon)) { |
703 | expected_mode = DRM_LSPCON_MODE_PCON; |
704 | lspcon_resume_in_pcon_wa(lspcon); |
705 | } else { |
706 | expected_mode = DRM_LSPCON_MODE_LS; |
707 | } |
708 | |
709 | if (lspcon_wait_mode(lspcon, expected_mode) == DRM_LSPCON_MODE_PCON) |
710 | return; |
711 | |
712 | if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON)) |
713 | drm_err(&i915->drm, "LSPCON resume failed\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "LSPCON resume failed\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__); |
714 | else |
715 | drm_dbg_kms(&i915->drm, "LSPCON resume success\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "LSPCON resume success\n" ); |
716 | } |