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