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