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