1/*
2 * Copyright 2011-2015, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Alexander von Gluck IV, kallisti5@unixzen.com
7 *		Bill Randle, billr@neocat.org
8 */
9
10
11#include "displayport.h"
12
13#include <Debug.h>
14
15#include "accelerant_protos.h"
16#include "atombios-obsolete.h"
17#include "connector.h"
18#include "mode.h"
19#include "edid.h"
20#include "encoder.h"
21
22
23#undef TRACE
24
25#define TRACE_DP
26#ifdef TRACE_DP
27#   define TRACE(x...) _sPrintf("radeon_hd: " x)
28#else
29#   define TRACE(x...) ;
30#endif
31
32#define ERROR(x...) _sPrintf("radeon_hd: " x)
33
34
35static ssize_t
36dp_aux_speak(uint32 connectorIndex, uint8* send, int sendBytes,
37	uint8* recv, int recvBytes, uint8 delay, uint8* ack)
38{
39	dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
40	if (!dpInfo->valid) {
41		ERROR("%s: cannot speak on invalid dpInfo!\n", __func__);
42		return B_IO_ERROR;
43	}
44
45	int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
46
47	// Build AtomBIOS Transaction
48	union auxChannelTransaction {
49		PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
50		PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
51	};
52	union auxChannelTransaction args;
53	memset(&args, 0, sizeof(args));
54
55	args.v2.lpAuxRequest = B_HOST_TO_LENDIAN_INT16(0 + 4);
56	args.v2.lpDataOut = B_HOST_TO_LENDIAN_INT16(16 + 4);
57	args.v2.ucDataOutLen = 0;
58	args.v2.ucChannelID = dpInfo->auxPin;
59	args.v2.ucDelay = delay / 10;
60
61	// Careful! This value differs in different atombios calls :-|
62	args.v2.ucHPD_ID = connector_pick_atom_hpdid(connectorIndex);
63
64	unsigned char* base = (unsigned char*)(gAtomContext->scratch + 1);
65
66	// TODO: This isn't correct for big endian systems!
67	// send needs to be swapped on big endian.
68	memcpy(base, send, sendBytes);
69
70	atom_execute_table(gAtomContext, index, (uint32*)&args);
71
72	*ack = args.v2.ucReplyStatus;
73
74	switch (args.v2.ucReplyStatus) {
75		case 1:
76			ERROR("%s: dp_aux channel timeout!\n", __func__);
77			return B_TIMED_OUT;
78		case 2:
79			ERROR("%s: dp_aux channel flags not zero!\n", __func__);
80			return B_BUSY;
81		case 3:
82			ERROR("%s: dp_aux channel error!\n", __func__);
83			return B_IO_ERROR;
84	}
85
86	int recvLength = args.v1.ucDataOutLen;
87	if (recvLength > recvBytes)
88		recvLength = recvBytes;
89
90	// TODO: This isn't correct for big endian systems!
91	// recv needs to be swapped on big endian.
92	if (recv && recvBytes)
93		memcpy(recv, base + 16, recvLength);
94
95	return recvLength;
96}
97
98
99status_t
100dp_aux_transaction(uint32 connectorIndex, dp_aux_msg* message)
101{
102	uint8 delay = 0;
103	if (message == NULL) {
104		ERROR("%s: DP message is invalid!\n", __func__);
105		return B_ERROR;
106	}
107
108	if (message->size > 16) {
109		ERROR("%s: Too many bytes! (%" B_PRIuSIZE ")\n", __func__,
110			message->size);
111		return B_ERROR;
112	}
113
114	uint8 transactionSize = 4;
115
116	switch(message->request & ~DP_AUX_I2C_MOT) {
117		case DP_AUX_NATIVE_WRITE:
118		case DP_AUX_I2C_WRITE:
119		case DP_AUX_I2C_WRITE_STATUS_UPDATE:
120			transactionSize += message->size;
121			break;
122	}
123
124	// If not bare address, check for buffer
125	if (message->size > 0 && message->buffer == NULL) {
126		ERROR("%s: DP message uninitalized buffer!\n", __func__);
127		return B_ERROR;
128	}
129
130	uint8 auxMessage[20];
131	auxMessage[0] = message->address & 0xff;
132	auxMessage[1] = (message->address >> 8) & 0xff;
133	auxMessage[2] = (message->request << 4) | ((message->address >> 16) & 0xf);
134	auxMessage[3] = message->size ? (message->size - 1) : 0;
135
136	if (message->size == 0)
137		auxMessage[3] |= 3 << 4;
138	else
139		auxMessage[3] |= transactionSize << 4;
140
141	uint8 retry;
142	for (retry = 0; retry < 7; retry++) {
143		uint8 ack;
144		ssize_t result = B_ERROR;
145		switch(message->request & ~DP_AUX_I2C_MOT) {
146			case DP_AUX_NATIVE_WRITE:
147			case DP_AUX_I2C_WRITE:
148			case DP_AUX_I2C_WRITE_STATUS_UPDATE:
149				memcpy(auxMessage + 4, message->buffer, message->size);
150				result = dp_aux_speak(connectorIndex, auxMessage,
151					transactionSize, NULL, 0, delay, &ack);
152				break;
153			case DP_AUX_NATIVE_READ:
154			case DP_AUX_I2C_READ:
155				result = dp_aux_speak(connectorIndex, auxMessage,
156					transactionSize, (uint8*)message->buffer, message->size,
157					delay, &ack);
158				break;
159			default:
160				ERROR("%s: Unknown dp_aux_msg request!\n", __func__);
161				return B_ERROR;
162		}
163
164		if (result == B_BUSY)
165			continue;
166		else if (result < B_OK)
167			return result;
168
169		ack >>= 4;
170		message->reply = ack;
171		switch(message->reply & DP_AUX_NATIVE_REPLY_MASK) {
172			case DP_AUX_NATIVE_REPLY_ACK:
173				return B_OK;
174			case DP_AUX_NATIVE_REPLY_DEFER:
175				TRACE("%s: aux reply defer received. Snoozing.\n", __func__);
176				snooze(400);
177				break;
178			default:
179				TRACE("%s: aux invalid native reply: 0x%02x\n", __func__,
180					message->reply);
181				return B_IO_ERROR;
182		}
183	}
184
185	ERROR("%s: IO Error. %" B_PRIu8 " attempts\n", __func__, retry);
186	return B_IO_ERROR;
187}
188
189
190void
191dpcd_reg_write(uint32 connectorIndex, uint32 address, uint8 value)
192{
193	//TRACE("%s: connector(%" B_PRId32 "): 0x%" B_PRIx32 " -> 0x%" B_PRIx8 "\n",
194	//	__func__, connectorIndex, address, value);
195	dp_aux_msg message;
196	memset(&message, 0, sizeof(message));
197
198	message.address = address;
199	message.buffer = &value;
200	message.request = DP_AUX_NATIVE_WRITE;
201	message.size = 1;
202
203	status_t result = dp_aux_transaction(connectorIndex, &message);
204	if (result != B_OK) {
205		ERROR("%s: error on DisplayPort aux write (0x%" B_PRIx32 ")\n",
206			__func__, result);
207	}
208}
209
210
211uint8
212dpcd_reg_read(uint32 connectorIndex, uint32 address)
213{
214	//TRACE("%s: connector(%" B_PRId32 "): read 0x%" B_PRIx32 ".\n",
215	//	__func__, connectorIndex, address);
216	uint8 response[3];
217
218	dp_aux_msg message;
219	memset(&message, 0, sizeof(message));
220
221	message.address = address;
222	message.buffer = &response;
223	message.request = DP_AUX_NATIVE_READ;
224	message.size = 1;
225
226	status_t result = dp_aux_transaction(connectorIndex, &message);
227	if (result != B_OK) {
228		ERROR("%s: error on DisplayPort aux read (0x%" B_PRIx32 ")\n",
229			__func__, result);
230	}
231
232	return response[0];
233}
234
235
236status_t
237dp_aux_get_i2c_byte(uint32 connectorIndex, uint32 address, uint8* data,
238	bool start, bool stop)
239{
240	uint8 reply[3];
241	dp_aux_msg message;
242	memset(&message, 0, sizeof(message));
243
244	message.address = address;
245	message.buffer = reply;
246	message.request = DP_AUX_I2C_READ;
247	message.size = 1;
248	if (stop == false) {
249		// Remove Middle-Of-Transmission on final transaction
250		message.request |= DP_AUX_I2C_MOT;
251	}
252	if  (stop || start) {
253		// Bare address packet
254		message.buffer = NULL;
255		message.size = 0;
256	}
257
258	for (int attempt = 0; attempt < 7; attempt++) {
259		status_t result = dp_aux_transaction(connectorIndex, &message);
260		if (result != B_OK) {
261			ERROR("%s: aux_ch transaction failed!\n", __func__);
262			return result;
263		}
264
265		switch (message.reply & DP_AUX_I2C_REPLY_MASK) {
266			case DP_AUX_I2C_REPLY_ACK:
267				*data = reply[0];
268				return B_OK;
269			case DP_AUX_I2C_REPLY_NACK:
270				TRACE("%s: aux i2c nack\n", __func__);
271				return B_IO_ERROR;
272			case DP_AUX_I2C_REPLY_DEFER:
273				TRACE("%s: aux i2c defer\n", __func__);
274				snooze(400);
275				break;
276			default:
277				TRACE("%s: aux invalid I2C reply: 0x%02x\n",
278					__func__, message.reply);
279				return B_ERROR;
280		}
281	}
282	return B_ERROR;
283}
284
285
286status_t
287dp_aux_set_i2c_byte(uint32 connectorIndex, uint32 address, uint8* data,
288	bool start, bool stop)
289{
290	dp_aux_msg message;
291	memset(&message, 0, sizeof(message));
292
293	message.address = address;
294	message.buffer = data;
295	message.request = DP_AUX_I2C_WRITE;
296	message.size = 1;
297	if (stop == false)
298		message.request |= DP_AUX_I2C_MOT;
299	if (stop || start) {
300		message.buffer = NULL;
301		message.size = 0;
302	}
303
304	for (int attempt = 0; attempt < 7; attempt++) {
305		status_t result = dp_aux_transaction(connectorIndex, &message);
306		if (result != B_OK) {
307			ERROR("%s: aux_ch transaction failed!\n", __func__);
308			return result;
309		}
310		switch (message.reply & DP_AUX_I2C_REPLY_MASK) {
311			case DP_AUX_I2C_REPLY_ACK:
312				return B_OK;
313			case DP_AUX_I2C_REPLY_NACK:
314				ERROR("%s: aux i2c nack\n", __func__);
315				return B_IO_ERROR;
316			case DP_AUX_I2C_REPLY_DEFER:
317				TRACE("%s: aux i2c defer\n", __func__);
318				snooze(400);
319				break;
320			default:
321				ERROR("%s: aux invalid I2C reply: 0x%02x\n", __func__,
322					message.reply);
323				return B_IO_ERROR;
324		}
325	}
326
327	return B_ERROR;
328}
329
330
331uint32
332dp_get_encoder_config(uint32 connectorIndex)
333{
334	uint32 result = 0;
335
336	uint32 digEncoderID = encoder_pick_dig(connectorIndex);
337	if (digEncoderID)
338		result |= ATOM_DP_CONFIG_DIG2_ENCODER;
339	else
340		result |= ATOM_DP_CONFIG_DIG1_ENCODER;
341
342	bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
343		== GRAPH_OBJECT_ENUM_ID2 ? true : false;
344	if (linkB)
345		result |= ATOM_DP_CONFIG_LINK_B;
346	else
347		result |= ATOM_DP_CONFIG_LINK_A;
348
349	return result;
350}
351
352
353uint32
354dp_get_lane_count(uint32 connectorIndex, display_mode* mode)
355{
356	size_t pixelChunk;
357	size_t pixelsPerChunk;
358	status_t result = dp_get_pixel_size_for((color_space)mode->space,
359		&pixelChunk, NULL, &pixelsPerChunk);
360
361	if (result != B_OK) {
362		TRACE("%s: Invalid color space!\n", __func__);
363		return 0;
364	}
365
366	uint32 bitsPerPixel = (pixelChunk / pixelsPerChunk) * 8;
367
368	uint32 dpMaxLinkRate
369		= dp_decode_link_rate(dpcd_reg_read(connectorIndex, DP_MAX_LINK_RATE));
370	uint32 dpMaxLaneCount = dpcd_reg_read(connectorIndex,
371			DP_MAX_LANE_COUNT) & DP_MAX_LANE_COUNT_MASK;
372
373	uint32 lane;
374	// don't go below 2 lanes or display is jittery
375	for (lane = 2; lane < dpMaxLaneCount; lane <<= 1) {
376		uint32 maxPixelClock = dp_get_pixel_clock_max(dpMaxLinkRate, lane,
377			bitsPerPixel);
378		if (mode->timing.pixel_clock <= maxPixelClock)
379			break;
380	}
381
382	TRACE("%s: Lanes: %" B_PRIu32 "\n", __func__, lane);
383	return lane;
384}
385
386
387uint32
388dp_get_link_rate(uint32 connectorIndex, display_mode* mode)
389{
390	uint16 encoderID = gConnector[connectorIndex]->encoderExternal.objectID;
391
392	if (encoderID == ENCODER_OBJECT_ID_NUTMEG)
393		return 270000;
394
395	size_t pixelChunk;
396	size_t pixelsPerChunk;
397	status_t result = dp_get_pixel_size_for((color_space)mode->space,
398		&pixelChunk, NULL, &pixelsPerChunk);
399
400	if (result != B_OK) {
401		TRACE("%s: Invalid color space!\n", __func__);
402		return 0;
403	}
404
405	uint32 bitsPerPixel = (pixelChunk / pixelsPerChunk) * 8;
406	uint32 laneCount = dp_get_lane_count(connectorIndex, mode);
407
408	uint32 maxPixelClock
409		= dp_get_pixel_clock_max(162000, laneCount, bitsPerPixel);
410	if (mode->timing.pixel_clock <= maxPixelClock)
411		return 162000;
412
413	maxPixelClock = dp_get_pixel_clock_max(270000, laneCount, bitsPerPixel);
414	if (mode->timing.pixel_clock <= maxPixelClock)
415		return 270000;
416
417	// TODO: DisplayPort 1.2
418	#if 0
419	if (dp_is_dp12_capable(connectorIndex)) {
420		maxPixelClock = dp_get_pixel_clock_max(540000, laneCount, bitsPerPixel);
421		if (mode->timing.pixel_clock <= maxPixelClock)
422			return 540000;
423	}
424	#endif
425
426	return dp_decode_link_rate(dpcd_reg_read(connectorIndex, DP_MAX_LINK_RATE));
427}
428
429
430static uint8
431dp_encoder_service(int action, int linkRate, uint8 lane, uint8 config)
432{
433	DP_ENCODER_SERVICE_PARAMETERS args;
434	int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
435
436	memset(&args, 0, sizeof(args));
437	args.ucLinkClock = linkRate / 10;
438	args.ucConfig = config;
439	args.ucAction = action;
440	args.ucLaneNum = lane;
441	args.ucStatus = 0;
442
443	atom_execute_table(gAtomContext, index, (uint32*)&args);
444	return args.ucStatus;
445}
446
447
448uint8
449dp_get_sink_type(uint32 connectorIndex)
450{
451	dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
452	return dp_encoder_service(ATOM_DP_ACTION_GET_SINK_TYPE, 0, 0,
453		dpInfo->auxPin);
454}
455
456
457void
458dp_setup_connectors()
459{
460	TRACE("%s\n", __func__);
461
462	for (uint32 index = 0; index < ATOM_MAX_SUPPORTED_DEVICE; index++) {
463		dp_info* dpInfo = &gConnector[index]->dpInfo;
464		// Validate connector is actually display port
465		if (gConnector[index]->valid == false
466			|| connector_is_dp(index) == false) {
467			dpInfo->valid = false;
468			continue;
469		}
470
471		// Configure communication pins.
472		uint32 i2cPinIndex = gConnector[index]->i2cPinIndex;
473		uint32 auxPin = gGPIOInfo[i2cPinIndex]->hwPin;
474		dpInfo->auxPin = auxPin;
475		dpInfo->valid = true;
476	}
477}
478
479
480bool
481dp_get_link_status(uint32 connectorIndex)
482{
483	dp_info* dp = &gConnector[connectorIndex]->dpInfo;
484
485	dp_aux_msg message;
486	memset(&message, 0, sizeof(message));
487
488	message.request = DP_AUX_NATIVE_READ;
489	message.address = DP_LANE_STATUS_0_1;
490	message.size = DP_LINK_STATUS_SIZE;
491	message.buffer = dp->linkStatus;
492
493	// TODO: Delay 100? Newer AMD code doesn't care about link status
494	status_t result = dp_aux_transaction(connectorIndex, &message);
495
496	if (result != B_OK) {
497		ERROR("%s: DisplayPort link status failed\n", __func__);
498		return false;
499	}
500
501	return true;
502}
503
504
505static uint8
506dp_get_lane_status(dp_info* dp, int lane)
507{
508	int i = DP_LANE_STATUS_0_1 + (lane >> 1);
509	int s = (lane & 1) * 4;
510	uint8 l = dp->linkStatus[i - DP_LANE_STATUS_0_1];
511	return (l >> s) & 0xf;
512}
513
514
515static bool
516dp_clock_recovery_ok(dp_info* dp)
517{
518	int lane;
519	uint8 laneStatus;
520
521	for (lane = 0; lane < dp->laneCount; lane++) {
522		laneStatus = dp_get_lane_status(dp, lane);
523		if ((laneStatus & DP_LANE_STATUS_CR_DONE_A) == 0)
524			return false;
525	}
526	return true;
527}
528
529
530static bool
531dp_clock_equalization_ok(dp_info* dp)
532{
533	uint8 laneAlignment
534		= dp->linkStatus[DP_LANE_ALIGN_STATUS_UPDATED - DP_LANE_STATUS_0_1];
535
536	if ((laneAlignment & DP_INTERLANE_ALIGN_DONE) == 0) {
537		TRACE("%s: false. Lane alignment incomplete.\n", __func__);
538		return false;
539	}
540
541	int lane;
542	for (lane = 0; lane < dp->laneCount; lane++) {
543		uint8 laneStatus = dp_get_lane_status(dp, lane);
544		if ((laneStatus & DP_LANE_STATUS_EQUALIZED_A)
545			!= DP_LANE_STATUS_EQUALIZED_A) {
546			TRACE("%s: false. Lanes not yet equalized.\n", __func__);
547			return false;
548		}
549	}
550	TRACE("%s: true. Lanes equalized.\n", __func__);
551	return true;
552}
553
554
555static void
556dp_update_vs_emph(uint32 connectorIndex)
557{
558	dp_info* dp = &gConnector[connectorIndex]->dpInfo;
559
560	// Set initial vs and emph on source
561	transmitter_dig_setup(connectorIndex, dp->linkRate, 0,
562		dp->trainingSet[0], ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH);
563
564	dp_aux_msg message;
565	memset(&message, 0, sizeof(message));
566
567	message.request = DP_AUX_NATIVE_WRITE;
568	message.address = DP_TRAINING_LANE0_SET;
569	message.buffer = dp->trainingSet;
570	message.size = dp->laneCount;
571		// TODO: Review laneCount as it sounds strange.
572	dp_aux_transaction(connectorIndex, &message);
573}
574
575
576static uint8
577dp_get_adjust_request_voltage(dp_info* dp, int lane)
578{
579	int i = DP_ADJ_REQUEST_0_1 + (lane >> 1);
580	int s = (((lane & 1) != 0) ? DP_ADJ_VCC_SWING_LANEB_SHIFT
581		: DP_ADJ_VCC_SWING_LANEA_SHIFT);
582	uint8 l = dp->linkStatus[i - DP_LANE_STATUS_0_1];
583
584	return ((l >> s) & 0x3) << DP_TRAIN_VCC_SWING_SHIFT;
585}
586
587
588static uint8
589dp_get_adjust_request_pre_emphasis(dp_info* dp, int lane)
590{
591	int i = DP_ADJ_REQUEST_0_1 + (lane >> 1);
592	int s = (((lane & 1) != 0) ? DP_ADJ_PRE_EMPHASIS_LANEB_SHIFT
593		: DP_ADJ_PRE_EMPHASIS_LANEA_SHIFT);
594	uint8 l = dp->linkStatus[i - DP_LANE_STATUS_0_1];
595
596	return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
597}
598
599
600static void
601dp_get_adjust_train(dp_info* dp)
602{
603	TRACE("%s\n", __func__);
604
605	const char* voltageNames[] = {
606		"0.4V", "0.6V", "0.8V", "1.2V"
607	};
608	const char* preEmphasisNames[] = {
609		"0dB", "3.5dB", "6dB", "9.5dB"
610	};
611
612	uint8 voltage = 0;
613	uint8 preEmphasis = 0;
614	int lane;
615
616	for (lane = 0; lane < dp->laneCount; lane++) {
617		uint8 laneVoltage = dp_get_adjust_request_voltage(dp, lane);
618		uint8 lanePreEmphasis = dp_get_adjust_request_pre_emphasis(dp, lane);
619
620		TRACE("%s: Requested %s at %s for lane %d\n", __func__,
621			preEmphasisNames[lanePreEmphasis >> DP_TRAIN_PRE_EMPHASIS_SHIFT],
622			voltageNames[laneVoltage >> DP_TRAIN_VCC_SWING_SHIFT],
623			lane);
624
625		if (laneVoltage > voltage)
626			voltage = laneVoltage;
627		if (lanePreEmphasis > preEmphasis)
628			preEmphasis = lanePreEmphasis;
629	}
630
631	// Check for maximum voltage and toggle max if reached
632	if (voltage >= DP_TRAIN_VCC_SWING_1200)
633		voltage |= DP_TRAIN_MAX_SWING_EN;
634
635	// Check for maximum pre-emphasis and toggle max if reached
636	if (preEmphasis >= DP_TRAIN_PRE_EMPHASIS_9_5)
637		preEmphasis |= DP_TRAIN_MAX_EMPHASIS_EN;
638
639	for (lane = 0; lane < 4; lane++)
640		dp->trainingSet[lane] = voltage | preEmphasis;
641}
642
643
644static void
645dp_set_tp(uint32 connectorIndex, int trainingPattern)
646{
647	TRACE("%s\n", __func__);
648	radeon_shared_info &info = *gInfo->shared_info;
649
650	pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
651
652	int rawTrainingPattern = 0;
653
654	if (info.dceMajor >= 4) {
655		TRACE("%s: Training with encoder...\n", __func__);
656		switch (trainingPattern) {
657			case DP_TRAINING_PATTERN_1:
658				rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1;
659				break;
660			case DP_TRAINING_PATTERN_2:
661				rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2;
662				break;
663			case DP_TRAINING_PATTERN_3:
664				rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3;
665				break;
666		}
667		encoder_dig_setup(connectorIndex, pll->pixelClock, rawTrainingPattern);
668	} else {
669		switch (trainingPattern) {
670			case DP_TRAINING_PATTERN_1:
671				rawTrainingPattern = 0;
672				break;
673			case DP_TRAINING_PATTERN_2:
674				rawTrainingPattern = 1;
675				break;
676		}
677		uint32 encoderConfig = dp_get_encoder_config(connectorIndex);
678		dp_encoder_service(ATOM_DP_ACTION_TRAINING_PATTERN_SEL, pll->pixelClock,
679			rawTrainingPattern, encoderConfig);
680	}
681
682	// Enable training pattern on the sink
683	dpcd_reg_write(connectorIndex, DP_TRAINING_PATTERN_SET, trainingPattern);
684}
685
686
687status_t
688dp_link_train_cr(uint32 connectorIndex)
689{
690	TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
691
692	dp_info* dp = &gConnector[connectorIndex]->dpInfo;
693
694	// Display Port Clock Recovery Training
695
696	bool clockRecovery = false;
697	uint8 voltage = 0xff;
698	int lane;
699
700	dp_set_tp(connectorIndex, DP_TRAINING_PATTERN_1);
701	memset(dp->trainingSet, 0, 4);
702	dp_update_vs_emph(connectorIndex);
703	snooze(400);
704
705	while (1) {
706		if (dp->trainingReadInterval == 0)
707			snooze(100);
708		else
709			snooze(1000 * 4 * dp->trainingReadInterval);
710
711		if (!dp_get_link_status(connectorIndex))
712			break;
713
714		if (dp_clock_recovery_ok(dp)) {
715			clockRecovery = true;
716			break;
717		}
718
719		for (lane = 0; lane < dp->laneCount; lane++) {
720			if ((dp->trainingSet[lane] & DP_TRAIN_MAX_SWING_EN) == 0)
721				break;
722		}
723
724		if (lane == dp->laneCount) {
725			ERROR("%s: clock recovery reached max voltage\n", __func__);
726			break;
727		}
728
729		if ((dp->trainingSet[0] & DP_TRAIN_VCC_SWING_MASK) == voltage) {
730			dp->trainingAttempts++;
731			if (dp->trainingAttempts >= 5) {
732				ERROR("%s: clock recovery tried 5 times\n", __func__);
733				break;
734			}
735		} else
736			dp->trainingAttempts = 0;
737
738		voltage = dp->trainingSet[0] & DP_TRAIN_VCC_SWING_MASK;
739
740		// Compute new trainingSet as requested by sink
741		dp_get_adjust_train(dp);
742
743		dp_update_vs_emph(connectorIndex);
744	}
745
746	if (!clockRecovery) {
747		ERROR("%s: clock recovery failed\n", __func__);
748		return B_ERROR;
749	}
750
751	TRACE("%s: clock recovery at voltage %d pre-emphasis %d\n",
752		__func__, dp->trainingSet[0] & DP_TRAIN_VCC_SWING_MASK,
753		(dp->trainingSet[0] & DP_TRAIN_PRE_EMPHASIS_MASK)
754		>> DP_TRAIN_PRE_EMPHASIS_SHIFT);
755	return B_OK;
756}
757
758
759status_t
760dp_link_train_ce(uint32 connectorIndex, bool tp3Support)
761{
762	TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
763
764	dp_info* dp = &gConnector[connectorIndex]->dpInfo;
765
766	if (tp3Support)
767		dp_set_tp(connectorIndex, DP_TRAINING_PATTERN_3);
768	else
769		dp_set_tp(connectorIndex, DP_TRAINING_PATTERN_2);
770
771	dp->trainingAttempts = 0;
772	bool channelEqual = false;
773
774	while (1) {
775		if (dp->trainingReadInterval == 0)
776			snooze(400);
777		else
778			snooze(1000 * 4 * dp->trainingReadInterval);
779
780		if (!dp_get_link_status(connectorIndex)) {
781			ERROR("%s: ERROR: Unable to get link status!\n", __func__);
782			break;
783		}
784
785		if (dp_clock_equalization_ok(dp)) {
786			channelEqual = true;
787			break;
788		}
789
790		if (dp->trainingAttempts > 5) {
791			ERROR("%s: ERROR: failed > 5 times!\n", __func__);
792			break;
793		}
794
795		dp_get_adjust_train(dp);
796
797		dp_update_vs_emph(connectorIndex);
798		dp->trainingAttempts++;
799	}
800
801	if (!channelEqual) {
802		ERROR("%s: ERROR: failed\n", __func__);
803		return B_ERROR;
804	}
805
806	TRACE("%s: channels equalized at voltage %d pre-emphasis %d\n",
807		__func__, dp->trainingSet[0] & DP_ADJ_VCC_SWING_LANEA_MASK,
808		(dp->trainingSet[0] & DP_TRAIN_PRE_EMPHASIS_MASK)
809		>> DP_TRAIN_PRE_EMPHASIS_SHIFT);
810
811	return B_OK;
812}
813
814
815status_t
816dp_link_train(uint8 crtcID)
817{
818	TRACE("%s\n", __func__);
819
820	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
821	dp_info* dp = &gConnector[connectorIndex]->dpInfo;
822	display_mode* mode = &gDisplay[crtcID]->currentMode;
823
824	if (dp->valid != true) {
825		ERROR("%s: started on invalid DisplayPort connector #%" B_PRIu32 "\n",
826			__func__, connectorIndex);
827		return B_ERROR;
828	}
829
830	dp->revision = dpcd_reg_read(connectorIndex, DP_DPCD_REV);
831	dp->trainingReadInterval
832		= dpcd_reg_read(connectorIndex, DP_TRAINING_AUX_RD_INTERVAL);
833
834	uint8 sandbox = dpcd_reg_read(connectorIndex, DP_MAX_LANE_COUNT);
835
836	radeon_shared_info &info = *gInfo->shared_info;
837	bool dpTPS3Supported = false;
838	if (info.dceMajor >= 5 && (sandbox & DP_TPS3_SUPPORTED) != 0)
839		dpTPS3Supported = true;
840
841	// *** DisplayPort link training initialization
842
843	// Power up the DP sink
844	if (dp->revision >= DP_DPCD_REV_11)
845		dpcd_reg_write(connectorIndex, DP_SET_POWER, DP_SET_POWER_D0);
846
847	// Possibly enable downspread on the sink
848	if ((dpcd_reg_read(connectorIndex, DP_MAX_DOWNSPREAD) & 0x1) != 0) {
849		dpcd_reg_write(connectorIndex, DP_DOWNSPREAD_CTRL,
850			DP_DOWNSPREAD_CTRL_AMP_EN);
851	} else
852		dpcd_reg_write(connectorIndex, DP_DOWNSPREAD_CTRL, 0);
853
854	encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
855		ATOM_ENCODER_CMD_SETUP_PANEL_MODE);
856
857	// Enable enhanced frame if supported
858	sandbox = dpcd_reg_read(connectorIndex, DP_LANE_COUNT);
859	if (dp->revision >= DP_DPCD_REV_11
860		&& (dpcd_reg_read(connectorIndex, DP_MAX_LANE_COUNT)
861			& DP_ENHANCED_FRAME_CAP)) {
862		sandbox |= DP_ENHANCED_FRAME_EN;
863	}
864	dpcd_reg_write(connectorIndex, DP_LANE_COUNT, sandbox);
865
866	// Set the link rate on the DP sink
867	sandbox = dp_encode_link_rate(dp->linkRate);
868	dpcd_reg_write(connectorIndex, DP_LINK_RATE, sandbox);
869
870	uint32 encoderConfig = dp_get_encoder_config(connectorIndex);
871
872	// Start link training on source
873	if (info.dceMajor >= 4) {
874		encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
875			ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
876	} else {
877		dp_encoder_service(ATOM_DP_ACTION_TRAINING_START,
878			mode->timing.pixel_clock, 0, encoderConfig);
879	}
880
881	// Disable the training pattern on the sink
882	dpcd_reg_write(connectorIndex, DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
883
884	dp_link_train_cr(connectorIndex);
885	dp_link_train_ce(connectorIndex, dpTPS3Supported);
886
887	// *** DisplayPort link training finish
888	snooze(400);
889
890	// Disable the training pattern on the sink
891	dpcd_reg_write(connectorIndex, DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
892
893	// Disable the training pattern on the source
894	if (info.dceMajor >= 4) {
895		encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
896			ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
897	} else {
898		dp_encoder_service(ATOM_DP_ACTION_TRAINING_COMPLETE,
899			mode->timing.pixel_clock, 0, encoderConfig);
900	}
901
902	return B_OK;
903}
904
905
906bool
907ddc2_dp_read_edid1(uint32 connectorIndex, edid1_info* edid)
908{
909	TRACE("%s\n", __func__);
910
911	dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
912
913	if (!dpInfo->valid) {
914		ERROR("%s: connector(%" B_PRIu32 ") missing valid DisplayPort data!\n",
915			__func__, connectorIndex);
916		return false;
917	}
918
919	edid1_raw raw;
920	uint8* rdata = (uint8*)&raw;
921	uint8 sdata = 0;
922
923	// The following sequence is from a trace of the Linux kernel
924	// radeon code; not sure if the initial writes to address 0 are
925	// requried.
926	// TODO: This surely cane be cleaned up
927	dp_aux_set_i2c_byte(connectorIndex, 0x00, &sdata, true, false);
928	dp_aux_set_i2c_byte(connectorIndex, 0x00, &sdata, false, true);
929
930	dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, true, false);
931	dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, false, false);
932	dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, true, false);
933	dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, false, false);
934	dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, false, true);
935
936	dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, true, false);
937	dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, false, false);
938	dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, true, false);
939
940	for (uint32 i = 0; i < sizeof(raw); i++) {
941		status_t result = dp_aux_get_i2c_byte(connectorIndex, 0x50,
942			rdata++, false, false);
943		if (result != B_OK) {
944			TRACE("%s: error reading EDID data at index %" B_PRIu32 ", "
945				"result = 0x%" B_PRIx32 "\n", __func__, i, result);
946			dp_aux_get_i2c_byte(connectorIndex, 0x50, &sdata, false, true);
947			return false;
948		}
949	}
950	dp_aux_get_i2c_byte(connectorIndex, 0x50, &sdata, false, true);
951
952	if (raw.version.version != 1 || raw.version.revision > 4) {
953		ERROR("%s: EDID version or revision out of range\n", __func__);
954		return false;
955	}
956
957	edid_decode(edid, &raw);
958
959	return true;
960}
961
962
963status_t
964dp_get_pixel_size_for(color_space space, size_t *pixelChunk,
965	size_t *rowAlignment, size_t *pixelsPerChunk)
966{
967	status_t result = get_pixel_size_for(space, pixelChunk, NULL,
968		pixelsPerChunk);
969
970	if ((space == B_RGB32) || (space == B_RGBA32) || (space == B_RGB32_BIG)
971		|| (space == B_RGBA32_BIG)) {
972		*pixelChunk = 3;
973	}
974
975	return result;
976}
977
978
979bool
980dp_is_dp12_capable(uint32 connectorIndex)
981{
982	TRACE("%s\n", __func__);
983	radeon_shared_info &info = *gInfo->shared_info;
984
985	uint32 capabilities = gConnector[connectorIndex]->encoder.capabilities;
986
987	// DP_DPCD_REV_12 as well?
988
989	if (info.dceMajor >= 5
990		&& gInfo->dpExternalClock >= 539000
991		&& (capabilities & ATOM_ENCODER_CAP_RECORD_HBR2) != 0) {
992		return true;
993	}
994
995	return false;
996}
997
998
999void
1000debug_dp_info()
1001{
1002	ERROR("Current DisplayPort Info =================\n");
1003	for (uint32 id = 0; id < ATOM_MAX_SUPPORTED_DEVICE; id++) {
1004		if (gConnector[id]->valid == true) {
1005			dp_info* dp = &gConnector[id]->dpInfo;
1006			ERROR("Connector #%" B_PRIu32 ") DP: %s\n", id,
1007				dp->valid ? "true" : "false");
1008
1009			if (!dp->valid)
1010				continue;
1011			ERROR(" + DP Config Data\n");
1012			ERROR("   - max lane count:          %d\n",
1013				dpcd_reg_read(id, DP_MAX_LANE_COUNT) & DP_MAX_LANE_COUNT_MASK);
1014			ERROR("   - max link rate:           %d\n",
1015				dpcd_reg_read(id, DP_MAX_LINK_RATE));
1016			ERROR("   - receiver port count:     %d\n",
1017				dpcd_reg_read(id, DP_NORP) & DP_NORP_MASK);
1018			ERROR("   - downstream port present: %s\n",
1019				dpcd_reg_read(id, DP_DOWNSTREAMPORT_PRESENT) & DP_DWN_STRM_PORT_PRESENT
1020					? "yes" : "no");
1021			ERROR("   - downstream port count:   %d\n",
1022				dpcd_reg_read(id, DP_DOWN_STREAM_PORT_COUNT)
1023					& DP_PORT_COUNT_MASK);
1024			ERROR(" + Training\n");
1025			ERROR("   - attempts:                %" B_PRIu8 "\n",
1026				dp->trainingAttempts);
1027			ERROR("   - delay:                   %d\n",
1028				dp->trainingReadInterval);
1029			ERROR(" + Data\n");
1030			ERROR("   - auxPin:                  0x%" B_PRIX32"\n", dp->auxPin);
1031			ERROR(" + Video\n");
1032			ERROR("   - laneCount:               %d\n", dp->laneCount);
1033			ERROR("   - linkRate:                %" B_PRIu32 "\n",
1034				dp->linkRate);
1035		}
1036	}
1037	ERROR("==========================================\n");
1038}
1039