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