xref: /haiku/src/add-ons/accelerants/radeon_hd/encoder.cpp (revision 52c4471a3024d2eb81fe88e2c3982b9f8daa5e56)
1 /*
2  * Copyright 2006-2012, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *	  Alexander von Gluck, kallisti5@unixzen.com
7  */
8 
9 
10 #include "encoder.h"
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <math.h>
16 
17 #include "accelerant.h"
18 #include "accelerant_protos.h"
19 #include "atombios-obsolete.h"
20 #include "bios.h"
21 #include "connector.h"
22 #include "display.h"
23 #include "displayport.h"
24 #include "utility.h"
25 
26 
27 #define TRACE_ENCODER
28 #ifdef TRACE_ENCODER
29 extern "C" void _sPrintf(const char* format, ...);
30 #   define TRACE(x...) _sPrintf("radeon_hd: " x)
31 #else
32 #   define TRACE(x...) ;
33 #endif
34 
35 #define ERROR(x...) _sPrintf("radeon_hd: " x)
36 
37 
38 static uint32
39 encoder_get_bpc()
40 {
41 	/*
42 	switch (8) {
43 		case 0:
44 			return PANEL_BPC_UNDEFINE;
45 		case 6:
46 			return PANEL_6BIT_PER_COLOR;
47 		case 8:
48 			return PANEL_8BIT_PER_COLOR;
49 		case 10:
50 			return PANEL_10BIT_PER_COLOR;
51 		case 12:
52 			return PANEL_12BIT_PER_COLOR;
53 		case 16:
54 			return PANEL_16BIT_PER_COLOR;
55 	}
56 	*/
57 	return PANEL_8BIT_PER_COLOR;
58 }
59 
60 
61 void
62 encoder_init()
63 {
64 	TRACE("%s: called\n", __func__);
65 	radeon_shared_info &info = *gInfo->shared_info;
66 
67 	for (uint32 id = 0; id < ATOM_MAX_SUPPORTED_DEVICE; id++) {
68 		if (gConnector[id]->valid == false)
69 			continue;
70 
71 		switch (gConnector[id]->encoder.objectID) {
72 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
73 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
74 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
75 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
76 				transmitter_dig_setup(id, 0, 0, 0,
77 					ATOM_TRANSMITTER_ACTION_INIT);
78 				break;
79 			default:
80 				break;
81 		}
82 
83 		if ((info.chipsetFlags & CHIP_APU) != 0) {
84 			if (gConnector[id]->encoderExternal.valid == true) {
85 				encoder_external_setup(id,
86 					EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT);
87 			}
88 		}
89 	}
90 }
91 
92 
93 void
94 encoder_assign_crtc(uint8 crtcID)
95 {
96 	TRACE("%s\n", __func__);
97 
98 	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
99 
100 	// Table version
101 	uint8 tableMajor;
102 	uint8 tableMinor;
103 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
104 		!= B_OK)
105 		return;
106 
107 	TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
108 		tableMajor, tableMinor);
109 
110 	uint16 connectorIndex = gDisplay[crtcID]->connectorIndex;
111 	uint16 connectorFlags = gConnector[connectorIndex]->flags;
112 	uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
113 
114 	// Prepare AtomBIOS command arguments
115 	union crtcSourceParam {
116 		SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
117 		SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
118 		SELECT_CRTC_SOURCE_PARAMETERS_V3 v3;
119 	};
120 	union crtcSourceParam args;
121 	memset(&args, 0, sizeof(args));
122 
123 	switch (tableMajor) {
124 		case 1:
125 			switch (tableMinor) {
126 				case 1:
127 				default:
128 					args.v1.ucCRTC = crtcID;
129 					switch (encoderID) {
130 						case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
131 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
132 							args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
133 							break;
134 						case ENCODER_OBJECT_ID_INTERNAL_LVDS:
135 						case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
136 							if ((gConnector[connectorIndex]->flags
137 								& ATOM_DEVICE_LCD1_SUPPORT) != 0)
138 								args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
139 							else
140 								args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
141 							break;
142 						case ENCODER_OBJECT_ID_INTERNAL_DVO1:
143 						case ENCODER_OBJECT_ID_INTERNAL_DDI:
144 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
145 							args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
146 							break;
147 						case ENCODER_OBJECT_ID_INTERNAL_DAC1:
148 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
149 							if ((connectorFlags
150 								& ATOM_DEVICE_TV_SUPPORT) != 0) {
151 								args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
152 							} else if ((connectorFlags
153 								& ATOM_DEVICE_CV_SUPPORT) != 0) {
154 								args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
155 							} else
156 								args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
157 							break;
158 						case ENCODER_OBJECT_ID_INTERNAL_DAC2:
159 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
160 							if ((connectorFlags
161 								& ATOM_DEVICE_TV_SUPPORT) != 0) {
162 								args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
163 							} else if ((connectorFlags
164 								& ATOM_DEVICE_CV_SUPPORT) != 0) {
165 								args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
166 							} else
167 								args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
168 							break;
169 					}
170 					break;
171 				case 2:
172 					args.v2.ucCRTC = crtcID;
173 					args.v2.ucEncodeMode
174 						= display_get_encoder_mode(connectorIndex);
175 					switch (encoderID) {
176 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
177 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
178 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
179 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
180 							switch (encoder_pick_dig(connectorIndex)) {
181 								case 0:
182 									args.v2.ucEncoderID
183 										= ASIC_INT_DIG1_ENCODER_ID;
184 									break;
185 								case 1:
186 									args.v2.ucEncoderID
187 										= ASIC_INT_DIG2_ENCODER_ID;
188 									break;
189 								case 2:
190 									args.v2.ucEncoderID
191 										= ASIC_INT_DIG3_ENCODER_ID;
192 									break;
193 								case 3:
194 									args.v2.ucEncoderID
195 										= ASIC_INT_DIG4_ENCODER_ID;
196 									break;
197 								case 4:
198 									args.v2.ucEncoderID
199 										= ASIC_INT_DIG5_ENCODER_ID;
200 									break;
201 								case 5:
202 									args.v2.ucEncoderID
203 										= ASIC_INT_DIG6_ENCODER_ID;
204 									break;
205 							}
206 							break;
207 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
208 							args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
209 							break;
210 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
211 							if ((connectorFlags
212 								& ATOM_DEVICE_TV_SUPPORT) != 0) {
213 								args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
214 							} else if ((connectorFlags
215 								& ATOM_DEVICE_CV_SUPPORT) != 0) {
216 								args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
217 							} else
218 								args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
219 							break;
220 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
221 							if ((connectorFlags
222 								& ATOM_DEVICE_TV_SUPPORT) != 0) {
223 								args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
224 							} else if ((connectorFlags
225 								& ATOM_DEVICE_CV_SUPPORT) != 0) {
226 								args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
227 							} else
228 								args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
229 							break;
230 					}
231 					break;
232 				case 3:
233 					args.v3.ucCRTC = crtcID;
234 					// TODO: Better bridge logic
235 					args.v2.ucEncodeMode
236 						= display_get_encoder_mode(connectorIndex);
237 					args.v3.ucDstBpc = encoder_get_bpc();
238 					switch (encoderID) {
239 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
240 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
241 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
242 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
243 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
244 							switch (encoder_pick_dig(connectorIndex)) {
245 								case 0:
246 									args.v3.ucEncoderID
247 										= ASIC_INT_DIG1_ENCODER_ID;
248 									break;
249 								case 1:
250 									args.v3.ucEncoderID
251 										= ASIC_INT_DIG2_ENCODER_ID;
252 									break;
253 								case 2:
254 									args.v3.ucEncoderID
255 										= ASIC_INT_DIG3_ENCODER_ID;
256 									break;
257 								case 3:
258 									args.v3.ucEncoderID
259 										= ASIC_INT_DIG4_ENCODER_ID;
260 									break;
261 								case 4:
262 									args.v3.ucEncoderID
263 										= ASIC_INT_DIG5_ENCODER_ID;
264 									break;
265 								case 5:
266 									args.v3.ucEncoderID
267 										= ASIC_INT_DIG6_ENCODER_ID;
268 									break;
269 								case 6:
270 									args.v3.ucEncoderID
271 										= ASIC_INT_DIG7_ENCODER_ID;
272 									break;
273 							}
274 							break;
275 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
276 							args.v3.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
277 							break;
278 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
279 							if ((connectorFlags
280 								& ATOM_DEVICE_TV_SUPPORT) != 0) {
281 								args.v3.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
282 							} else if ((connectorFlags
283 								& ATOM_DEVICE_CV_SUPPORT) != 0) {
284 								args.v3.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
285 							} else
286 								args.v3.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
287 							break;
288 						case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
289 							if ((connectorFlags
290 								& ATOM_DEVICE_TV_SUPPORT) != 0) {
291 								args.v3.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
292 							} else if ((connectorFlags
293 								& ATOM_DEVICE_CV_SUPPORT) != 0) {
294 								args.v3.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
295 							} else
296 								args.v3.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
297 							break;
298 					}
299 					break;
300 			}
301 			break;
302 		default:
303 			ERROR("%s: Unknown table version: %" B_PRIu8 ".%" B_PRIu8 "\n",
304 				__func__, tableMajor, tableMinor);
305 			return;
306 	}
307 
308 	atom_execute_table(gAtomContext, index, (uint32*)&args);
309 
310 	// update crtc encoder scratch register @ scratch 3
311 	encoder_crtc_scratch(crtcID);
312 }
313 
314 
315 uint32
316 encoder_pick_dig(uint32 connectorIndex)
317 {
318 	TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
319 	radeon_shared_info &info = *gInfo->shared_info;
320 	uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
321 
322 	// obtain assigned CRT
323 	uint32 crtcID;
324 	for (crtcID = 0; crtcID < MAX_DISPLAY; crtcID++) {
325 		if (gDisplay[crtcID]->attached != true)
326 			continue;
327 		if (gDisplay[crtcID]->connectorIndex == connectorIndex)
328 			break;
329 	}
330 
331 	bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
332 		== GRAPH_OBJECT_ENUM_ID2 ? true : false;
333 
334 	uint32 dceVersion = (info.dceMajor * 100) + info.dceMinor;
335 
336 	if (dceVersion >= 400) {
337 		// APU
338 		switch (info.chipsetID) {
339 			case RADEON_PALM:
340 				return linkB ? 1 : 0;
341 			case RADEON_SUMO:
342 			case RADEON_SUMO2:
343 				return crtcID;
344 		}
345 
346 		switch (encoderID) {
347 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
348 				return linkB ? 1 : 0;
349 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
350 				return linkB ? 3 : 2;
351 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
352 				return linkB ? 5 : 4;
353 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
354 				return 6;
355 		}
356 	}
357 
358 	if (dceVersion >= 302)
359 		return crtcID;
360 
361 	if (encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA)
362 		return 1;
363 
364 	return 0;
365 }
366 
367 
368 void
369 encoder_apply_quirks(uint8 crtcID)
370 {
371 	TRACE("%s: display %" B_PRIu8 "\n", __func__, crtcID);
372 	radeon_shared_info &info = *gInfo->shared_info;
373 	register_info* regs = gDisplay[crtcID]->regs;
374 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
375 	uint16 connectorFlags = gConnector[connectorIndex]->flags;
376 
377 	// Setting the scaler clears this on some chips...
378 	if (info.dceMajor >= 3
379 		&& (connectorFlags & ATOM_DEVICE_TV_SUPPORT) == 0) {
380 		// TODO: assume non interleave mode for now
381 		// en: EVERGREEN_INTERLEAVE_EN : AVIVO_D1MODE_INTERLEAVE_EN
382 		Write32(OUT, regs->modeDataFormat, 0);
383 	}
384 }
385 
386 
387 void
388 encoder_mode_set(uint8 crtcID)
389 {
390 	TRACE("%s: display %" B_PRIu8 "\n", __func__, crtcID);
391 	radeon_shared_info &info = *gInfo->shared_info;
392 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
393 	uint16 connectorFlags = gConnector[connectorIndex]->flags;
394 	pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
395 
396 	// TODO: Should this be the adjusted pll or the original?
397 	uint32 pixelClock = pll->pixelClock;
398 
399 	switch (gConnector[connectorIndex]->encoder.objectID) {
400 		case ENCODER_OBJECT_ID_INTERNAL_DAC1:
401 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
402 		case ENCODER_OBJECT_ID_INTERNAL_DAC2:
403 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
404 			encoder_analog_setup(connectorIndex, pixelClock, ATOM_ENABLE);
405 			if (info.dceMajor < 5) {
406 				// TV encoder was dropped in DCE 5
407 				if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0
408 					|| (connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
409 					encoder_tv_setup(connectorIndex, pixelClock, ATOM_ENABLE);
410 				} else {
411 					encoder_tv_setup(connectorIndex, pixelClock, ATOM_DISABLE);
412 				}
413 			}
414 			break;
415 		case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
416 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
417 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
418 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
419 			encoder_digital_setup(connectorIndex, pixelClock,
420 				PANEL_ENCODER_ACTION_ENABLE);
421 			break;
422 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
423 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
424 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
425 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
426 			if ((info.chipsetFlags & CHIP_APU) != 0
427 				|| info.dceMajor >= 5) {
428 				// Setup DIG encoder
429 				encoder_dig_setup(connectorIndex, pixelClock,
430 					ATOM_ENCODER_CMD_SETUP);
431 				encoder_dig_setup(connectorIndex, pixelClock,
432 					ATOM_ENCODER_CMD_SETUP_PANEL_MODE);
433 			} else if (info.dceMajor >= 4) {
434 				// Disable DIG transmitter
435 				transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
436 					ATOM_TRANSMITTER_ACTION_DISABLE);
437 				// Setup DIG encoder
438 				encoder_dig_setup(connectorIndex, pixelClock,
439 					ATOM_ENCODER_CMD_SETUP);
440 				// Enable DIG transmitter
441 				transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
442 					ATOM_TRANSMITTER_ACTION_ENABLE);
443 			} else {
444 				// Disable DIG transmitter
445 				transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
446 					ATOM_TRANSMITTER_ACTION_DISABLE);
447 				// Disable DIG encoder
448 				encoder_dig_setup(connectorIndex, pixelClock, ATOM_DISABLE);
449 				// Enable the DIG encoder
450 				encoder_dig_setup(connectorIndex, pixelClock, ATOM_ENABLE);
451 
452 				// Setup and enable DIG transmitter
453 				transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
454 					ATOM_TRANSMITTER_ACTION_SETUP);
455 				transmitter_dig_setup(connectorIndex, pixelClock, 0, 0,
456 					ATOM_TRANSMITTER_ACTION_ENABLE);
457 			}
458 			break;
459 		case ENCODER_OBJECT_ID_INTERNAL_DDI:
460 		case ENCODER_OBJECT_ID_INTERNAL_DVO1:
461 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
462 			TRACE("%s: TODO for DVO encoder setup\n", __func__);
463 			break;
464 	}
465 
466 	if (gConnector[connectorIndex]->encoderExternal.valid == true) {
467 		if ((info.chipsetFlags & CHIP_APU) != 0) {
468 			// aka DCE 4.1
469 			encoder_external_setup(connectorIndex,
470 				EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
471 		} else
472 			encoder_external_setup(connectorIndex, ATOM_ENABLE);
473 
474 	}
475 
476 	encoder_apply_quirks(crtcID);
477 }
478 
479 
480 status_t
481 encoder_tv_setup(uint32 connectorIndex, uint32 pixelClock, int command)
482 {
483 	TRACE("%s: connector %" B_PRIu32 ", pixelClock: %" B_PRIu32 "\n", __func__,
484 		connectorIndex, pixelClock);
485 
486 	uint16 connectorFlags = gConnector[connectorIndex]->flags;
487 
488 	TV_ENCODER_CONTROL_PS_ALLOCATION args;
489 	memset(&args, 0, sizeof(args));
490 
491 	int index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
492 
493 	args.sTVEncoder.ucAction = command;
494 
495 	if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
496 		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
497 	else {
498 		// TODO: we assume NTSC for now
499 		args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
500 	}
501 
502 	args.sTVEncoder.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
503 
504 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
505 }
506 
507 
508 status_t
509 encoder_digital_setup(uint32 connectorIndex, uint32 pixelClock, int command)
510 {
511 	TRACE("%s: connector %" B_PRIu32 ", pixelClock: %" B_PRIu32 "\n", __func__,
512 		connectorIndex, pixelClock);
513 
514 	int index = 0;
515 	uint16 connectorFlags = gConnector[connectorIndex]->flags;
516 
517 	switch (gConnector[connectorIndex]->encoder.objectID) {
518 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
519 			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
520 			break;
521 		case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
522 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
523 			index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
524 			break;
525 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
526 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
527 				index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
528 			else
529 				index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
530 			break;
531 	}
532 
533 	// Table verson
534 	uint8 tableMajor;
535 	uint8 tableMinor;
536 
537 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
538 		!= B_OK) {
539 		ERROR("%s: cannot parse command table\n", __func__);
540 		return B_ERROR;
541 	}
542 
543 	uint32 lvdsFlags = gConnector[connectorIndex]->lvdsFlags;
544 
545 	bool isHdmi = false;
546 	if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_HDMIA
547 		|| gConnector[connectorIndex]->type == VIDEO_CONNECTOR_HDMIB) {
548 		isHdmi = true;
549 	}
550 
551 	// Prepare AtomBIOS command arguments
552 	union lvdsEncoderControl {
553 		LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
554 		LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
555 	};
556 	union lvdsEncoderControl args;
557 	memset(&args, 0, sizeof(args));
558 
559 	TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
560 		tableMajor, tableMinor);
561 
562 	switch (tableMajor) {
563 	case 1:
564 	case 2:
565 		switch (tableMinor) {
566 			case 1:
567 				args.v1.ucMisc = 0;
568 				args.v1.ucAction = command;
569 				if (isHdmi)
570 					args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
571 				args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
572 
573 				if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
574 					if ((lvdsFlags & ATOM_PANEL_MISC_DUAL) != 0)
575 						args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
576 					if ((lvdsFlags & ATOM_PANEL_MISC_888RGB) != 0)
577 						args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
578 				} else {
579 					//if (dig->linkb)
580 					//	args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
581 					if (pixelClock > 165000)
582 						args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
583 					/*if (pScrn->rgbBits == 8) */
584 					args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
585 				}
586 				break;
587 			case 2:
588 			case 3:
589 				args.v2.ucMisc = 0;
590 				args.v2.ucAction = command;
591 				if (tableMinor == 3) {
592 					//if (dig->coherent_mode)
593 					//	args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
594 				}
595 				if (isHdmi)
596 					args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
597 				args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
598 				args.v2.ucTruncate = 0;
599 				args.v2.ucSpatial = 0;
600 				args.v2.ucTemporal = 0;
601 				args.v2.ucFRC = 0;
602 				if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
603 					if ((lvdsFlags & ATOM_PANEL_MISC_DUAL) != 0)
604 						args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
605 					if ((lvdsFlags & ATOM_PANEL_MISC_SPATIAL) != 0) {
606 						args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
607 						if ((lvdsFlags & ATOM_PANEL_MISC_888RGB) != 0) {
608 							args.v2.ucSpatial
609 								|= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
610 						}
611 					}
612 
613 					if ((lvdsFlags & ATOM_PANEL_MISC_TEMPORAL) != 0) {
614 						args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
615 						if ((lvdsFlags & ATOM_PANEL_MISC_888RGB) != 0) {
616 							args.v2.ucTemporal
617 								|= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
618 						}
619 						if (((lvdsFlags >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT)
620 							& 0x3) == 2) {
621 							args.v2.ucTemporal
622 							|= PANEL_ENCODER_TEMPORAL_LEVEL_4;
623 						}
624 					}
625 				} else {
626 					//if (dig->linkb)
627 					//	args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
628 					if (pixelClock > 165000)
629 						args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
630 				}
631 				break;
632 			default:
633 				ERROR("%s: Unknown minor table version: %"
634 					B_PRIu8 ".%" B_PRIu8 "\n", __func__,
635 					tableMajor, tableMinor);
636 				return B_ERROR;
637 		}
638 		break;
639 	default:
640 		ERROR("%s: Unknown major table version: %" B_PRIu8 ".%" B_PRIu8 "\n",
641 			__func__, tableMajor, tableMinor);
642 		return B_ERROR;
643 	}
644 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
645 }
646 
647 
648 status_t
649 encoder_dig_setup(uint32 connectorIndex, uint32 pixelClock, int command)
650 {
651 	TRACE("%s\n", __func__);
652 
653 	radeon_shared_info &info = *gInfo->shared_info;
654 	connector_info* connector = gConnector[connectorIndex];
655 
656 	int index = 0;
657 	if (info.dceMajor >= 4)
658 		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
659 	else {
660 		if (encoder_pick_dig(connectorIndex))
661 			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
662 		else
663 			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
664 	}
665 
666 	// Table verson
667 	uint8 tableMajor;
668 	uint8 tableMinor;
669 
670 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
671 		!= B_OK) {
672 		ERROR("%s: cannot parse command table\n", __func__);
673 		return B_ERROR;
674 	}
675 
676 	// Prepare AtomBIOS command arguments
677 	union digEncoderControl {
678 		DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
679 		DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
680 		DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
681 		DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
682 		DIG_ENCODER_CONTROL_PARAMETERS_V5 v5;
683 	};
684 	union digEncoderControl args;
685 	memset(&args, 0, sizeof(args));
686 
687 	bool isDPBridge = connector->encoderExternal.isDPBridge;
688 	bool linkB = connector->encoder.linkEnumeration
689 		== GRAPH_OBJECT_ENUM_ID2 ? true : false;
690 	uint32 digEncoderID = encoder_pick_dig(connectorIndex);
691 
692 	uint32 panelMode = 0;
693 	// determine DP panel mode if doing panel mode setup
694 	if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) {
695 		if (info.dceMajor >= 4 && isDPBridge) {
696 			if (connector->encoderExternal.objectID == ENCODER_OBJECT_ID_NUTMEG)
697 				panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
698 			else if (connector->encoderExternal.objectID
699 				== ENCODER_OBJECT_ID_TRAVIS) {
700 				dp_info* dp = &gConnector[connectorIndex]->dpInfo;
701 				uint8 id[6];
702 				int bit;
703 				for (bit = 0; bit < 6; bit++)
704 					id[bit] = dpcd_reg_read(dp->auxPin, 0x503 + bit);
705 				if (id[0] == 0x73 && id[1] == 0x69 && id[2] == 0x76
706 					&& id[3] == 0x61 && id[4] == 0x72 && id[5] == 0x54) {
707 					panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
708 				} else {
709 					panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
710 				}
711 			} else {
712 				panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
713 			}
714 		} else
715 			panelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
716 	}
717 
718 	#if 0
719 	uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
720 	if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) {
721 		uint8 temp = dpcd_read_reg(hwPin, DP_EDP_CONFIGURATION_CAP);
722 		if ((temp & 1) != 0)
723 			panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
724 	}
725 	#endif
726 
727 	TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
728 		tableMajor, tableMinor);
729 
730 	dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
731 	uint32 dpClock = 0;
732 	if (dpInfo->valid == true)
733 		dpClock = dpInfo->linkRate;
734 
735 	bool dualLink = false;
736 	if (connector->type == VIDEO_CONNECTOR_DVID
737 		&& pixelClock > 165000) {
738 		// TODO: Expand on this duallink code
739 		dualLink = true;
740 	}
741 
742 	uint32 encoderMode = display_get_encoder_mode(connectorIndex);
743 
744 	// Careful! The mapping of ucHPD_ID differs between atombios calls
745 	uint16 hpdID = connector_pick_atom_hpdid(connectorIndex);
746 
747 	if (tableMajor != 1) {
748 		ERROR("%s: Unknown table major!\n", __func__);
749 	}
750 
751 	switch (tableMinor) {
752 		case 1:
753 			args.v1.ucAction = command;
754 			args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
755 
756 			if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
757 				args.v3.ucPanelMode = panelMode;
758 			else {
759 				args.v1.ucEncoderMode = encoderMode;
760 			}
761 
762 			if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
763 				|| args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
764 				args.v1.ucLaneNum = dpInfo->laneCount;
765 			} else if (dualLink)
766 				args.v1.ucLaneNum = 8;
767 			else
768 				args.v1.ucLaneNum = 4;
769 
770 			if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
771 				|| args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)
772 				&& dpClock == 270000) {
773 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
774 			}
775 
776 			switch (connector->encoder.objectID) {
777 				case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
778 					args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
779 					break;
780 				case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
781 				case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
782 					args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
783 					break;
784 				case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
785 					args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
786 					break;
787 			}
788 
789 			if (linkB)
790 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
791 			else
792 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
793 			break;
794 		case 2:
795 		case 3:
796 			args.v3.ucAction = command;
797 			args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
798 
799 			if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
800 				args.v3.ucPanelMode = panelMode;
801 			else
802 				args.v3.ucEncoderMode = encoderMode;
803 
804 			if (args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP
805 				|| args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
806 				args.v3.ucLaneNum = dpInfo->laneCount;
807 			} else if (dualLink)
808 				args.v3.ucLaneNum = 8;
809 			else
810 				args.v3.ucLaneNum = 4;
811 
812 			if ((args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP
813 				|| args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)
814 				&& dpClock == 270000) {
815 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
816 			}
817 
818 			args.v3.acConfig.ucDigSel = encoder_pick_dig(connectorIndex);
819 			args.v3.ucBitPerColor = encoder_get_bpc();
820 			break;
821 		case 4:
822 			args.v4.ucAction = command;
823 			args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
824 
825 			if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
826 				args.v4.ucPanelMode = panelMode;
827 			else
828 				args.v4.ucEncoderMode = encoderMode;
829 
830 			if (args.v4.ucEncoderMode == ATOM_ENCODER_MODE_DP
831 				|| args.v4.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
832 				// Is DP?
833 				args.v4.ucLaneNum = dpInfo->laneCount;
834 				if (dpClock == 270000) {
835 					args.v4.ucConfig
836 						|= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
837 				} else if (dpClock == 540000) {
838 					args.v4.ucConfig
839 						|= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
840 				}
841 			} else if (dualLink) {
842 				// DualLink, double the lane numbers
843 				args.v4.ucLaneNum = 8;
844 			} else {
845 				args.v4.ucLaneNum = 4;
846 			}
847 			args.v4.acConfig.ucDigSel = digEncoderID;
848 			args.v4.ucBitPerColor = encoder_get_bpc();
849 
850 			if (hpdID == 0xff)
851 				args.v4.ucHPD_ID = 0;
852 			else
853 				args.v4.ucHPD_ID = hpdID + 1;
854 			break;
855 		case 5:
856 			switch(command) {
857 				case ATOM_ENCODER_CMD_SETUP_PANEL_MODE:
858 					args.v5.asDPPanelModeParam.ucAction = command;
859 					args.v5.asDPPanelModeParam.ucPanelMode = panelMode;
860 					args.v5.asDPPanelModeParam.ucDigId = digEncoderID;
861 					break;
862 				case ATOM_ENCODER_CMD_STREAM_SETUP:
863 					args.v5.asStreamParam.ucAction = command;
864 					args.v5.asStreamParam.ucDigId = digEncoderID;
865 					args.v5.asStreamParam.ucDigMode = encoderMode;
866 					if (encoderMode == ATOM_ENCODER_MODE_DP
867 						|| encoderMode == ATOM_ENCODER_MODE_DP_MST) {
868 						args.v5.asStreamParam.ucLaneNum = dpInfo->laneCount;
869 					} else if (dualLink)
870 						args.v5.asStreamParam.ucLaneNum = 8;
871 					else
872 						args.v5.asStreamParam.ucLaneNum = 4;
873 					args.v5.asStreamParam.ulPixelClock
874 						= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
875 					args.v5.asStreamParam.ucBitPerColor = encoder_get_bpc();
876 					args.v5.asStreamParam.ucLinkRateIn270Mhz = dpClock / 27000;
877 					break;
878 				case ATOM_ENCODER_CMD_DP_LINK_TRAINING_START:
879 				case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1:
880 				case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2:
881 				case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3:
882 				case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN4:
883 				case ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE:
884 				case ATOM_ENCODER_CMD_DP_VIDEO_OFF:
885 				case ATOM_ENCODER_CMD_DP_VIDEO_ON:
886 					args.v5.asCmdParam.ucAction = command;
887 					args.v5.asCmdParam.ucDigId = digEncoderID;
888 					break;
889 				default:
890 					ERROR("%s: Unknown command: 0x%X\n", __func__, command);
891 			}
892 			break;
893 		default:
894 			ERROR("%s: unknown tableMinor!\n", __func__);
895 			return B_ERROR;
896 	}
897 
898 	status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args);
899 
900 	#if 0
901 	if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP
902 		&& panelMode == DP_PANEL_MODE_INTERNAL_DP2_MODE) {
903 		dpcd_write_reg(hwPin, DP_EDP_CONFIGURATION_SET, 1);
904 	}
905 	#endif
906 
907 	return result;
908 }
909 
910 
911 status_t
912 encoder_external_setup(uint32 connectorIndex, int command)
913 {
914 	TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
915 
916 	encoder_info* encoder
917 		= &gConnector[connectorIndex]->encoder;
918 	encoder_info* extEncoder
919 		= &gConnector[connectorIndex]->encoderExternal;
920 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
921 
922 	dp_info* dpInfo
923 		= &gConnector[connectorIndex]->dpInfo;
924 
925 	if (extEncoder->valid != true) {
926 		ERROR("%s: connector %" B_PRIu32 " doesn't have a valid "
927 			"external encoder!", __func__, connectorIndex);
928 		return B_ERROR;
929 	}
930 
931 	uint8 tableMajor;
932 	uint8 tableMinor;
933 
934 	int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
935 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
936 		!= B_OK) {
937 		ERROR("%s: Error parsing ExternalEncoderControl table\n", __func__);
938 		return B_ERROR;
939 	}
940 
941 	// Prepare AtomBIOS command arguments
942 	union externalEncoderControl {
943 		EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1;
944 		EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3;
945 	};
946 	union externalEncoderControl args;
947 	memset(&args, 0, sizeof(args));
948 
949 	int connectorObjectID
950 		= (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK)
951 			>> OBJECT_ID_SHIFT;
952 
953 	uint32 pixelClock = encoder->pll.pixelClock;
954 
955 	TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
956 		tableMajor, tableMinor);
957 	switch (tableMajor) {
958 		case 1:
959 			// no options needed on table 1.x
960 			break;
961 		case 2:
962 			switch (tableMinor) {
963 				case 1:
964 				case 2:
965 					args.v1.sDigEncoder.ucAction = command;
966 					args.v1.sDigEncoder.usPixelClock
967 						= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
968 					args.v1.sDigEncoder.ucEncoderMode
969 						= display_get_encoder_mode(connectorIndex);
970 
971 					if (connector_is_dp(connectorIndex)) {
972 						if (dpInfo->linkRate == 270000) {
973 							args.v1.sDigEncoder.ucConfig
974 								|= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
975 						}
976 						args.v1.sDigEncoder.ucLaneNum
977 							= dpInfo->laneCount;
978 					} else if (pixelClock > 165000) {
979 						args.v1.sDigEncoder.ucLaneNum = 8;
980 					} else {
981 						args.v1.sDigEncoder.ucLaneNum = 4;
982 					}
983 					break;
984 				case 3:
985 				{
986 					args.v3.sExtEncoder.ucAction = command;
987 					if (command == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) {
988 						args.v3.sExtEncoder.usConnectorId
989 							= B_HOST_TO_LENDIAN_INT16(connectorObjectID);
990 					} else {
991 						args.v3.sExtEncoder.usPixelClock
992 							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
993 					}
994 
995 					args.v3.sExtEncoder.ucEncoderMode
996 						= display_get_encoder_mode(connectorIndex);
997 
998 					if (connector_is_dp(connectorIndex)) {
999 						if (dpInfo->linkRate == 270000) {
1000 							args.v3.sExtEncoder.ucConfig
1001 								|=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
1002 						} else if (dpInfo->linkRate == 540000) {
1003 							args.v3.sExtEncoder.ucConfig
1004 								|=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
1005 						}
1006 						args.v1.sDigEncoder.ucLaneNum
1007 							= dpInfo->laneCount;
1008 					} else if (pixelClock > 165000) {
1009 						args.v3.sExtEncoder.ucLaneNum = 8;
1010 					} else {
1011 						args.v3.sExtEncoder.ucLaneNum = 4;
1012 					}
1013 
1014 					switch ((connectorFlags & ENUM_ID_MASK) >> ENUM_ID_SHIFT) {
1015 						case GRAPH_OBJECT_ENUM_ID1:
1016 							TRACE("%s: external encoder 1\n", __func__);
1017 							args.v3.sExtEncoder.ucConfig
1018 								|= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1;
1019 							break;
1020 						case GRAPH_OBJECT_ENUM_ID2:
1021 							TRACE("%s: external encoder 2\n", __func__);
1022 							args.v3.sExtEncoder.ucConfig
1023 								|= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2;
1024 							break;
1025 						case GRAPH_OBJECT_ENUM_ID3:
1026 							TRACE("%s: external encoder 3\n", __func__);
1027 							args.v3.sExtEncoder.ucConfig
1028 								|= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3;
1029 							break;
1030 					}
1031 
1032 					// TODO: don't set statically
1033 					uint32 bitsPerColor = 8;
1034 					switch (bitsPerColor) {
1035 						case 0:
1036 							args.v3.sExtEncoder.ucBitPerColor
1037 								= PANEL_BPC_UNDEFINE;
1038 							break;
1039 						case 6:
1040 							args.v3.sExtEncoder.ucBitPerColor
1041 								= PANEL_6BIT_PER_COLOR;
1042 							break;
1043 						case 8:
1044 						default:
1045 							args.v3.sExtEncoder.ucBitPerColor
1046 								= PANEL_8BIT_PER_COLOR;
1047 							break;
1048 						case 10:
1049 							args.v3.sExtEncoder.ucBitPerColor
1050 								= PANEL_10BIT_PER_COLOR;
1051 							break;
1052 						case 12:
1053 							args.v3.sExtEncoder.ucBitPerColor
1054 								= PANEL_12BIT_PER_COLOR;
1055 							break;
1056 						case 16:
1057 							args.v3.sExtEncoder.ucBitPerColor
1058 								= PANEL_16BIT_PER_COLOR;
1059 							break;
1060 					}
1061 					break;
1062 				}
1063 				default:
1064 					ERROR("%s: Unknown table minor version: "
1065 						"%" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
1066 						tableMajor, tableMinor);
1067 					return B_ERROR;
1068 			}
1069 			break;
1070 		default:
1071 			ERROR("%s: Unknown table major version: "
1072 				"%" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
1073 				tableMajor, tableMinor);
1074 			return B_ERROR;
1075 	}
1076 
1077 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
1078 }
1079 
1080 
1081 status_t
1082 encoder_analog_setup(uint32 connectorIndex, uint32 pixelClock, int command)
1083 {
1084 	TRACE("%s: connector %" B_PRIu32 ", pixelClock: %" B_PRIu32 "\n", __func__,
1085 		connectorIndex, pixelClock);
1086 
1087 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1088 
1089 	int index = 0;
1090 	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
1091 	memset(&args, 0, sizeof(args));
1092 
1093 	switch (gConnector[connectorIndex]->encoder.objectID) {
1094 		case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1095 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1096 			index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
1097 			break;
1098 		case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1099 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1100 			index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
1101 			break;
1102 	}
1103 
1104 	args.ucAction = command;
1105 
1106 	if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
1107 		args.ucDacStandard = ATOM_DAC1_PS2;
1108 	else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1109 		args.ucDacStandard = ATOM_DAC1_CV;
1110 	else {
1111 		TRACE("%s: TODO, hardcoded NTSC TV support\n", __func__);
1112 		if (1) {
1113 			// NTSC, NTSC_J, PAL 60
1114 			args.ucDacStandard = ATOM_DAC1_NTSC;
1115 		} else {
1116 			// PAL, SCART. SECAM, PAL_CN
1117 			args.ucDacStandard = ATOM_DAC1_PAL;
1118 		}
1119 	}
1120 
1121 	args.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1122 
1123 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
1124 }
1125 
1126 
1127 bool
1128 encoder_analog_load_detect(uint32 connectorIndex)
1129 {
1130 	TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
1131 
1132 	if (gConnector[connectorIndex]->encoderExternal.valid == true)
1133 		return encoder_dig_load_detect(connectorIndex);
1134 
1135 	return encoder_dac_load_detect(connectorIndex);
1136 }
1137 
1138 
1139 bool
1140 encoder_dac_load_detect(uint32 connectorIndex)
1141 {
1142 	TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
1143 
1144 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1145 	uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
1146 
1147 	if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) == 0
1148 		&& (connectorFlags & ATOM_DEVICE_CV_SUPPORT) == 0
1149 		&& (connectorFlags & ATOM_DEVICE_CRT_SUPPORT) == 0) {
1150 		ERROR("%s: executed on non-dac device connector #%" B_PRIu8 "\n",
1151 			__func__, connectorIndex);
1152 		return false;
1153 	}
1154 
1155 	// *** tell the card we want to do a DAC detection
1156 
1157 	DAC_LOAD_DETECTION_PS_ALLOCATION args;
1158 	int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1159 	uint8 tableMajor;
1160 	uint8 tableMinor;
1161 
1162 	memset(&args, 0, sizeof(args));
1163 
1164 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
1165 		!= B_OK) {
1166 		ERROR("%s: failed getting AtomBIOS header for DAC_LoadDetection\n",
1167 			__func__);
1168 		return false;
1169 	}
1170 
1171 	args.sDacload.ucMisc = 0;
1172 
1173 	if (encoderID == ENCODER_OBJECT_ID_INTERNAL_DAC1
1174 		|| encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) {
1175 		args.sDacload.ucDacType = ATOM_DAC_A;
1176 	} else {
1177 		args.sDacload.ucDacType = ATOM_DAC_B;
1178 	}
1179 
1180 	if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1181 		args.sDacload.usDeviceID
1182 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT1_SUPPORT);
1183 		atom_execute_table(gAtomContext, index, (uint32*)&args);
1184 
1185 		uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1186 
1187 		if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0)
1188 			return true;
1189 
1190 	} else if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1191 		args.sDacload.usDeviceID
1192 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT2_SUPPORT);
1193 		atom_execute_table(gAtomContext, index, (uint32*)&args);
1194 
1195 		uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1196 
1197 		if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0)
1198 			return true;
1199 
1200 	} else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1201 		args.sDacload.usDeviceID
1202 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CV_SUPPORT);
1203 		if (tableMinor >= 3)
1204 			args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1205 		atom_execute_table(gAtomContext, index, (uint32*)&args);
1206 
1207 		uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1208 
1209 		if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0)
1210 			return true;
1211 
1212 	} else if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1213 		args.sDacload.usDeviceID
1214 			= B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_TV1_SUPPORT);
1215 		if (tableMinor >= 3)
1216 			args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1217 		atom_execute_table(gAtomContext, index, (uint32*)&args);
1218 
1219 		uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1220 
1221 		if ((biosScratch0
1222 			& (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) {
1223 			return true; /* Composite connected */
1224 		} else if ((biosScratch0
1225 			& (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) {
1226 			return true; /* S-Video connected */
1227 		}
1228 
1229 	}
1230 	return false;
1231 }
1232 
1233 
1234 bool
1235 encoder_dig_load_detect(uint32 connectorIndex)
1236 {
1237 	TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
1238 	radeon_shared_info &info = *gInfo->shared_info;
1239 
1240 	if (info.dceMajor < 4) {
1241 		ERROR("%s: Strange: External DIG encoder on DCE < 4?\n", __func__);
1242 		return false;
1243 	}
1244 
1245 	encoder_external_setup(connectorIndex,
1246 		EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
1247 
1248 	uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0);
1249 
1250 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1251 
1252 	if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0)
1253 		if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0)
1254 			return true;
1255 	if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0)
1256 		if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0)
1257 			return true;
1258 	if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1259 		if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0)
1260 			return true;
1261 	if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1262 		if ((biosScratch0
1263 			& (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0)
1264 			return true; /* Composite connected */
1265 		else if ((biosScratch0
1266 			& (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0)
1267 			return true; /* S-Video connected */
1268 	}
1269 
1270 	return false;
1271 }
1272 
1273 
1274 status_t
1275 transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock,
1276 	uint8 laneNumber, uint8 laneSet, int command)
1277 {
1278 	TRACE("%s: connector %" B_PRIu32 ", pixelClock: %" B_PRIu32 "\n", __func__,
1279 		connectorIndex, pixelClock);
1280 
1281 	uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
1282 	int index;
1283 	switch (encoderID) {
1284 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1285 			index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1286 			break;
1287 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1288 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1289 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1290 			index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
1291 			break;
1292 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1293 			index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl);
1294 			break;
1295 		default:
1296 			ERROR("%s: BUG: dig setup run on non-dig encoder!\n", __func__);
1297 			return B_ERROR;
1298 	}
1299 
1300 	if (index < 0) {
1301 		ERROR("%s: GetIndexIntoMasterTable failed!\n", __func__);
1302 		return B_ERROR;
1303 	}
1304 
1305 	uint8 tableMajor;
1306 	uint8 tableMinor;
1307 
1308 	if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
1309 		!= B_OK)
1310 		return B_ERROR;
1311 
1312 	// Prepare AtomBIOS arguments
1313 	union digTransmitterControl {
1314 		DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
1315 		DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
1316 		DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
1317 		DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
1318 		DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
1319 		DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 v6;
1320 	};
1321 	union digTransmitterControl args;
1322 	memset(&args, 0, sizeof(args));
1323 
1324 	TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
1325 		tableMajor, tableMinor);
1326 
1327 	int connectorObjectID
1328 		= (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK)
1329 			>> OBJECT_ID_SHIFT;
1330 	uint32 encoderObjectID = gConnector[connectorIndex]->encoder.objectID;
1331 	uint32 digEncoderID = encoder_pick_dig(connectorIndex);
1332 
1333 	pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
1334 
1335 	// Careful! The mapping of ucHPD_ID differs between atombios calls
1336 	uint16 hpdID = connector_pick_atom_hpdid(connectorIndex);
1337 
1338 	bool isDP = connector_is_dp(connectorIndex);
1339 	bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
1340 		== GRAPH_OBJECT_ENUM_ID2 ? true : false;
1341 
1342 	dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
1343 
1344 	uint32 dpClock = 0;
1345 	int dpLaneCount = 0;
1346 	if (dpInfo->valid == true) {
1347 		dpClock = dpInfo->linkRate;
1348 		dpLaneCount = dpInfo->laneCount;
1349 	}
1350 
1351 	switch (tableMajor) {
1352 		case 1:
1353 			switch (tableMinor) {
1354 				case 1:
1355 					args.v1.ucAction = command;
1356 					if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1357 						args.v1.usInitInfo
1358 							= B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1359 					} else if (command
1360 						== ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1361 						args.v1.asMode.ucLaneSel = laneNumber;
1362 						args.v1.asMode.ucLaneSet = laneSet;
1363 					} else {
1364 						if (isDP) {
1365 							args.v1.usPixelClock
1366 								= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1367 						} else if (pixelClock > 165000) {
1368 							args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1369 								(pixelClock / 2) / 10);
1370 						} else {
1371 							args.v1.usPixelClock
1372 								= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1373 						}
1374 					}
1375 
1376 					args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
1377 
1378 					if (digEncoderID > 0) {
1379 						args.v1.ucConfig
1380 							|= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
1381 					} else {
1382 						args.v1.ucConfig
1383 							|= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
1384 					}
1385 
1386 					// TODO: IGP DIG Transmitter setup
1387 					#if 0
1388 					if ((rdev->flags & RADEON_IS_IGP) && (encoderObjectID
1389 						== ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
1390 						if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
1391 							if (igp_lane_info & 0x1)
1392 								args.v1.ucConfig
1393 									|= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
1394 							else if (igp_lane_info & 0x2)
1395 								args.v1.ucConfig
1396 									|= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
1397 							else if (igp_lane_info & 0x4)
1398 								args.v1.ucConfig
1399 									|= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
1400 							else if (igp_lane_info & 0x8)
1401 								args.v1.ucConfig
1402 									|= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
1403 						} else {
1404 							if (igp_lane_info & 0x3)
1405 								args.v1.ucConfig
1406 									|= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
1407 							else if (igp_lane_info & 0xc)
1408 								args.v1.ucConfig
1409 									|= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
1410 						}
1411 					}
1412 					#endif
1413 
1414 					if (linkB == true)
1415 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
1416 					else
1417 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
1418 
1419 					if (isDP)
1420 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
1421 					else if ((gConnector[connectorIndex]->flags
1422 						& ATOM_DEVICE_DFP_SUPPORT) != 0) {
1423 						if (1) {
1424 							// if coherentMode, i've only ever seen it true
1425 							args.v1.ucConfig
1426 								|= ATOM_TRANSMITTER_CONFIG_COHERENT;
1427 						}
1428 						if (pixelClock > 165000) {
1429 							args.v1.ucConfig
1430 								|= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
1431 						}
1432 					}
1433 					break;
1434 				case 2:
1435 					args.v2.ucAction = command;
1436 					if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1437 						args.v2.usInitInfo
1438 							= B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1439 					} else if (command
1440 						== ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1441 						args.v2.asMode.ucLaneSel = laneNumber;
1442 						args.v2.asMode.ucLaneSet = laneSet;
1443 					} else {
1444 						if (isDP) {
1445 							args.v2.usPixelClock
1446 								= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1447 						} else if (pixelClock > 165000) {
1448 							args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1449 								(pixelClock / 2) / 10);
1450 						} else {
1451 							args.v2.usPixelClock
1452 								= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1453 						}
1454 					}
1455 					args.v2.acConfig.ucEncoderSel = digEncoderID;
1456 					if (linkB)
1457 						args.v2.acConfig.ucLinkSel = 1;
1458 
1459 					switch (encoderObjectID) {
1460 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1461 							args.v2.acConfig.ucTransmitterSel = 0;
1462 							break;
1463 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1464 							args.v2.acConfig.ucTransmitterSel = 1;
1465 							break;
1466 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1467 							args.v2.acConfig.ucTransmitterSel = 2;
1468 							break;
1469 					}
1470 
1471 					if (isDP) {
1472 						args.v2.acConfig.fCoherentMode = 1;
1473 						args.v2.acConfig.fDPConnector = 1;
1474 					} else if ((gConnector[connectorIndex]->flags
1475 						& ATOM_DEVICE_DFP_SUPPORT) != 0) {
1476 						if (1) {
1477 							// if coherentMode, i've only ever seen it true
1478 							args.v2.acConfig.fCoherentMode = 1;
1479 						}
1480 
1481 						if (pixelClock > 165000)
1482 							args.v2.acConfig.fDualLinkConnector = 1;
1483 					}
1484 					break;
1485 				case 3:
1486 					args.v3.ucAction = command;
1487 					if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1488 						args.v3.usInitInfo
1489 							= B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1490 					} else if (command
1491 						== ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1492 						args.v3.asMode.ucLaneSel = laneNumber;
1493 						args.v3.asMode.ucLaneSet = laneSet;
1494 					} else {
1495 						if (isDP) {
1496 							args.v3.usPixelClock
1497 								= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1498 						} else if (pixelClock > 165000) {
1499 							args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1500 								(pixelClock / 2) / 10);
1501 						} else {
1502 							args.v3.usPixelClock
1503 								= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1504 						}
1505 					}
1506 
1507 					if (isDP)
1508 						args.v3.ucLaneNum = dpLaneCount;
1509 					else if (pixelClock > 165000)
1510 						args.v3.ucLaneNum = 8;
1511 					else
1512 						args.v3.ucLaneNum = 4;
1513 
1514 					if (linkB == true)
1515 						args.v3.acConfig.ucLinkSel = 1;
1516 					if (digEncoderID & 1)
1517 						args.v3.acConfig.ucEncoderSel = 1;
1518 
1519 					// Select the PLL for the PHY
1520 					// DP PHY to be clocked from external src if possible
1521 
1522 					// DCE4 has external DCPLL clock for DP
1523 					if (isDP && gInfo->dpExternalClock) {
1524 						// use external clock source (id'ed to 2 on DCE4)
1525 						args.v3.acConfig.ucRefClkSource = 2; // EXT clock
1526 					} else
1527 						args.v3.acConfig.ucRefClkSource = pll->id;
1528 
1529 					switch (encoderObjectID) {
1530 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1531 							args.v3.acConfig.ucTransmitterSel = 0;
1532 							break;
1533 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1534 							args.v3.acConfig.ucTransmitterSel = 1;
1535 							break;
1536 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1537 							args.v3.acConfig.ucTransmitterSel = 2;
1538 							break;
1539 					}
1540 
1541 					if (isDP)
1542 						args.v3.acConfig.fCoherentMode = 1;
1543 					else if ((gConnector[connectorIndex]->flags
1544 						& ATOM_DEVICE_DFP_SUPPORT) != 0) {
1545 						if (1) {
1546 							// if coherentMode, i've only ever seen it true
1547 							args.v3.acConfig.fCoherentMode = 1;
1548 						}
1549 						if (pixelClock > 165000)
1550 							args.v3.acConfig.fDualLinkConnector = 1;
1551 					}
1552 					break;
1553 				case 4:
1554 					args.v4.ucAction = command;
1555 					if (command == ATOM_TRANSMITTER_ACTION_INIT) {
1556 						args.v4.usInitInfo
1557 							= B_HOST_TO_LENDIAN_INT16(connectorObjectID);
1558 					} else if (command
1559 						== ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
1560 						args.v4.asMode.ucLaneSel = laneNumber;
1561 						args.v4.asMode.ucLaneSet = laneSet;
1562 					} else {
1563 						if (isDP) {
1564 							args.v4.usPixelClock
1565 								= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1566 						} else if (pixelClock > 165000) {
1567 							args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16(
1568 								(pixelClock / 2) / 10);
1569 						} else {
1570 							args.v4.usPixelClock
1571 								= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1572 						}
1573 					}
1574 
1575 					if (isDP)
1576 						args.v4.ucLaneNum = dpLaneCount;
1577 					else if (pixelClock > 165000)
1578 						args.v4.ucLaneNum = 8;
1579 					else
1580 						args.v4.ucLaneNum = 4;
1581 
1582 					if (linkB == true)
1583 						args.v4.acConfig.ucLinkSel = 1;
1584 					if (digEncoderID & 1)
1585 						args.v4.acConfig.ucEncoderSel = 1;
1586 
1587 					// Select the PLL for the PHY
1588 					// DP PHY to be clocked from external src if possible
1589 					// DCE5, DCPLL usually generates the DP ref clock
1590 					if (isDP) {
1591 						if (gInfo->dpExternalClock > 0) {
1592 							args.v4.acConfig.ucRefClkSource
1593 								= ENCODER_REFCLK_SRC_EXTCLK;
1594 						} else {
1595 							args.v4.acConfig.ucRefClkSource
1596 								= ENCODER_REFCLK_SRC_DCPLL;
1597 						}
1598 					} else
1599 						args.v4.acConfig.ucRefClkSource = pll->id;
1600 
1601 					switch (encoderObjectID) {
1602 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1603 							args.v4.acConfig.ucTransmitterSel = 0;
1604 							break;
1605 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1606 							args.v4.acConfig.ucTransmitterSel = 1;
1607 							break;
1608 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1609 							args.v4.acConfig.ucTransmitterSel = 2;
1610 							break;
1611 					}
1612 
1613 					if (isDP)
1614 						args.v4.acConfig.fCoherentMode = 1;
1615 					else if ((gConnector[connectorIndex]->flags
1616 						& ATOM_DEVICE_DFP_SUPPORT) != 0) {
1617 						if (1) {
1618 							// if coherentMode, i've only ever seen it true
1619 							args.v4.acConfig.fCoherentMode = 1;
1620 						}
1621 						if (pixelClock > 165000)
1622 							args.v4.acConfig.fDualLinkConnector = 1;
1623 					}
1624 					break;
1625 				case 5:
1626 					args.v5.ucAction = command;
1627 
1628 					if (isDP) {
1629 						args.v5.usSymClock
1630 							= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1631 					} else {
1632 						args.v5.usSymClock
1633 							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1634 					}
1635 					switch (encoderObjectID) {
1636 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1637 							if (linkB)
1638 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB;
1639 							else
1640 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA;
1641 							break;
1642 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1643 							if (linkB)
1644 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD;
1645 							else
1646 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC;
1647 							break;
1648 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1649 							if (linkB)
1650 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF;
1651 							else
1652 								args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE;
1653 							break;
1654 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
1655 							args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYG;
1656 					}
1657 					if (isDP) {
1658 						args.v5.ucLaneNum = dpLaneCount;
1659 					} else if (pixelClock >= 165000) {
1660 						args.v5.ucLaneNum = 8;
1661 					} else {
1662 						args.v5.ucLaneNum = 4;
1663 					}
1664 
1665 					args.v5.ucConnObjId = connectorObjectID;
1666 
1667 					if (command != ATOM_TRANSMITTER_ACTION_INIT) {
1668 						// not used on INIT and display_get_encoder_mode
1669 						// unavailable until displays are probed.
1670 						args.v5.ucDigMode
1671 							= display_get_encoder_mode(connectorIndex);
1672 					}
1673 
1674 					if (isDP && gInfo->dpExternalClock) {
1675 						args.v5.asConfig.ucPhyClkSrcId
1676 							= ENCODER_REFCLK_SRC_EXTCLK;
1677 					} else {
1678 						args.v5.asConfig.ucPhyClkSrcId = pll->id;
1679 					}
1680 
1681 					if (isDP) {
1682 						args.v5.asConfig.ucCoherentMode = 1;
1683 							// DP always coherent
1684 					} else if ((gConnector[connectorIndex]->flags
1685 						& ATOM_DEVICE_DFP_SUPPORT) != 0) {
1686 						// TODO: dig coherent mode? VVV
1687 						args.v5.asConfig.ucCoherentMode = 1;
1688 					}
1689 
1690 					if (hpdID == 0xff)
1691 						args.v5.asConfig.ucHPDSel = 0;
1692 					else
1693 						args.v5.asConfig.ucHPDSel = hpdID + 1;
1694 
1695 					args.v5.ucDigEncoderSel = 1 << digEncoderID;
1696 					args.v5.ucDPLaneSet = laneSet;
1697 					break;
1698 				case 6:
1699 					args.v6.ucAction = command;
1700 					if (isDP) {
1701 						args.v6.ulSymClock
1702 							= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
1703 					} else {
1704 						args.v6.ulSymClock
1705 							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
1706 					}
1707 					switch (encoderObjectID) {
1708 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1709 							if (linkB)
1710 								args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYB;
1711 							else
1712 								args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYA;
1713 							break;
1714 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1715 							if (linkB)
1716 								args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYD;
1717 							else
1718 								args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYC;
1719 							break;
1720 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1721 							if (linkB)
1722 								args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYF;
1723 							else
1724 								args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYE;
1725 							break;
1726 						case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
1727 							args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYG;
1728 							break;
1729 					}
1730 					if (isDP)
1731 						args.v6.ucLaneNum = dpLaneCount;
1732 					else if (pixelClock > 165000)
1733 						args.v6.ucLaneNum = 8;
1734 					else
1735 						args.v6.ucLaneNum = 4;
1736 
1737 					args.v6.ucConnObjId = connectorObjectID;
1738 
1739 					if (command == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH)
1740 						args.v6.ucDPLaneSet = laneSet;
1741 					else if (command != ATOM_TRANSMITTER_ACTION_INIT) {
1742 						// not used on INIT and display_get_encoder_mode
1743 						// unavailable until displays are probed.
1744 						args.v6.ucDigMode
1745 							= display_get_encoder_mode(connectorIndex);
1746 					}
1747 
1748 					if (hpdID == 0xff)
1749 						args.v6.ucHPDSel = 0;
1750 					else
1751 						args.v6.ucHPDSel = hpdID + 1;
1752 
1753 					args.v6.ucDigEncoderSel = 1 << digEncoderID;
1754 					break;
1755 				default:
1756 					ERROR("%s: unknown table version\n", __func__);
1757 			}
1758 			break;
1759 		default:
1760 			ERROR("%s: unknown table version\n", __func__);
1761 	}
1762 
1763 	return atom_execute_table(gAtomContext, index, (uint32*)&args);
1764 }
1765 
1766 
1767 void
1768 encoder_crtc_scratch(uint8 crtcID)
1769 {
1770 	TRACE("%s: display %" B_PRIu8 "\n", __func__, crtcID);
1771 
1772 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1773 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1774 
1775 	// TODO: r500
1776 	uint32 biosScratch3 = Read32(OUT, R600_SCRATCH_REG3);
1777 
1778 	if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1779 		biosScratch3 &= ~ATOM_S3_TV1_CRTC_ACTIVE;
1780 		biosScratch3 |= (crtcID << 18);
1781 	}
1782 	if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1783 		biosScratch3 &= ~ATOM_S3_CV_CRTC_ACTIVE;
1784 		biosScratch3 |= (crtcID << 24);
1785 	}
1786 	if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1787 		biosScratch3 &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
1788 		biosScratch3 |= (crtcID << 16);
1789 	}
1790 	if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1791 		biosScratch3 &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
1792 		biosScratch3 |= (crtcID << 20);
1793 	}
1794 	if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) {
1795 		biosScratch3 &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
1796 		biosScratch3 |= (crtcID << 17);
1797 	}
1798 	if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) {
1799 		biosScratch3 &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
1800 		biosScratch3 |= (crtcID << 19);
1801 	}
1802 	if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) {
1803 		biosScratch3 &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
1804 		biosScratch3 |= (crtcID << 23);
1805 	}
1806 	if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) {
1807 		biosScratch3 &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
1808 		biosScratch3 |= (crtcID << 25);
1809 	}
1810 
1811 	// TODO: r500
1812 	Write32(OUT, R600_SCRATCH_REG3, biosScratch3);
1813 }
1814 
1815 
1816 void
1817 encoder_dpms_scratch(uint8 crtcID, bool power)
1818 {
1819 	TRACE("%s: display %" B_PRIu8 "\n", __func__, crtcID);
1820 
1821 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1822 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1823 
1824 	// TODO: r500
1825 	uint32 biosScratch2 = Read32(OUT, R600_SCRATCH_REG2);
1826 
1827 	if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) {
1828 		if (power == true)
1829 			biosScratch2 &= ~ATOM_S2_TV1_DPMS_STATE;
1830 		else
1831 			biosScratch2 |= ATOM_S2_TV1_DPMS_STATE;
1832 	}
1833 	if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) {
1834 		if (power == true)
1835 			biosScratch2 &= ~ATOM_S2_CV_DPMS_STATE;
1836 		else
1837 			biosScratch2 |= ATOM_S2_CV_DPMS_STATE;
1838 	}
1839 	if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) {
1840 		if (power == true)
1841 			biosScratch2 &= ~ATOM_S2_CRT1_DPMS_STATE;
1842 		else
1843 			biosScratch2 |= ATOM_S2_CRT1_DPMS_STATE;
1844 	}
1845 	if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) {
1846 		if (power == true)
1847 			biosScratch2 &= ~ATOM_S2_CRT2_DPMS_STATE;
1848 		else
1849 			biosScratch2 |= ATOM_S2_CRT2_DPMS_STATE;
1850 	}
1851 	if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) {
1852 		if (power == true)
1853 			biosScratch2 &= ~ATOM_S2_LCD1_DPMS_STATE;
1854 		else
1855 			biosScratch2 |= ATOM_S2_LCD1_DPMS_STATE;
1856 	}
1857 	if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) {
1858 		if (power == true)
1859 			biosScratch2 &= ~ATOM_S2_DFP1_DPMS_STATE;
1860 		else
1861 			biosScratch2 |= ATOM_S2_DFP1_DPMS_STATE;
1862 	}
1863 	if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) {
1864 		if (power == true)
1865 			biosScratch2 &= ~ATOM_S2_DFP2_DPMS_STATE;
1866 		else
1867 			biosScratch2 |= ATOM_S2_DFP2_DPMS_STATE;
1868 	}
1869 	if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) {
1870 		if (power == true)
1871 			biosScratch2 &= ~ATOM_S2_DFP3_DPMS_STATE;
1872 		else
1873 			biosScratch2 |= ATOM_S2_DFP3_DPMS_STATE;
1874 	}
1875 	if ((connectorFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) {
1876 		if (power == true)
1877 			biosScratch2 &= ~ATOM_S2_DFP4_DPMS_STATE;
1878 		else
1879 			biosScratch2 |= ATOM_S2_DFP4_DPMS_STATE;
1880 	}
1881 	if ((connectorFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) {
1882 		if (power == true)
1883 			biosScratch2 &= ~ATOM_S2_DFP5_DPMS_STATE;
1884 		else
1885 			biosScratch2 |= ATOM_S2_DFP5_DPMS_STATE;
1886 	}
1887 	Write32(OUT, R600_SCRATCH_REG2, biosScratch2);
1888 }
1889 
1890 
1891 void
1892 encoder_dpms_set(uint8 crtcID, int mode)
1893 {
1894 	TRACE("%s: display %" B_PRIu8 ", power: %s\n", __func__, crtcID,
1895 		mode == B_DPMS_ON ? "true" : "false");
1896 
1897 	int index = -1;
1898 	radeon_shared_info &info = *gInfo->shared_info;
1899 
1900 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
1901 	memset(&args, 0, sizeof(args));
1902 
1903 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1904 	uint32 connectorFlags = gConnector[connectorIndex]->flags;
1905 	uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
1906 
1907 	switch (encoderID) {
1908 		case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1909 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1910 			index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1911 			break;
1912 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
1913 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
1914 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
1915 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
1916 			encoder_dpms_set_dig(crtcID, mode);
1917 			break;
1918 		case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1919 		case ENCODER_OBJECT_ID_INTERNAL_DDI:
1920 			index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1921 			break;
1922 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
1923 			if (info.dceMajor >= 5)
1924 				encoder_dpms_set_dvo(crtcID, mode);
1925 			else if (info.dceMajor >= 3)
1926 				encoder_dpms_set_dig(crtcID, mode);
1927 			else
1928 				index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1929 			break;
1930 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1931 			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1932 			break;
1933 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
1934 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
1935 				index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
1936 			else
1937 				index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1938 			break;
1939 		case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1940 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
1941 			if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0)
1942 				index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1943 			else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1944 				index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1945 			else
1946 				index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1947 			break;
1948 		case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1949 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
1950 			if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0)
1951 				index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1952 			else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0)
1953 				index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1954 			else
1955 				index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1956 			break;
1957 		// default, none on purpose
1958 	}
1959 
1960 	// If we have an index, we need to execute a table.
1961 	if (index >= 0) {
1962 		switch (mode) {
1963 			case B_DPMS_ON:
1964 				args.ucAction = ATOM_ENABLE;
1965 				break;
1966 			case B_DPMS_STAND_BY:
1967 			case B_DPMS_SUSPEND:
1968 			case B_DPMS_OFF:
1969 				args.ucAction = ATOM_DISABLE;
1970 				break;
1971 		}
1972 
1973 		atom_execute_table(gAtomContext, index, (uint32*)&args);
1974 		if (info.dceMajor < 5) {
1975 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
1976 				args.ucAction = args.ucAction == ATOM_DISABLE
1977 					? ATOM_LCD_BLOFF : ATOM_LCD_BLON;
1978 				atom_execute_table(gAtomContext, index, (uint32*)&args);
1979 			}
1980 		}
1981 		if (info.dceMajor < 4)
1982 			encoder_dpms_scratch(crtcID, true);
1983 	}
1984 }
1985 
1986 
1987 void
1988 encoder_dpms_set_dig(uint8 crtcID, int mode)
1989 {
1990 	TRACE("%s: display %" B_PRIu8 ", power: %s\n", __func__, crtcID,
1991 		mode == B_DPMS_ON ? "true" : "false");
1992 
1993 	radeon_shared_info &info = *gInfo->shared_info;
1994 	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
1995 	connector_info* connector = gConnector[connectorIndex];
1996 	uint32 connectorFlags = connector->flags;
1997 	pll_info* pll = &connector->encoder.pll;
1998 	bool hasExternal = connector->encoderExternal.valid;
1999 	bool travisQuirk = info.dceMajor < 5
2000 		&& (connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0
2001 		&& connector->encoderExternal.objectID == ENCODER_OBJECT_ID_TRAVIS;
2002 
2003 	switch (mode) {
2004 		case B_DPMS_ON:
2005 			if ((info.dceMajor == 4 && info.dceMinor == 1)
2006 				|| info.dceMajor >= 5) {
2007 				// Setup encoder
2008 				encoder_dig_setup(connectorIndex, pll->pixelClock,
2009 					ATOM_ENCODER_CMD_SETUP);
2010 				encoder_dig_setup(connectorIndex, pll->pixelClock,
2011 					ATOM_ENCODER_CMD_SETUP_PANEL_MODE);
2012 			} else if (info.dceMajor >= 4) {
2013 				// Setup encoder
2014 				encoder_dig_setup(connectorIndex, pll->pixelClock,
2015 					ATOM_ENCODER_CMD_SETUP);
2016 			} else {
2017 				// Setup encoder and transmitter
2018 				encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_ENABLE);
2019 				transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
2020 					ATOM_TRANSMITTER_ACTION_SETUP);
2021 			}
2022 
2023 			if (connector->type == VIDEO_CONNECTOR_EDP) {
2024 				// TODO: If VIDEO_CONNECTOR_EDP, ATOM_TRANSMITTER_ACTION_POWER_ON
2025 				ERROR("%s: TODO, edp_panel_power!\n",
2026 					__func__);
2027 			}
2028 
2029 			// Enable transmitter
2030 			transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
2031 				ATOM_TRANSMITTER_ACTION_ENABLE);
2032 
2033 			if (connector_is_dp(connectorIndex)) {
2034 				if (info.dceMajor >= 4) {
2035 					encoder_dig_setup(connectorIndex, pll->pixelClock,
2036 						ATOM_ENCODER_CMD_DP_VIDEO_OFF);
2037 				}
2038 				// dp link train
2039 				dp_link_train(crtcID);
2040 				if (info.dceMajor >= 4) {
2041 					encoder_dig_setup(connectorIndex, pll->pixelClock,
2042 						ATOM_ENCODER_CMD_DP_VIDEO_ON);
2043 				}
2044 				// not sure what AtomBIOS table/command sets this
2045 				// register, but it's required to get the video output
2046 				Write32(OUT, AVIVO_DP_VID_STREAM_CNTL, 0x201);
2047 			}
2048 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
2049 				transmitter_dig_setup(connectorIndex, pll->pixelClock,
2050 					0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLON);
2051 			}
2052 			if (hasExternal)
2053 				encoder_external_setup(connectorIndex, ATOM_ENABLE);
2054 			break;
2055 		case B_DPMS_STAND_BY:
2056 		case B_DPMS_SUSPEND:
2057 		case B_DPMS_OFF:
2058 			if (connector_is_dp(connectorIndex)) {
2059 				if (info.dceMajor >= 4) {
2060 					encoder_dig_setup(connectorIndex, pll->pixelClock,
2061 						ATOM_ENCODER_CMD_DP_VIDEO_OFF);
2062 				}
2063 			}
2064 			if (hasExternal)
2065 				encoder_external_setup(connectorIndex, ATOM_DISABLE);
2066 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
2067 				transmitter_dig_setup(connectorIndex, pll->pixelClock,
2068 					0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLOFF);
2069 			}
2070 			if (connector_is_dp(connectorIndex) && !travisQuirk) {
2071 				// If not TRAVIS on < DCE 5, set_rx_power_state D3
2072 				ERROR("%s: TODO: dpms off set_rx_power_state D3\n", __func__);
2073 			}
2074 			if (info.dceMajor >= 4) {
2075 				// Disable transmitter
2076 				transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
2077 					ATOM_TRANSMITTER_ACTION_DISABLE);
2078 			} else {
2079 				// Disable transmitter and encoder
2080 				transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
2081 					ATOM_TRANSMITTER_ACTION_DISABLE);
2082 				encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_DISABLE);
2083 			}
2084 
2085 			if (connector_is_dp(connectorIndex)) {
2086 				if (travisQuirk) {
2087 					ERROR("%s: TODO: dpms off set_rx_power_state D3\n",
2088 						__func__);
2089 				}
2090 				if (connector->type == VIDEO_CONNECTOR_EDP) {
2091 					// TODO: ATOM_TRANSMITTER_ACTION_POWER_OFF
2092 					ERROR("%s: TODO, edp_panel_power!\n", __func__);
2093 				}
2094 			}
2095 			break;
2096 	}
2097 }
2098 
2099 
2100 void
2101 encoder_dpms_set_dvo(uint8 crtcID, int mode)
2102 {
2103 	ERROR("%s: TODO, dvo encoder dpms stub\n", __func__);
2104 }
2105 
2106 
2107 void
2108 encoder_output_lock(bool lock)
2109 {
2110 	TRACE("%s: %s\n", __func__, lock ? "true" : "false");
2111 	uint32 biosScratch6 = Read32(OUT, R600_SCRATCH_REG6);
2112 
2113 	if (lock) {
2114 		biosScratch6 |= ATOM_S6_CRITICAL_STATE;
2115 		biosScratch6 &= ~ATOM_S6_ACC_MODE;
2116 	} else {
2117 		biosScratch6 &= ~ATOM_S6_CRITICAL_STATE;
2118 		biosScratch6 |= ATOM_S6_ACC_MODE;
2119 	}
2120 
2121 	Write32(OUT, R600_SCRATCH_REG6, biosScratch6);
2122 }
2123 
2124 static const char* encoder_name_matrix[] = {
2125 	"NONE",
2126 	"Internal Radeon LVDS",
2127 	"Internal Radeon TMDS1",
2128 	"Internal Radeon TMDS2",
2129 	"Internal Radeon DAC1",
2130 	"Internal Radeon DAC2 (TV)",
2131 	"Internal Radeon SDVOA",
2132 	"Internal Radeon SDVOB",
2133 	"External 3rd party SI170B",
2134 	"External 3rd party CH7303",
2135 	"External 3rd party CH7301",
2136 	"Internal Radeon DVO1",
2137 	"External 3rd party SDVOA",
2138 	"External 3rd party SDVOB",
2139 	"External 3rd party TITFP513",
2140 	"Internal LVTM1",
2141 	"External 3rd party VT1623",
2142 	"External HDMI SI1930",
2143 	"Internal HDMI",
2144 	"Internal Kaleidoscope TMDS1",
2145 	"Internal Kaleidoscope DVO1",
2146 	"Internal Kaleidoscope DAC1",
2147 	"Internal Kaleidoscope DAC2",
2148 	"External Kaleidoscope SI178",
2149 	"MVPU FPGA",
2150 	"Internal Kaleidoscope DDI",
2151 	"External Kaleidoscope VT1625",
2152 	"External Kaleidoscope HDMI SI1932",
2153 	"External Kaleidoscope DP AN9801",
2154 	"External Kaleidoscope DP DP501",
2155 	"Internal Kaleidoscope UNIPHY",
2156 	"Internal Kaleidoscope LVTMA",
2157 	"Internal Kaleidoscope UNIPHY1",
2158 	"Internal Kaleidoscope UNIPHY2",
2159 	"External Nutmeg Bridge",
2160 	"External Travis Bridge",
2161 	"Internal Kaleidoscope VCE"
2162 };
2163 
2164 
2165 const char*
2166 encoder_name_lookup(uint32 encoderID) {
2167 	if (encoderID < B_COUNT_OF(encoder_name_matrix))
2168 		return encoder_name_matrix[encoderID];
2169 	else
2170 		return "Unknown";
2171 }
2172 
2173 
2174 uint32
2175 encoder_object_lookup(uint32 connectorFlags, uint8 dacID)
2176 {
2177 	// used on older cards to take a guess at the encoder
2178 	// object
2179 
2180 	radeon_shared_info &info = *gInfo->shared_info;
2181 
2182 	uint32 ret = 0;
2183 
2184 	switch (connectorFlags) {
2185 		case ATOM_DEVICE_CRT1_SUPPORT:
2186 		case ATOM_DEVICE_TV1_SUPPORT:
2187 		case ATOM_DEVICE_TV2_SUPPORT:
2188 		case ATOM_DEVICE_CRT2_SUPPORT:
2189 		case ATOM_DEVICE_CV_SUPPORT:
2190 			switch (dacID) {
2191 				case 1:
2192 					if ((info.chipsetID == RADEON_RS400)
2193 						|| (info.chipsetID == RADEON_RS480))
2194 						ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
2195 					else if (info.chipsetID >= RADEON_RS600)
2196 						ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1;
2197 					else
2198 						ret = ENCODER_INTERNAL_DAC1_ENUM_ID1;
2199 					break;
2200 				case 2:
2201 					if (info.chipsetID >= RADEON_RS600)
2202 						ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1;
2203 					else {
2204 						ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
2205 					}
2206 					break;
2207 				case 3: // external dac
2208 					if (info.chipsetID >= RADEON_RS600)
2209 						ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
2210 					else
2211 						ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2212 					break;
2213 			}
2214 			break;
2215 		case ATOM_DEVICE_LCD1_SUPPORT:
2216 			if (info.chipsetID >= RADEON_RS600)
2217 				ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
2218 			else
2219 				ret = ENCODER_INTERNAL_LVDS_ENUM_ID1;
2220 			break;
2221 		case ATOM_DEVICE_DFP1_SUPPORT:
2222 			if ((info.chipsetID == RADEON_RS400)
2223 				|| (info.chipsetID == RADEON_RS480))
2224 				ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2225 			else if (info.chipsetID >= RADEON_RS600)
2226 				ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1;
2227 			else
2228 				ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1;
2229 			break;
2230 		case ATOM_DEVICE_LCD2_SUPPORT:
2231 		case ATOM_DEVICE_DFP2_SUPPORT:
2232 			if ((info.chipsetID == RADEON_RS600)
2233 				|| (info.chipsetID == RADEON_RS690)
2234 				|| (info.chipsetID == RADEON_RS740))
2235 				ret = ENCODER_INTERNAL_DDI_ENUM_ID1;
2236 			else if (info.chipsetID >= RADEON_RS600)
2237 				ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
2238 			else
2239 				ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
2240 			break;
2241 		case ATOM_DEVICE_DFP3_SUPPORT:
2242 			ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
2243 			break;
2244 	}
2245 
2246 	return ret;
2247 }
2248 
2249 
2250 uint32
2251 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags)
2252 {
2253 	switch (encoderID) {
2254 		case ENCODER_OBJECT_ID_INTERNAL_LVDS:
2255 		case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
2256 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
2257 		case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
2258 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2259 				return VIDEO_ENCODER_LVDS;
2260 			else
2261 				return VIDEO_ENCODER_TMDS;
2262 			break;
2263 		case ENCODER_OBJECT_ID_INTERNAL_DAC1:
2264 			return VIDEO_ENCODER_DAC;
2265 		case ENCODER_OBJECT_ID_INTERNAL_DAC2:
2266 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
2267 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
2268 			return VIDEO_ENCODER_TVDAC;
2269 		case ENCODER_OBJECT_ID_INTERNAL_DVO1:
2270 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
2271 		case ENCODER_OBJECT_ID_INTERNAL_DDI:
2272 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
2273 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
2274 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
2275 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
2276 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2277 				return VIDEO_ENCODER_LVDS;
2278 			else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
2279 				return VIDEO_ENCODER_DAC;
2280 			else
2281 				return VIDEO_ENCODER_TMDS;
2282 			break;
2283 		case ENCODER_OBJECT_ID_SI170B:
2284 		case ENCODER_OBJECT_ID_CH7303:
2285 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
2286 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
2287 		case ENCODER_OBJECT_ID_TITFP513:
2288 		case ENCODER_OBJECT_ID_VT1623:
2289 		case ENCODER_OBJECT_ID_HDMI_SI1930:
2290 		case ENCODER_OBJECT_ID_TRAVIS:
2291 		case ENCODER_OBJECT_ID_NUTMEG:
2292 			if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0)
2293 				return VIDEO_ENCODER_LVDS;
2294 			else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0)
2295 				return VIDEO_ENCODER_DAC;
2296 			else
2297 				return VIDEO_ENCODER_TMDS;
2298 			break;
2299 	}
2300 
2301 	return VIDEO_ENCODER_NONE;
2302 }
2303 
2304 
2305 bool
2306 encoder_is_external(uint32 encoderID)
2307 {
2308 	switch (encoderID) {
2309 		case ENCODER_OBJECT_ID_SI170B:
2310 		case ENCODER_OBJECT_ID_CH7303:
2311 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOA:
2312 		case ENCODER_OBJECT_ID_EXTERNAL_SDVOB:
2313 		case ENCODER_OBJECT_ID_TITFP513:
2314 		case ENCODER_OBJECT_ID_VT1623:
2315 		case ENCODER_OBJECT_ID_HDMI_SI1930:
2316 		case ENCODER_OBJECT_ID_TRAVIS:
2317 		case ENCODER_OBJECT_ID_NUTMEG:
2318 			return true;
2319 	}
2320 
2321 	return false;
2322 }
2323 
2324 
2325 bool
2326 encoder_is_dp_bridge(uint32 encoderID)
2327 {
2328 	switch (encoderID) {
2329 		case ENCODER_OBJECT_ID_TRAVIS:
2330 		case ENCODER_OBJECT_ID_NUTMEG:
2331 			return true;
2332 	}
2333 	return false;
2334 }
2335